diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9eea3a2e64ae25bc1f3f459c82ee5c7ee16f51f5..9f80cd261f75d6677ddf70f28331cd99f4fa7397 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -318,7 +318,7 @@ tests-and-coverage:
 
 
 build-documentation:
-  image: i10git.cs.fau.de:5005/pycodegen/pycodegen/documentation
+  image: i10git.cs.fau.de:5005/pycodegen/pycodegen/full
   stage: docs
   needs: []
   before_script:
@@ -328,6 +328,7 @@ build-documentation:
     - make html SPHINXOPTS="-W --keep-going"
   tags:
     - docker
+    - cuda11
   artifacts:
     paths:
       - docs/build/html
diff --git a/docs/.gitignore b/docs/.gitignore
index be765e19aae423d5341d8ea05a3a0d74ff16cf66..87cf4fd0072f0c2840e1decff692637984f6e15e 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,4 +1,4 @@
 build
 
 #   sphinx.ext.autosummary generated files
-**/autoapi
+**/generated
diff --git a/docs/Makefile b/docs/Makefile
index d0c3cbf1020d5c292abdedf27627c6abe25e2293..7720d146e574ad59bf65669f2c0acdcecc15e4c1 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -18,3 +18,8 @@ help:
 # "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
 %: Makefile
 	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+clean:
+	rm -rf source/reference/generated
+	rm -rf source/backend/generated
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
diff --git a/docs/source/_static/img/logo copy.png b/docs/source/_static/img/logo copy.png
deleted file mode 100644
index 784183cd932787cfce3cf6c38e77622f40699e8f..0000000000000000000000000000000000000000
Binary files a/docs/source/_static/img/logo copy.png and /dev/null differ
diff --git a/docs/source/_static/img/logo_large.svg b/docs/source/_static/img/logo_large.svg
deleted file mode 100644
index 8b4155d3a1aaa9bc002967137e732930109e192f..0000000000000000000000000000000000000000
--- a/docs/source/_static/img/logo_large.svg
+++ /dev/null
@@ -1,444 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="379.82614mm"
-   height="189.91307mm"
-   viewBox="0 0 1345.8407 672.92033"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.92.3 (2405546, 2018-03-11)"
-   sodipodi:docname="logo_large.svg"
-   inkscape:export-filename="/home/martin/code/pycodegen/pystencils/doc/img/github_repo_card.png"
-   inkscape:export-xdpi="85.599998"
-   inkscape:export-ydpi="85.599998">
-  <defs
-     id="defs4">
-    <inkscape:path-effect
-       effect="spiro"
-       id="path-effect4188"
-       is_visible="true" />
-    <inkscape:path-effect
-       effect="spiro"
-       id="path-effect4188-5"
-       is_visible="true" />
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4596">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4598" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4600" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4602" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4604" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4606" />
-    </filter>
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4608">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4610" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4612" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4614" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4616" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4618" />
-    </filter>
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4620">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4622" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4624" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4626" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4628" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4630" />
-    </filter>
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4632">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4634" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4636" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4638" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4640" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4642" />
-    </filter>
-    <inkscape:path-effect
-       effect="spiro"
-       id="path-effect4188-7"
-       is_visible="true" />
-    <inkscape:path-effect
-       effect="spiro"
-       id="path-effect4188-5-6"
-       is_visible="true" />
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4596-6">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4598-6" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4600-9" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4602-1" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4604-4" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4606-3" />
-    </filter>
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4620-1">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4622-1" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4624-4" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4626-8" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4628-5" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4630-7" />
-    </filter>
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4632-1">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4634-9" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4636-8" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4638-7" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4640-6" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4642-5" />
-    </filter>
-    <filter
-       y="-0.25"
-       height="1.5"
-       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
-       inkscape:menu="Shadows and Glows"
-       inkscape:label="Dark And Glow"
-       style="color-interpolation-filters:sRGB"
-       id="filter4608-0">
-      <feGaussianBlur
-         stdDeviation="5"
-         result="result6"
-         id="feGaussianBlur4610-2" />
-      <feComposite
-         result="result8"
-         in="SourceGraphic"
-         operator="atop"
-         in2="result6"
-         id="feComposite4612-5" />
-      <feComposite
-         result="result9"
-         operator="over"
-         in2="SourceAlpha"
-         in="result8"
-         id="feComposite4614-7" />
-      <feColorMatrix
-         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
-         result="result10"
-         id="feColorMatrix4616-6" />
-      <feBlend
-         in="result10"
-         mode="normal"
-         in2="result6"
-         id="feBlend4618-9" />
-    </filter>
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.70000001"
-     inkscape:cx="545.01294"
-     inkscape:cy="35.725386"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:window-width="3840"
-     inkscape:window-height="2061"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:window-maximized="1"
-     fit-margin-top="0"
-     fit-margin-left="0"
-     fit-margin-right="0"
-     fit-margin-bottom="0">
-    <inkscape:grid
-       type="xygrid"
-       id="grid4176"
-       originx="267.20477"
-       originy="315.17846" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(267.20477,-694.6203)">
-    <text
-       xml:space="preserve"
-       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.78659058px;line-height:125%;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, ';letter-spacing:0px;word-spacing:0px;fill:#252525;fill-opacity:1;stroke:none;stroke-width:4.34832382px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       x="159.99139"
-       y="964.43109"
-       id="text1392-1"
-       inkscape:export-xdpi="70.669998"
-       inkscape:export-ydpi="70.669998"><tspan
-         sodipodi:role="line"
-         id="tspan1390-1"
-         x="159.99139"
-         y="964.43109"
-         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:156.53968811px;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, Bold';fill:#252525;fill-opacity:1;stroke-width:4.34832382px">pystencils</tspan></text>
-    <g
-       id="g9986"
-       transform="matrix(4.1201463,0,0,4.1201463,-399.75066,866.02979)"
-       inkscape:export-xdpi="70.669998"
-       inkscape:export-ydpi="70.669998">
-      <path
-         inkscape:connector-curvature="0"
-         inkscape:original-d="M 60.891002,27.333516 H 118.64865"
-         inkscape:path-effect="#path-effect4188-7"
-         id="path4186-6"
-         d="M 60.891002,27.333516 H 118.64865"
-         style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.78799796;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.70388345" />
-      <path
-         sodipodi:nodetypes="cc"
-         inkscape:connector-curvature="0"
-         inkscape:original-d="M 89.922623,-0.47572315 C 31.237244,132.88729 89.846228,36.88339 89.846228,56.13594"
-         inkscape:path-effect="#path-effect4188-5-6"
-         id="path4186-3-9"
-         d="M 89.922623,-0.47572315 89.846228,56.13594"
-         style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.78799796;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.70388345" />
-      <circle
-         transform="matrix(0.21391721,0,0,0.21391721,27.733834,-23.442344)"
-         r="34.345188"
-         cy="108.02044"
-         cx="291.42902"
-         id="path4136-76"
-         style="opacity:1;fill:#e69f00;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4596-6)" />
-      <circle
-         transform="matrix(0.21391721,0,0,0.21391721,27.733834,-23.442344)"
-         r="34.345188"
-         cy="365.43817"
-         cx="290.41885"
-         id="path4136-6-0"
-         style="opacity:1;fill:#0072b2;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4620-1)" />
-      <circle
-         transform="matrix(0.21391721,0,0,0.21391721,27.733834,-23.442344)"
-         r="34.345188"
-         cy="236.72931"
-         cx="422.24377"
-         id="path4136-3-9"
-         style="opacity:1;fill:#999999;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4632-1)" />
-      <circle
-         transform="matrix(0.21391721,0,0,0.21391721,27.733834,-23.442344)"
-         r="34.345188"
-         cy="236.72931"
-         cx="155.56349"
-         id="path4136-7-0"
-         style="opacity:1;fill:#009e73;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4608-0)" />
-    </g>
-    <text
-       xml:space="preserve"
-       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.7668047px;line-height:125%;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, ';letter-spacing:0px;word-spacing:0px;fill:#252525;fill-opacity:0.70629368;stroke:none;stroke-width:1.09585059px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-       x="229.96391"
-       y="1071.713"
-       id="text1392-1-3"
-       inkscape:export-xdpi="70.669998"
-       inkscape:export-ydpi="70.669998"><tspan
-         sodipodi:role="line"
-         id="tspan1390-1-6"
-         x="229.96391"
-         y="1071.713"
-         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:62.0406723px;line-height:105.99999428%;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, Bold';fill:#252525;fill-opacity:0.70629368;stroke-width:1.09585059px">speed up stencil </tspan><tspan
-         sodipodi:role="line"
-         x="229.96391"
-         y="1137.4761"
-         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:62.0406723px;line-height:105.99999428%;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, Bold';fill:#252525;fill-opacity:0.70629368;stroke-width:1.09585059px"
-         id="tspan109">computations on</tspan><tspan
-         sodipodi:role="line"
-         x="229.96391"
-         y="1203.2393"
-         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:62.0406723px;line-height:105.99999428%;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, Bold';fill:#252525;fill-opacity:0.70629368;stroke-width:1.09585059px"
-         id="tspan107">numpy arrays</tspan></text>
-  </g>
-</svg>
diff --git a/docs/source/_static/img/pystencils-logo-dark.svg b/docs/source/_static/img/pystencils-logo-dark.svg
new file mode 100644
index 0000000000000000000000000000000000000000..aeb209218373402703529f3e318a9b58b2a67813
--- /dev/null
+++ b/docs/source/_static/img/pystencils-logo-dark.svg
@@ -0,0 +1,453 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="49.310894mm"
+   height="48.976913mm"
+   viewBox="0 0 49.310894 48.976913"
+   version="1.1"
+   id="svg1"
+   inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
+   sodipodi:docname="pystencils-logo-dark.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview1"
+     pagecolor="#ffffff"
+     bordercolor="#111111"
+     borderopacity="1"
+     inkscape:showpageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="1"
+     inkscape:deskcolor="#d1d1d1"
+     inkscape:document-units="mm"
+     showguides="true"
+     inkscape:lockguides="false"
+     showgrid="false"
+     inkscape:zoom="4"
+     inkscape:cx="73.125"
+     inkscape:cy="102.5"
+     inkscape:window-width="2560"
+     inkscape:window-height="1399"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       id="grid4"
+       units="mm"
+       originx="4.6554451"
+       originy="-0.83749382"
+       spacingx="0.99999998"
+       spacingy="1"
+       empcolor="#0099e5"
+       empopacity="0.30196078"
+       color="#0099e5"
+       opacity="0.14901961"
+       empspacing="5"
+       enabled="true"
+       visible="false" />
+    <sodipodi:guide
+       position="38.829266,-5.2751542"
+       orientation="1,0"
+       id="guide2"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="10.481264,-5.2751542"
+       orientation="1,0"
+       id="guide3"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="24.655266,8.8988453"
+       orientation="0,-1"
+       id="guide4"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="24.655266,-19.449154"
+       orientation="0,-1"
+       id="guide5"
+       inkscape:locked="false" />
+  </sodipodi:namedview>
+  <defs
+     id="defs1">
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect5"
+       is_visible="true"
+       lpeversion="0" />
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4608-0"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4610-2" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4612-5" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4614-7" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4616-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4618-9" />
+    </filter>
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4632-1"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4634-9" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4636-8" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4638-7" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4640-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4642-5" />
+    </filter>
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4620-1"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4622-1" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4624-4" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4626-8" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4628-5" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4630-7" />
+    </filter>
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4596-6"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4598-6" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4600-9" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4602-1" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4604-4" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4606-3" />
+    </filter>
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-5-6"
+       is_visible="true"
+       lpeversion="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-7"
+       is_visible="true"
+       lpeversion="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-5-6-3"
+       is_visible="true"
+       lpeversion="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-7-2"
+       is_visible="true"
+       lpeversion="0" />
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4608-0-5"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4610-2-5" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4612-5-4" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4614-7-7" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4616-6-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4618-9-5" />
+    </filter>
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4620-1-7"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4622-1-4" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4624-4-5" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4626-8-2" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4628-5-5" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4630-7-4" />
+    </filter>
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4596-6-3"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4598-6-0" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4600-9-7" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4602-1-8" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4604-4-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4606-3-8" />
+    </filter>
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4632-1-4"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4634-9-9" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4636-8-2" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4638-7-0" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4640-6-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4642-5-8" />
+    </filter>
+  </defs>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(4.6554452,-0.83749467)">
+    <g
+       id="g24"
+       transform="translate(1.812973e-4,-8.5216229e-5)">
+      <rect
+         style="display:inline;opacity:1;fill:#ffffff;fill-opacity:0.701961;stroke-width:0.409154"
+         id="rect1"
+         width="28.348"
+         height="1.396094"
+         x="5.825819"
+         y="19.277994"
+         inkscape:label="axis-H" />
+      <rect
+         style="opacity:1;fill:#ffffff;fill-opacity:0.701961;stroke-width:0.409154"
+         id="rect2"
+         width="28.348"
+         height="1.396094"
+         x="5.8020415"
+         y="-20.697866"
+         transform="rotate(90)"
+         inkscape:label="axis-V" />
+      <circle
+         transform="matrix(0.10711925,0,0,0.10711925,-10.838025,-5.3822253)"
+         r="34.345188"
+         cy="236.72931"
+         cx="155.56349"
+         id="path4136-7-0"
+         style="fill:#009e73;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4608-0-5)"
+         inkscape:label="circle-L" />
+      <circle
+         transform="matrix(0.10711925,0,0,0.10711925,-11.109448,-4.9954233)"
+         r="34.345188"
+         cy="365.43817"
+         cx="290.41885"
+         id="path4136-6-0"
+         style="fill:#0072b2;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4620-1-7)"
+         inkscape:label="circle-B" />
+      <circle
+         transform="matrix(0.10711925,0,0,0.10711925,-11.20464,-5.7690267)"
+         r="34.345188"
+         cy="108.02044"
+         cx="291.42902"
+         id="path4136-76"
+         style="fill:#e69f00;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4596-6-3)"
+         inkscape:label="circle-T" />
+      <circle
+         transform="matrix(0.10711925,0,0,0.10711925,-11.056616,-5.2185227)"
+         r="34.345188"
+         cy="236.72931"
+         cx="422.24377"
+         id="path4136-3-9"
+         style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4632-1-4)"
+         inkscape:label="circle-R" />
+    </g>
+    <path
+       style="font-weight:bold;font-size:9.525px;line-height:125%;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, Bold';letter-spacing:0px;word-spacing:0px;fill:#cccccc;stroke-width:0.264583px"
+       d="m -0.08344542,45.62341 c 0,-1.190625 -0.86677496,-2.124075 -1.88594988,-2.124075 -0.409575,0 -0.8001,0.13335 -1.114425,0.371475 -0.00953,-0.219075 -0.09525,-0.32385 -0.43815,-0.32385 h -0.676275 c -0.1809749,0 -0.4571999,0.01905 -0.4571999,0.36195 0,0.3429 0.28575,0.352425 0.4476749,0.352425 h 0.3429 v 4.78155 h -0.333375 c -0.1809749,0 -0.4571999,0.0095 -0.4571999,0.36195 0,0.3429 0.28575,0.352425 0.4476749,0.352425 h 1.476375 c 0.161925,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.276225,-0.36195 -0.4572,-0.36195 h -0.333375 V 47.37601 c 0.36195,0.314325 0.7239,0.381 1.000125,0.381 1.0477499,0 1.99072488,-0.9144 1.99072488,-2.1336 z m -0.78104996,0 c 0,0.8382 -0.60960002,1.419225 -1.22872492,1.419225 -0.676275,0 -0.97155,-0.771525 -0.97155,-1.190625 v -0.676275 c 0,-0.51435 0.504825,-0.962025 1.04775,-0.962025 0.6476999,0 1.15252492,0.6477 1.15252492,1.4097 z m 5.89597128,-1.7145 c 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 H 3.497951 c -0.17145,0 -0.447675,0.01905 -0.447675,0.352425 0,0.352425 0.2667,0.36195 0.447675,0.36195 h 0.1524 L 2.831201,46.74736 1.888226,44.261335 h 0.123825 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 H 0.92620106 c -0.18097499,0 -0.44767498,0.0095 -0.44767498,0.36195 0,0.3429 0.27622499,0.352425 0.44767498,0.352425 H 1.1643261 L 2.497826,47.62366 c -0.0381,0.104775 -0.238125,0.771525 -0.3429,0.981075 -0.1905,0.36195 -0.485775,0.581025 -0.66675,0.581025 0.00953,-0.0381 0.104775,-0.06668 0.104775,-0.20955 0,-0.276225 -0.200025,-0.47625 -0.4762499,-0.47625 -0.29527503,0 -0.47625003,0.200025 -0.47625003,0.47625 0,0.428625 0.34289999,0.8382 0.83819993,0.8382 0.9525,0 1.419225,-1.266825 1.457325,-1.3716 l 1.4192249,-4.181475 h 0.2286 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 z m 4.6196213,2.5527 c 0,-1.00965 -1.2477749,-1.228725 -1.5620999,-1.27635 l -0.962025,-0.17145 c -0.24765,-0.05715 -0.5048249,-0.161925 -0.5048249,-0.381 0,-0.219075 0.2952749,-0.447675 1.1048999,-0.447675 0.695325,0 0.828675,0.2286 0.85725,0.447675 0.00953,0.1905 0.0381,0.381 0.390525,0.381 0.3905249,0 0.4000499,-0.2286 0.4000499,-0.447675 v -0.6477 c 0,-0.180975 -0.01905,-0.447675 -0.3524249,-0.447675 -0.20955,0 -0.28575,0.08573 -0.32385,0.161925 -0.40005,-0.161925 -0.78105,-0.161925 -0.9525,-0.161925 -1.6287749,0 -1.8383249,0.81915 -1.8383249,1.16205 0,0.89535 1.0001249,1.08585 1.8954749,1.2192 0.4191,0.06668 1.133475,0.180975 1.133475,0.6096 0,0.32385 -0.333375,0.581025 -1.114425,0.581025 -0.409575,0 -0.89535,-0.09525 -1.1144249,-0.771525 -0.05715,-0.20955 -0.104775,-0.32385 -0.40005,-0.32385 -0.390525,0 -0.40005,0.2286 -0.40005,0.4572 v 0.89535 c 0,0.180975 0.00953,0.4572 0.352425,0.4572 0.09525,0 0.257175,0 0.381,-0.314325 0.4476749,0.295275 0.9143999,0.314325 1.1715749,0.314325 1.5335249,0 1.8383249,-0.828675 1.8383249,-1.2954 z m 4.8958458,-0.0095 c 0,-0.200025 0,-0.428625 -0.40005,-0.428625 -0.371475,0 -0.381,0.2286 -0.381,0.4191 -0.0095,0.51435 -0.485775,0.600075 -0.6858,0.600075 -0.638175,0 -0.638175,-0.43815 -0.638175,-0.638175 v -2.143125 h 1.4478 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 h -1.4478 v -0.6858 c 0,-0.20955 -0.0095,-0.447675 -0.390525,-0.447675 -0.390525,0 -0.40005,0.2286 -0.40005,0.447675 v 0.6858 h -0.733425 c -0.180975,0 -0.447675,0.01905 -0.447675,0.36195 0,0.3429 0.2667,0.352425 0.43815,0.352425 h 0.74295 v 2.19075 c 0,0.942975 0.66675,1.304925 1.39065,1.304925 0.7239,0 1.50495,-0.428625 1.50495,-1.304925 z m 5.153022,0.161925 c 0,-0.32385 -0.333375,-0.333375 -0.40005,-0.333375 -0.20955,0 -0.295275,0.0381 -0.381,0.24765 -0.1905,0.43815 -0.657225,0.51435 -0.89535,0.51435 -0.638175,0 -1.27635,-0.409575 -1.4478,-1.114425 h 2.676525 c 0.238125,0 0.447675,0 0.447675,-0.4191 0,-1.095375 -0.62865,-2.03835 -1.876425,-2.03835 -1.143,0 -2.07645,0.962025 -2.07645,2.143125 0,1.171575 0.97155,2.143125 2.2098,2.143125 1.2954,0 1.743075,-0.89535 1.743075,-1.143 z m -0.81915,-1.39065 H 16.58529 c 0.1524,-0.600075 0.6477,-1.038225 1.23825,-1.038225 0.43815,0 0.9525,0.20955 1.057275,1.038225 z m 6.257922,2.124075 c 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 h -0.333375 v -2.07645 c 0,-0.9906 -0.504825,-1.4097 -1.285875,-1.4097 -0.5334,0 -0.9144,0.219075 -1.143,0.40005 -0.0095,-0.238125 -0.0762,-0.352425 -0.447675,-0.352425 h -0.676275 c -0.180975,0 -0.447675,0.01905 -0.447675,0.36195 0,0.3429 0.28575,0.352425 0.43815,0.352425 h 0.3429 v 2.72415 h -0.333375 c -0.180975,0 -0.447675,0.0095 -0.447675,0.36195 0,0.3429 0.28575,0.352425 0.43815,0.352425 h 1.476375 c 0.161925,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.276225,-0.36195 -0.4572,-0.36195 H 21.928812 V 45.41386 c 0,-0.866775 0.6477,-1.20015 1.08585,-1.20015 0.447675,0 0.55245,0.238125 0.55245,0.74295 v 2.028825 h -0.28575 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.295275,0.352425 0.4572,0.352425 h 1.419225 c 0.1524,0 0.43815,-0.0095 0.43815,-0.352425 z m 4.58152,-0.733425 c 0,-0.32385 -0.333375,-0.333375 -0.40005,-0.333375 -0.180975,0 -0.295275,0.01905 -0.381,0.24765 -0.04763,0.1143 -0.238125,0.51435 -0.847725,0.51435 -0.74295,0 -1.381125,-0.619125 -1.381125,-1.419225 0,-0.428625 0.24765,-1.438275 1.438275,-1.438275 l 0.485775,0.0095 c 0.0095,0.381 0.219075,0.523875 0.47625,0.523875 0.2667,0 0.4953,-0.180975 0.4953,-0.4953 0,-0.7239 -1.00965,-0.752475 -1.457325,-0.752475 -1.647825,0 -2.22885,1.304925 -2.22885,2.15265 0,1.152525 0.904875,2.1336 2.11455,2.1336 1.362075,0 1.685925,-0.981075 1.685925,-1.143 z m 4.895846,0.733425 c 0,-0.352425 -0.28575,-0.36195 -0.4572,-0.36195 h -0.89535 V 44.00416 c 0,-0.3429 -0.06668,-0.4572 -0.447675,-0.4572 h -1.31445 c -0.17145,0 -0.4572,0.01905 -0.4572,0.352425 0,0.352425 0.28575,0.36195 0.4572,0.36195 h 0.97155 v 2.72415 h -1.04775 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.4572,0.352425 h 2.733675 c 0.17145,0 0.4572,-0.0095 0.4572,-0.352425 z m -1.31445,-4.886325 c 0,-0.295275 -0.238125,-0.5334 -0.542925,-0.5334 -0.3048,0 -0.542925,0.238125 -0.542925,0.5334 0,0.3048 0.238125,0.542925 0.542925,0.542925 0.3048,0 0.542925,-0.238125 0.542925,-0.542925 z m 6.429372,4.886325 c 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 h -1.133475 v -4.6482 c 0,-0.3429 -0.06668,-0.4572 -0.447675,-0.4572 h -1.46685 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.447675,0.352425 H 37.3593 v 4.391025 h -1.12395 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.447675,0.352425 h 3.057525 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 z m 4.924422,-0.885825 c 0,-1.00965 -1.247775,-1.228725 -1.5621,-1.27635 l -0.962025,-0.17145 c -0.24765,-0.05715 -0.504825,-0.161925 -0.504825,-0.381 0,-0.219075 0.295275,-0.447675 1.1049,-0.447675 0.695325,0 0.828675,0.2286 0.85725,0.447675 0.0095,0.1905 0.0381,0.381 0.390525,0.381 0.390525,0 0.40005,-0.2286 0.40005,-0.447675 v -0.6477 c 0,-0.180975 -0.01905,-0.447675 -0.352425,-0.447675 -0.20955,0 -0.28575,0.08573 -0.32385,0.161925 -0.40005,-0.161925 -0.78105,-0.161925 -0.9525,-0.161925 -1.628775,0 -1.838325,0.81915 -1.838325,1.16205 0,0.89535 1.000125,1.08585 1.895475,1.2192 0.4191,0.06668 1.133475,0.180975 1.133475,0.6096 0,0.32385 -0.333375,0.581025 -1.114425,0.581025 -0.409575,0 -0.89535,-0.09525 -1.114425,-0.771525 -0.05715,-0.20955 -0.104775,-0.32385 -0.40005,-0.32385 -0.390525,0 -0.40005,0.2286 -0.40005,0.4572 v 0.89535 c 0,0.180975 0.0095,0.4572 0.352425,0.4572 0.09525,0 0.257175,0 0.381,-0.314325 0.447675,0.295275 0.9144,0.314325 1.171575,0.314325 1.533525,0 1.838325,-0.828675 1.838325,-1.2954 z"
+       id="text1392-1"
+       aria-label="pystencils" />
+  </g>
+</svg>
diff --git a/docs/source/_static/img/pystencils-logo-light.svg b/docs/source/_static/img/pystencils-logo-light.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c59a25519edd719586d66f91b6c05ba14b3db9c3
--- /dev/null
+++ b/docs/source/_static/img/pystencils-logo-light.svg
@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="49.310894mm"
+   height="48.976913mm"
+   viewBox="0 0 49.310894 48.976913"
+   version="1.1"
+   id="svg1"
+   inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
+   sodipodi:docname="pystencils-logo-light.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview1"
+     pagecolor="#ffffff"
+     bordercolor="#111111"
+     borderopacity="1"
+     inkscape:showpageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="1"
+     inkscape:deskcolor="#d1d1d1"
+     inkscape:document-units="mm"
+     showguides="true"
+     inkscape:lockguides="false"
+     showgrid="false"
+     inkscape:zoom="2.8284271"
+     inkscape:cx="33.410796"
+     inkscape:cy="139.65359"
+     inkscape:window-width="2560"
+     inkscape:window-height="1399"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       id="grid4"
+       units="mm"
+       originx="4.6554451"
+       originy="-0.837491"
+       spacingx="0.99999998"
+       spacingy="1"
+       empcolor="#0099e5"
+       empopacity="0.30196078"
+       color="#0099e5"
+       opacity="0.14901961"
+       empspacing="5"
+       enabled="true"
+       visible="false" />
+    <sodipodi:guide
+       position="38.829267,-5.2751543"
+       orientation="1,0"
+       id="guide2"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="10.481264,-5.2751543"
+       orientation="1,0"
+       id="guide3"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="24.655266,8.8988446"
+       orientation="0,-1"
+       id="guide4"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="24.655266,-19.449154"
+       orientation="0,-1"
+       id="guide5"
+       inkscape:locked="false" />
+  </sodipodi:namedview>
+  <defs
+     id="defs1">
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect5"
+       is_visible="true"
+       lpeversion="0" />
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4608-0"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4610-2" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4612-5" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4614-7" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4616-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4618-9" />
+    </filter>
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4632-1"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4634-9" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4636-8" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4638-7" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4640-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4642-5" />
+    </filter>
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4620-1"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4622-1" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4624-4" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4626-8" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4628-5" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4630-7" />
+    </filter>
+    <filter
+       y="-0.17469697"
+       height="1.3493938"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4596-6"
+       x="-0.17469697"
+       width="1.3493938">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4598-6" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4600-9" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4602-1" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4604-4" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4606-3" />
+    </filter>
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-5-6"
+       is_visible="true"
+       lpeversion="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-7"
+       is_visible="true"
+       lpeversion="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-5-6-3"
+       is_visible="true"
+       lpeversion="0" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4188-7-2"
+       is_visible="true"
+       lpeversion="0" />
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4608-0-5"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4610-2-5" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4612-5-4" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4614-7-7" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4616-6-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4618-9-5" />
+    </filter>
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4620-1-7"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4622-1-4" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4624-4-5" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4626-8-2" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4628-5-5" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4630-7-4" />
+    </filter>
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4596-6-3"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4598-6-0" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4600-9-7" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4602-1-8" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4604-4-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4606-3-8" />
+    </filter>
+    <filter
+       y="-0.17469696"
+       height="1.3493939"
+       inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow"
+       inkscape:menu="Shadows and Glows"
+       inkscape:label="Dark And Glow"
+       style="color-interpolation-filters:sRGB"
+       id="filter4632-1-4"
+       x="-0.17469696"
+       width="1.3493939">
+      <feGaussianBlur
+         stdDeviation="5"
+         result="result6"
+         id="feGaussianBlur4634-9-9" />
+      <feComposite
+         result="result8"
+         in="SourceGraphic"
+         operator="atop"
+         in2="result6"
+         id="feComposite4636-8-2" />
+      <feComposite
+         result="result9"
+         operator="over"
+         in2="SourceAlpha"
+         in="result8"
+         id="feComposite4638-7-0" />
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
+         result="result10"
+         id="feColorMatrix4640-6-6" />
+      <feBlend
+         in="result10"
+         mode="normal"
+         in2="result6"
+         id="feBlend4642-5-8" />
+    </filter>
+  </defs>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(4.6554451,-0.83749467)">
+    <g
+       id="g25"
+       transform="translate(1.812973e-4,-8.5216229e-5)">
+      <g
+         id="g24">
+        <rect
+           style="display:inline;opacity:1;fill:#000000;fill-opacity:0.701961;stroke-width:0.409154"
+           id="rect1"
+           width="28.348"
+           height="1.396094"
+           x="5.825819"
+           y="19.277994"
+           inkscape:label="axis-H" />
+        <rect
+           style="opacity:1;fill:#000000;fill-opacity:0.701961;stroke-width:0.409154"
+           id="rect2"
+           width="28.348"
+           height="1.396094"
+           x="5.8020415"
+           y="-20.697866"
+           transform="rotate(90)"
+           inkscape:label="axis-V" />
+        <circle
+           transform="matrix(0.10711925,0,0,0.10711925,-10.838025,-5.3822253)"
+           r="34.345188"
+           cy="236.72931"
+           cx="155.56349"
+           id="path4136-7-0"
+           style="fill:#009e73;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4608-0-5)"
+           inkscape:label="circle-L" />
+        <circle
+           transform="matrix(0.10711925,0,0,0.10711925,-11.109448,-4.9954233)"
+           r="34.345188"
+           cy="365.43817"
+           cx="290.41885"
+           id="path4136-6-0"
+           style="fill:#0072b2;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4620-1-7)"
+           inkscape:label="circle-B" />
+        <circle
+           transform="matrix(0.10711925,0,0,0.10711925,-11.20464,-5.7690267)"
+           r="34.345188"
+           cy="108.02044"
+           cx="291.42902"
+           id="path4136-76"
+           style="fill:#e69f00;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4596-6-3)"
+           inkscape:label="circle-T" />
+        <circle
+           transform="matrix(0.10711925,0,0,0.10711925,-11.056616,-5.2185227)"
+           r="34.345188"
+           cy="236.72931"
+           cx="422.24377"
+           id="path4136-3-9"
+           style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4632-1-4)"
+           inkscape:label="circle-R" />
+      </g>
+      <path
+         style="font-weight:bold;font-size:9.525px;line-height:125%;font-family:'Latin Modern Mono Light';-inkscape-font-specification:'Latin Modern Mono Light, Bold';letter-spacing:0px;word-spacing:0px;fill:#252525;stroke-width:0.264583px"
+         d="m -0.08362661,45.623494 c 0,-1.190625 -0.86677497,-2.124075 -1.88594989,-2.124075 -0.409575,0 -0.8001,0.13335 -1.114425,0.371475 -0.00953,-0.219075 -0.09525,-0.32385 -0.43815,-0.32385 h -0.6762749 c -0.180975,0 -0.4572,0.01905 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.447675,0.352425 h 0.3428999 v 4.781549 h -0.3333749 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.447675,0.352425 h 1.4763749 c 0.161925,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.276225,-0.36195 -0.4572,-0.36195 h -0.333375 v -1.666874 c 0.36195,0.314325 0.7239,0.381 1.000125,0.381 1.0477499,0 1.99072489,-0.9144 1.99072489,-2.1336 z m -0.78104997,0 c 0,0.8382 -0.60960002,1.419225 -1.22872492,1.419225 -0.676275,0 -0.97155,-0.771525 -0.97155,-1.190625 v -0.676275 c 0,-0.51435 0.504825,-0.962025 1.04775,-0.962025 0.6476999,0 1.15252492,0.6477 1.15252492,1.4097 z m 5.89597128,-1.7145 c 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 H 3.4977698 c -0.17145,0 -0.447675,0.01905 -0.447675,0.352425 0,0.352425 0.2667,0.36195 0.447675,0.36195 h 0.1524 l -0.81915,2.486025 -0.942975,-2.486025 h 0.123825 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 H 0.92601987 c -0.180975,0 -0.44767499,0.0095 -0.44767499,0.36195 0,0.3429 0.27622499,0.352425 0.44767499,0.352425 H 1.1641449 l 1.3334999,3.362325 c -0.0381,0.104775 -0.238125,0.771525 -0.3429,0.981075 -0.1905,0.361949 -0.485775,0.581024 -0.66675,0.581024 0.00953,-0.0381 0.104775,-0.06667 0.104775,-0.20955 0,-0.276224 -0.200025,-0.476249 -0.4762499,-0.476249 -0.29527503,0 -0.47625002,0.200025 -0.47625002,0.476249 0,0.428625 0.34289998,0.8382 0.83819992,0.8382 0.9525,0 1.419225,-1.266824 1.457325,-1.371599 l 1.4192249,-4.181475 h 0.2286 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 z m 4.6196213,2.5527 c 0,-1.00965 -1.2477749,-1.228725 -1.5620999,-1.27635 l -0.962025,-0.17145 c -0.24765,-0.05715 -0.5048249,-0.161925 -0.5048249,-0.381 0,-0.219075 0.2952749,-0.447675 1.1048999,-0.447675 0.695325,0 0.828675,0.2286 0.85725,0.447675 0.00953,0.1905 0.0381,0.381 0.390525,0.381 0.3905249,0 0.4000499,-0.2286 0.4000499,-0.447675 v -0.6477 c 0,-0.180975 -0.01905,-0.447675 -0.3524249,-0.447675 -0.20955,0 -0.28575,0.08573 -0.32385,0.161925 -0.40005,-0.161925 -0.78105,-0.161925 -0.9525,-0.161925 -1.6287749,0 -1.8383249,0.81915 -1.8383249,1.16205 0,0.89535 1.0001249,1.08585 1.8954749,1.2192 0.4191,0.06667 1.133475,0.180975 1.133475,0.6096 0,0.32385 -0.333375,0.581025 -1.114425,0.581025 -0.409575,0 -0.89535,-0.09525 -1.1144249,-0.771525 -0.05715,-0.20955 -0.104775,-0.32385 -0.40005,-0.32385 -0.390525,0 -0.40005,0.2286 -0.40005,0.4572 v 0.89535 c 0,0.180975 0.00953,0.4572 0.352425,0.4572 0.09525,0 0.257175,0 0.381,-0.314325 0.4476749,0.295275 0.9143999,0.314325 1.1715749,0.314325 1.5335249,0 1.8383249,-0.828675 1.8383249,-1.2954 z m 4.895846,-0.0095 c 0,-0.200025 0,-0.428625 -0.40005,-0.428625 -0.371475,0 -0.381,0.2286 -0.381,0.4191 -0.0095,0.51435 -0.485775,0.600075 -0.6858,0.600075 -0.638175,0 -0.638175,-0.43815 -0.638175,-0.638175 v -2.143125 h 1.4478 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 h -1.4478 v -0.6858 c 0,-0.20955 -0.0095,-0.447675 -0.390525,-0.447675 -0.390525,0 -0.40005,0.2286 -0.40005,0.447675 v 0.6858 h -0.733425 c -0.180975,0 -0.447675,0.01905 -0.447675,0.36195 0,0.3429 0.2667,0.352425 0.43815,0.352425 h 0.74295 v 2.19075 c 0,0.942975 0.66675,1.304925 1.39065,1.304925 0.7239,0 1.50495,-0.428625 1.50495,-1.304925 z m 5.153022,0.161925 c 0,-0.32385 -0.333375,-0.333375 -0.40005,-0.333375 -0.20955,0 -0.295275,0.0381 -0.381,0.24765 -0.1905,0.43815 -0.657225,0.51435 -0.89535,0.51435 -0.638175,0 -1.27635,-0.409575 -1.4478,-1.114425 h 2.676525 c 0.238125,0 0.447675,0 0.447675,-0.4191 0,-1.095375 -0.62865,-2.03835 -1.876425,-2.03835 -1.143,0 -2.07645,0.962025 -2.07645,2.143125 0,1.171575 0.97155,2.143125 2.2098,2.143125 1.2954,0 1.743075,-0.89535 1.743075,-1.143 z m -0.81915,-1.39065 h -2.295525 c 0.1524,-0.600075 0.6477,-1.038225 1.23825,-1.038225 0.43815,0 0.9525,0.20955 1.057275,1.038225 z m 6.257921,2.124075 c 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 h -0.333375 v -2.07645 c 0,-0.9906 -0.504824,-1.4097 -1.285874,-1.4097 -0.5334,0 -0.9144,0.219075 -1.143,0.40005 -0.0095,-0.238125 -0.0762,-0.352425 -0.447675,-0.352425 h -0.676275 c -0.180975,0 -0.447675,0.01905 -0.447675,0.36195 0,0.3429 0.28575,0.352425 0.43815,0.352425 h 0.3429 v 2.72415 h -0.333375 c -0.180975,0 -0.447675,0.0095 -0.447675,0.36195 0,0.3429 0.28575,0.352425 0.43815,0.352425 h 1.476375 c 0.161925,0 0.447675,-0.0095 0.447675,-0.352425 0,-0.352425 -0.276225,-0.36195 -0.4572,-0.36195 h -0.333375 v -1.571625 c 0,-0.866775 0.6477,-1.20015 1.08585,-1.20015 0.447675,0 0.55245,0.238125 0.55245,0.74295 v 2.028825 h -0.28575 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.295275,0.352425 0.4572,0.352425 h 1.419224 c 0.1524,0 0.43815,-0.0095 0.43815,-0.352425 z m 4.58152,-0.733425 c 0,-0.32385 -0.333375,-0.333375 -0.40005,-0.333375 -0.180975,0 -0.295275,0.01905 -0.381,0.24765 -0.04763,0.1143 -0.238125,0.51435 -0.847725,0.51435 -0.74295,0 -1.381125,-0.619125 -1.381125,-1.419225 0,-0.428625 0.24765,-1.438275 1.438275,-1.438275 l 0.485775,0.0095 c 0.0095,0.381 0.219075,0.523875 0.47625,0.523875 0.2667,0 0.4953,-0.180975 0.4953,-0.4953 0,-0.7239 -1.00965,-0.752475 -1.457325,-0.752475 -1.647825,0 -2.228849,1.304925 -2.228849,2.15265 0,1.152525 0.904874,2.1336 2.114549,2.1336 1.362075,0 1.685925,-0.981075 1.685925,-1.143 z m 4.895847,0.733425 c 0,-0.352425 -0.28575,-0.36195 -0.4572,-0.36195 h -0.89535 v -2.981325 c 0,-0.3429 -0.06667,-0.4572 -0.447675,-0.4572 h -1.31445 c -0.17145,0 -0.4572,0.01905 -0.4572,0.352425 0,0.352425 0.28575,0.36195 0.4572,0.36195 h 0.97155 v 2.72415 h -1.04775 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.4572,0.352425 h 2.733675 c 0.17145,0 0.4572,-0.0095 0.4572,-0.352425 z m -1.31445,-4.886325 c 0,-0.295275 -0.238125,-0.5334 -0.542925,-0.5334 -0.3048,0 -0.542925,0.238125 -0.542925,0.5334 0,0.3048 0.238125,0.542925 0.542925,0.542925 0.3048,0 0.542925,-0.238125 0.542925,-0.542925 z m 6.429372,4.886325 c 0,-0.352425 -0.2667,-0.36195 -0.447675,-0.36195 h -1.133475 v -4.6482 c 0,-0.3429 -0.06667,-0.4572 -0.447675,-0.4572 h -1.46685 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.447675,0.352425 h 1.133475 v 4.391025 h -1.12395 c -0.180975,0 -0.4572,0.0095 -0.4572,0.36195 0,0.3429 0.28575,0.352425 0.447675,0.352425 h 3.057525 c 0.17145,0 0.447675,-0.0095 0.447675,-0.352425 z m 4.924422,-0.885825 c 0,-1.00965 -1.247775,-1.228725 -1.5621,-1.27635 l -0.962025,-0.17145 c -0.24765,-0.05715 -0.504825,-0.161925 -0.504825,-0.381 0,-0.219075 0.295275,-0.447675 1.1049,-0.447675 0.695325,0 0.828675,0.2286 0.85725,0.447675 0.0095,0.1905 0.0381,0.381 0.390525,0.381 0.390525,0 0.40005,-0.2286 0.40005,-0.447675 v -0.6477 c 0,-0.180975 -0.01905,-0.447675 -0.352425,-0.447675 -0.20955,0 -0.28575,0.08573 -0.32385,0.161925 -0.40005,-0.161925 -0.78105,-0.161925 -0.9525,-0.161925 -1.628775,0 -1.838325,0.81915 -1.838325,1.16205 0,0.89535 1.000125,1.08585 1.895475,1.2192 0.4191,0.06667 1.133475,0.180975 1.133475,0.6096 0,0.32385 -0.333375,0.581025 -1.114425,0.581025 -0.409575,0 -0.89535,-0.09525 -1.114425,-0.771525 -0.05715,-0.20955 -0.104775,-0.32385 -0.40005,-0.32385 -0.390525,0 -0.40005,0.2286 -0.40005,0.4572 v 0.89535 c 0,0.180975 0.0095,0.4572 0.352425,0.4572 0.09525,0 0.257175,0 0.381,-0.314325 0.447675,0.295275 0.9144,0.314325 1.171575,0.314325 1.533525,0 1.838325,-0.828675 1.838325,-1.2954 z"
+         id="text1392-1"
+         inkscape:label="text1392-1"
+         aria-label="pystencils" />
+    </g>
+  </g>
+</svg>
diff --git a/docs/source/backend/ast.rst b/docs/source/backend/ast.rst
index 84ccb01f3911338870ff16ba028018b07c37cdad..409ae164a629f4ec3b0c0cd6d4b43cda5b4018cb 100644
--- a/docs/source/backend/ast.rst
+++ b/docs/source/backend/ast.rst
@@ -20,7 +20,7 @@ Base Classes
 .. module:: pystencils.backend.ast.astnode
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
     :template: autosummary/entire_class.rst
 
@@ -34,7 +34,7 @@ Structural Nodes
 .. module:: pystencils.backend.ast.structural
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
     :template: autosummary/entire_class.rst
 
@@ -55,7 +55,7 @@ Expressions
 .. module:: pystencils.backend.ast.expressions
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
     :template: autosummary/entire_class.rst
 
@@ -108,7 +108,7 @@ SIMD Nodes
 .. module:: pystencils.backend.ast.vector
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
     :template: autosummary/entire_class.rst
 
@@ -123,7 +123,7 @@ Utility
 .. currentmodule:: pystencils.backend.ast
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     expressions.evaluate_expression
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 9a4592e2ed194fc7d1d73f6351e2223c229fc1ff..e88859b99d6ad08b1f6358e31ad0f8b5ff1852f5 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -4,7 +4,6 @@ import re
 from pystencils import __version__ as pystencils_version
 
 project = "pystencils"
-html_logo = "_static/img/logo.png"
 html_title = "pystencils Documentation"
 
 copyright = (
@@ -33,9 +32,9 @@ extensions = [
     "sphinx.ext.mathjax",
     "sphinx.ext.napoleon",
     "sphinx.ext.inheritance_diagram",
-    "nbsphinx",
     "sphinxcontrib.bibtex",
     "sphinx_autodoc_typehints",
+    "myst_nb",
 ]
 
 templates_path = ["_templates"]
@@ -49,6 +48,7 @@ intersphinx_mapping = {
     "numpy": ("https://docs.scipy.org/doc/numpy/", None),
     "matplotlib": ("https://matplotlib.org/", None),
     "sympy": ("https://docs.sympy.org/latest/", None),
+    "cupy": ("https://docs.cupy.dev/en/stable/", None),
 }
 
 # -- Options for inheritance diagrams-----------------------------------------
@@ -57,18 +57,33 @@ inheritance_graph_attrs = {
     "bgcolor": "white",
 }
 
+# -- Options for MyST / MyST-NB ----------------------------------------------
+
+nb_execution_mode = "off"  # do not execute notebooks by default
+
+myst_enable_extensions = [
+    "dollarmath",
+    "colon_fence",
+]
+
 # -- Options for HTML output -------------------------------------------------
 
-html_theme = "furo"
+html_theme = "sphinx_book_theme"
 html_static_path = ["_static"]
 html_css_files = [
-    'css/fixtables.css',
+    "css/fixtables.css",
 ]
+html_theme_options = {
+    "logo": {
+        "image_light": "_static/img/pystencils-logo-light.svg",
+        "image_dark": "_static/img/pystencils-logo-dark.svg",
+    }
+}
 
 # NbSphinx configuration
 
-nbsphinx_execute = 'never'
-nbsphinx_codecell_lexer = 'python3'
+nbsphinx_execute = "never"
+nbsphinx_codecell_lexer = "python3"
 
 #   BibTex
-bibtex_bibfiles = ['pystencils.bib']
+bibtex_bibfiles = ["pystencils.bib"]
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 868fbc036906e9f79caa8378c298c6ca0b86e34e..66582cb4b6e847fc6b3022c1726257d866b3ba85 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -2,15 +2,6 @@
 pystencils v2.0-dev Documentation
 #################################
 
-.. toctree::
-   :maxdepth: 1
-   :hidden:
-   
-   tutorials/index
-   reference/index
-   migration
-   backend/index
-
 .. note::
    You are currently viewing the documentation pages for the development revision |release|
    of pystencils 2.0.
@@ -39,7 +30,7 @@ Its features include:
   and take control of numerical precision using the `versatile type system <page_type_system>`.
 - **Kernel Description:** Derive and optimize stencil-based update rules using a symbolic abstraction
   of numerical `fields <page_symbolic_language>`.
-- **Code Generation:** `Generate and compile <page_kernel_creation>` high-performance parallel kernels for CPUs and GPUs.
+- **Code Generation:** `Generate and compile <guide_kernelcreation>` high-performance parallel kernels for CPUs and GPUs.
   Accelerate your kernels on multicore CPUs using the automatic OpenMP parallelization
   and make full use of your cores' SIMD units through the highly configurable vectorizer.
 - **Rapid Prototyping:** Run your numerical solvers on `NumPy <https://numpy.org>`_ and `CuPy <https://cupy.dev>`_ arrays
@@ -50,32 +41,56 @@ Its features include:
   such as `waLBerla`_ to build massively parallel simulations.
 
 
-Contents
---------
+.. .. card:: Getting Started: Our Tutorials
+..    :link: page_tutorials
+..    :link-type: ref
 
-.. card:: Getting Started: Our Tutorials
-   :link: page_tutorials
-   :link-type: ref
+..    New to *pystencils*? Check out our set of tutorials to quickly and interactively learn the basics.
 
-   New to *pystencils*? Check out our set of tutorials to quickly and interactively learn the basics.
+.. .. card:: Reference Guide and APIs
+..    :link: page_api
+..    :link-type: ref
 
-.. card:: Reference Guide and APIs
-   :link: page_api
-   :link-type: ref
+..    Get an overview of *pystencils*' APIs for mathematical modelling and code generation.
 
-   Get an overview of *pystencils*' APIs for mathematical modelling and code generation.
+.. .. card:: Migration Guide: 1.3.x to 2.0
+..    :link: page_v2_migration
+..    :link-type: ref
 
-.. card:: Migration Guide: 1.3.x to 2.0
-   :link: page_v2_migration
-   :link-type: ref
+..    Find advice on migrating your code from *pystencils 1.3.x* to *pystencils 2.0*
 
-   Find advice on migrating your code from *pystencils 1.3.x* to *pystencils 2.0*
+.. .. card:: Developers's Reference: Code Generation Backend
+..    :link: page_codegen_backend
+..    :link-type: ref
 
-.. card:: Developers's Reference: Code Generation Backend
-   :link: page_codegen_backend
-   :link-type: ref
+..    Dive deep into the core of pystencils' code generation engine.
 
-   Dive deep into the core of pystencils' code generation engine.
+Topics
+------
+
+.. toctree::
+   :maxdepth: 1
+   :caption: Getting Started
+
+   installation
+   tutorials/index
+
+.. toctree::
+   :maxdepth: 1
+   :caption: Reference Guides
+
+   reference/symbolic_language
+   reference/kernelcreation
+   reference/gpu_kernels
+   reference/types
+   reference/api/index
+
+.. toctree::
+   :maxdepth: 1
+   :caption: Advanced
+
+   migration
+   backend/index
 
 Projects using pystencils
 -------------------------
diff --git a/docs/source/installation.md b/docs/source/installation.md
new file mode 100644
index 0000000000000000000000000000000000000000..cea0acd2feba1c45f2e73b0d52292a92aaa28d07
--- /dev/null
+++ b/docs/source/installation.md
@@ -0,0 +1,55 @@
+(_installation)=
+# Setup and Installation
+
+## Install pystencils
+
+There are two ways to install the latest development version of pystencils 2.0.
+You can either install it directly from our git repository:
+
+```bash
+pip install "git+https://i10git.cs.fau.de/pycodegen/pystencils.git@v2.0-dev"
+```
+
+Or clone the repository locally and perform an editable install:
+
+```bash
+git clone -b v2.0-dev https://i10git.cs.fau.de/pycodegen/pystencils.git
+pip install -e pystencils
+```
+
+### Feature Groups
+
+In both cases, you can add a set of optional features to your installation by listing them
+in square brackets (e.g. `pip install -e pystencils[feature1, feature2]`).
+The following feature sets are available:
+
+- `interactive` (**recommended**): Install dependencies for using pystencils interactively from
+  within Jupyter notebooks.
+  Setting this flag will cause pip to install `jupyter`, `matplotlib`, and `graphviz`, among others, alongside pystencils.
+- `alltrafos` (**recommended**): Install dependencies to enable a wider set of code transformation.
+  These include [islpy](https://pypi.org/project/islpy/) for polyhedral loop transformations,
+  and [py-cpuinfo](https://pypi.org/project/py-cpuinfo/) for detecting the current hardware in order
+  to select optimal vector instructions.
+- `use_cython`: Install [Cython](https://cython.org/), which is used internally by pystencils
+  to accelerate the setup of boundary conditions.
+
+:::{dropdown} For Developers
+
+If you are developing pystencils, we recommend you perform an editable install of your
+local clone of the repository, with all optional features:
+```bash
+pip install -e pystencils[alltrafos,interactive,use_cython,doc,tests]
+```
+
+This includes the additional feature groups `doc`, which contains all dependencies required
+to build this documentation, and `tests`, which adds `flake8` for code style checking,
+`mypy` for static type checking, and `pytest` plus plugins for running the test suite.
+:::
+
+### For Nvidia GPUs
+
+If you have an Nvidia graphics processor and CUDA installed, you can use pystencils to directly compile
+and execute kernels running on your GPU.
+This requires a working installation of [cupy](https://cupy.dev).
+Please refer to the cupy's [installation manual](https://docs.cupy.dev/en/stable/install.html)
+for details about installing cupy.
diff --git a/docs/source/reference/api/codegen.rst b/docs/source/reference/api/codegen.rst
new file mode 100644
index 0000000000000000000000000000000000000000..6418f32f6fe6d78267a373150fe7a2257c5e0b97
--- /dev/null
+++ b/docs/source/reference/api/codegen.rst
@@ -0,0 +1,29 @@
+Code Generator and Configuration
+================================
+
+.. module:: pystencils.kernelcreation
+
+.. autosummary::
+  :toctree: generated
+  :nosignatures:
+
+  create_kernel
+
+.. module:: pystencils.config
+
+.. autosummary::
+  :toctree: generated
+  :nosignatures:
+  :template: autosummary/entire_class.rst
+
+  CreateKernelConfig
+  CpuOptimConfig
+  OpenMpConfig
+  VectorizationConfig
+  GpuIndexingConfig
+
+.. autosummary::
+  :toctree: generated
+  :nosignatures:
+
+  AUTO
\ No newline at end of file
diff --git a/docs/source/reference/field.rst b/docs/source/reference/api/field.rst
similarity index 92%
rename from docs/source/reference/field.rst
rename to docs/source/reference/api/field.rst
index 7ad7dafee97d86c1ee0b0da1883800b40f844a7f..79cc12a3a883906a0dd6a2f27d50047344e4c770 100644
--- a/docs/source/reference/field.rst
+++ b/docs/source/reference/api/field.rst
@@ -14,7 +14,7 @@ Creating Fields
 ---------------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     fields
@@ -30,7 +30,7 @@ Name and Element Type
 ^^^^^^^^^^^^^^^^^^^^^
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
 
     Field.name
     Field.dtype
@@ -40,7 +40,7 @@ Dimensionality, Shape, and Memory Layout
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     
     Field.ndim
     Field.values_per_cell
@@ -58,7 +58,7 @@ Accessing Field Entries
 -----------------------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     Field.center
diff --git a/docs/source/reference/api/index.rst b/docs/source/reference/api/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b19c6303eb578f4b621febe507519ae3822df20a
--- /dev/null
+++ b/docs/source/reference/api/index.rst
@@ -0,0 +1,13 @@
+***
+API
+***
+
+Modules
+=======
+
+.. toctree::
+    :maxdepth: 1
+
+    field
+    sympyextensions
+    codegen
diff --git a/docs/source/reference/sympyextensions.rst b/docs/source/reference/api/sympyextensions.rst
similarity index 93%
rename from docs/source/reference/sympyextensions.rst
rename to docs/source/reference/api/sympyextensions.rst
index 98b6e35938f5362ef9b1c8ac2ad389ac707e692f..d377f998ea5d52189007b7c45f6de2f0d92e1258 100644
--- a/docs/source/reference/sympyextensions.rst
+++ b/docs/source/reference/api/sympyextensions.rst
@@ -7,7 +7,7 @@ Symbol Factory
 --------------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     SymbolCreator
@@ -17,7 +17,7 @@ Functions
 ---------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     math.prod
@@ -31,7 +31,7 @@ Expression Analysis
 -------------------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     math.is_constant
@@ -46,7 +46,7 @@ Expression Rewriting and Simplifications
 ----------------------------------------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     math.remove_small_floats
@@ -78,7 +78,7 @@ Integer Operations
 ------------------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
     :template: autosummary/sympy_class.rst
 
diff --git a/docs/source/reference/gpu_kernels.md b/docs/source/reference/gpu_kernels.md
new file mode 100644
index 0000000000000000000000000000000000000000..1e9456bf7e22e14a4470c737af91b0dc1a5d949d
--- /dev/null
+++ b/docs/source/reference/gpu_kernels.md
@@ -0,0 +1,229 @@
+---
+jupytext:
+  formats: md:myst
+  text_representation:
+    extension: .md
+    format_name: myst
+    format_version: 0.13
+    jupytext_version: 1.16.4
+kernelspec:
+  display_name: Python 3 (ipykernel)
+  language: python
+  name: python3
+mystnb:
+  execution_mode: cache
+---
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+
+import sympy as sp
+import pystencils as ps
+import numpy as np
+import matplotlib.pyplot as plt
+```
+
+(guide_gpukernels)=
+# Pystencils for GPUs
+
+Pystencils offers code generation for Nvidia GPUs using the CUDA programming model,
+as well as just-in-time compilation and execution of CUDA kernels from within Python
+based on the [cupy] library.w
+This section's objective is to give a detailed introduction into the creation of
+GPU kernels with pystencils.
+
+## Generate, Compile and Run CUDA Kernels
+
+In order to obtain a CUDA implementation of a symbolic kernel, naught more is required
+than setting the {any}`target <CreateKernelConfig.target>` code generator option to
+{any}`Target.CUDA`:
+
+```{code-cell} ipython3
+f, g = ps.fields("f, g: float64[3D]")
+update = ps.Assignment(f.center(), 2 * g.center())
+
+cfg = ps.CreateKernelConfig(target=ps.Target.CUDA)
+kernel = ps.create_kernel(update, cfg)
+
+ps.inspect(kernel)
+```
+
+The `kernel` object returned by the code generator in above snippet is an instance
+of the {py:class}`GpuKernelFunction` class.
+It extends {py:class}`KernelFunction` with some GPU-specific information.
+In particular, it defines the {any}`threads_range <GpuKernelFunction.threads_range>`
+property, which tells us how many threads the kernel is expecting to be executed with:
+
+```{code-cell} ipython3
+kernel.threads_range
+```
+
+If a GPU is available and [CuPy][cupy] is installed in the current environment,
+the kernel can be compiled and run immediately.
+To execute the kernel, a {any}`cupy.ndarray` has to be passed for each field.
+
+:::{note}
+[CuPy][cupy] is a Python library for numerical computations on GPU arrays,
+which operates much in the same way that [NumPy][numpy] works on CPU arrays.
+Cupy and NumPy expose nearly the same APIs for array operations;
+the difference being that CuPy allocates all its arrays on the GPU
+and performs its operations as CUDA kernels.
+Also, CuPy exposes a just-in-time-compiler for GPU kernels, which internally calls [nvcc].
+In pystencils, we use CuPy both to compile and provide executable kernels on-demand from within Python code,
+and to allocate and manage the data these kernels can be executed on.
+
+For more information on CuPy, refer to [their documentation][cupy-docs].
+:::
+
+```{code-cell} ipython3
+:tags: [raises-exception]
+import cupy as cp
+
+rng = cp.random.default_rng(seed=42)
+f_arr = rng.random((16, 16, 16))
+g_arr = cp.zeros_like(f_arr)
+
+kfunc = kernel.compile()
+kfunc(f=f_arr, g=g_arr)
+```
+
+### Modifying the Launch Grid
+
+The `kernel.compile()` invocation in the above code produces a {any}`CupyKernelWrapper` callable object.
+This object holds the kernel's launch grid configuration
+(i.e. the number of thread blocks, and the number of threads per block.)
+Pystencils specifies a default value for the block size and if possible, 
+the number of blocks is automatically inferred in order to cover the entire iteration space.
+In addition, the wrapper's interface allows us to customize the GPU launch grid,
+by manually setting both the number of threads per block, and the number of blocks on the grid:
+
+```{code-cell} ipython3
+kfunc.block_size = (16, 8, 8)
+kfunc.num_blocks = (1, 2, 2)
+```
+
+For most kernels, setting only the `block_size` is sufficient since pystencils will
+automatically compute the number of blocks;
+for exceptions to this, see [](#manual_launch_grids).
+If `num_blocks` is set manually and the launch grid thus specified is too small, only
+a part of the iteration space will be traversed by the kernel;
+similarily, if it is too large, it will cause any threads working outside of the iteration bounds to idle.
+
+(manual_launch_grids)=
+### Manual Launch Grids and Non-Cuboid Iteration Patterns
+
+In some cases, it will be unavoidable to set the launch grid size manually;
+especially if the code generator is unable to automatically determine the size of the
+iteration space.
+An example for this is the triangular iteration previously described in the [Kernel Creation Guide](#example_triangular_iteration).
+Let's set it up once more:
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+
+def _draw_ispace(f_arr):
+    n, m = f_arr.shape
+    fig, ax = plt.subplots()
+    
+    ax.set_xticks(np.arange(0, m, 4))
+    ax.set_yticks(np.arange(0, n, 4))
+    # ax.set_xticklabels([])
+    # ax.set_yticklabels([])
+
+    ax.set_xticks(np.arange(-.5, m, 1), minor=True)
+    ax.set_yticks(np.arange(-.5, n, 1), minor=True)
+    
+    ax.grid(which="minor", linewidth=2)
+    ax.tick_params(which='minor', bottom=False, left=False)
+    
+    ax.imshow(f_arr, interpolation="none", aspect="equal", origin="lower")
+```
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+
+f = ps.fields("f: float64[2D]")
+assignments = [
+    ps.Assignment(f(0), 1)
+]
+```
+
+```{code-cell} ipython3
+y = ps.DEFAULTS.spatial_counters[0]
+cfg = ps.CreateKernelConfig(
+    target=ps.Target.CUDA,
+    iteration_slice=ps.make_slice[:, y:]
+)
+    
+kernel = ps.create_kernel(assignments, cfg).compile()
+```
+
+This warns us that the threads range could not be determined automatically.
+We can disable this warning by setting `manual_launch_grid` in the GPU indexing options:
+
+```{code-cell}
+cfg = ps.CreateKernelConfig(
+    # ... other options ...
+    gpu_indexing=ps.GpuIndexingConfig(
+        manual_launch_grid=True
+    )
+)
+```
+
+Now, to execute our kernel, we have to manually specify its launch grid:
+
+```{code-cell} ipython3
+kernel.block_size = (8, 8)
+kernel.num_blocks = (2, 2)
+```
+
+This way the kernel will cover this iteration space:
+
+```{code-cell} ipython3
+:tags: [remove-input]
+f_arr = cp.zeros((16, 16))
+kernel(f=f_arr)
+_draw_ispace(cp.asnumpy(f_arr))
+```
+
+We can also observe the effect of decreasing the launch grid size:
+
+```{code-cell} ipython3
+kernel.block_size = (4, 4)
+kernel.num_blocks = (2, 3)
+```
+
+```{code-cell} ipython3
+:tags: [remove-input]
+f_arr = cp.zeros((16, 16))
+kernel(f=f_arr)
+_draw_ispace(cp.asnumpy(f_arr))
+```
+
+Here, since there are only eight threads operating in $x$-direction, 
+and twelve threads in $y$-direction,
+only a part of the triangle is being processed.
+
+## API Reference
+
+```{eval-rst}
+.. autosummary::
+  :toctree: generated
+  :nosignatures:
+  :template: autosummary/recursive_class.rst
+
+  pystencils.backend.kernelfunction.GpuKernelFunction
+  pystencils.backend.jit.gpu_cupy.CupyKernelWrapper
+```
+
+:::{admonition} Developers To Do:
+
+- Fast approximation functions
+- Fp16 on GPU
+:::
+
+
+[cupy]: https://cupy.dev "CuPy Homepage"
+[numpy]: https://numpy.org "NumPy Homepage"
+[nvcc]: https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html "NVIDIA CUDA Compiler Driver"
+[cupy-docs]: https://docs.cupy.dev/en/stable/overview.html "CuPy Documentation"
\ No newline at end of file
diff --git a/docs/source/reference/index.rst b/docs/source/reference/index.rst
deleted file mode 100644
index 7da7b5795a76c01ead467215c1deb514e4fd186c..0000000000000000000000000000000000000000
--- a/docs/source/reference/index.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-.. _page_api:
-
-###############
-Reference Guide
-###############
-
-These pages list the public APIs of pystencils, with advice on how to use them.
-
-.. toctree::
-    :maxdepth: 2
-
-    symbolic_language
-    kernelcreation
-    types
diff --git a/docs/source/reference/kernelcreation.md b/docs/source/reference/kernelcreation.md
new file mode 100644
index 0000000000000000000000000000000000000000..af8c01456cdcfebe911c3b26c913fb36b0c744cd
--- /dev/null
+++ b/docs/source/reference/kernelcreation.md
@@ -0,0 +1,527 @@
+---
+jupytext:
+  formats: md:myst
+  text_representation:
+    extension: .md
+    format_name: myst
+    format_version: 0.13
+    jupytext_version: 1.16.4
+kernelspec:
+  display_name: Python 3 (ipykernel)
+  language: python
+  name: python3
+mystnb:
+  execution_mode: cache
+---
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+
+import sympy as sp
+import pystencils as ps
+import numpy as np
+import matplotlib.pyplot as plt
+```
+
+(guide_kernelcreation)=
+# Kernel Creation
+
+Once a kernel's assignments are fully assembled, they need to be passed through pystencils' code
+generation engine in order to produce the kernel's executable code.
+The goal of this chapter is to shed light on pystencils' main code generation pipeline.
+Here, we show how to invoke the code generator and discuss its various configuration options
+and their effects on the generated kernel.
+
+## Running the Code Generator
+
+The primary way to invoke the code generation engine is through the `create_kernel` function.
+It takes two arguments:
+- the list of assignment that make up the kernel (optionally wrapped as an ``AssignmentCollection``),
+- and a configuration object, an instance of {any}`CreateKernelConfig <pystencils.config.CreateKernelConfig>`.
+
+```{eval-rst}
+.. autosummary::
+  :nosignatures:
+
+  pystencils.kernelcreation.create_kernel
+  pystencils.config.CreateKernelConfig
+```
+
+For a simple kernel, an invocation of the code generator might look like this:
+
+```{code-cell} ipython3
+# Symbol and field definitions
+u_src, u_dst, f = ps.fields("u_src, u_dst, f: float32[2D]")
+h = sp.Symbol("h")
+
+# Kernel definition
+update = [
+  ps.Assignment(
+    u_dst[0,0], (h**2 * f[0, 0] + u_src[1, 0] + u_src[-1, 0] + u_src[0, 1] + u_src[0, -1]) / 4
+  )
+]
+
+# Code Generator Configuration
+cfg = ps.CreateKernelConfig(
+  target=ps.Target.CUDA,
+  default_dtype="float32",
+  ghost_layers=1
+)
+
+kernel = ps.create_kernel(update, cfg)
+```
+
+The above snippet defines a five-point-stencil Jacobi update. A few noteworthy things are going on:
+- The target data type of the kernel is to be `float32`.
+  This is explicitly specified for the three fields `u`, `u_tmp` and `f`.
+  For the symbol `h`, this is left implicit; `h` therefore learns its data type from the `default_dtype` configuration option.
+- The target hardware for this kernel are Nvidia GPUs; this is reflected by the `target` property being set to `Target.CUDA`.
+- As the five-point stencil reads data from neighbors offset by one cell, it can not be legally executed on the outermost
+  layer of nodes of the fields' 2D arrays. Here, we ensure that these outer layers are excluded by setting `ghost_layers=1`.
+  This is not strictly necessary, since the code generator could infer that information by itself.
+
+## Inspecting the Generated Code
+
+The object returned by the code generator, here named `kernel`, is an instance of the {any}`KernelFunction` class.
+This object stores the kernel's name, its list of parameters, the set of fields it operates on, and its hardware target.
+Also, it of course holds the kernel itself, in the form of an [abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST).
+This tree can be printed out as compilable code in the target language (C++ or, in this case, CUDA),
+but holds much more information than the printed-out code string.
+When working in a Jupyter notebook, we can interactively inspect the kernel using pystencils' `inspect` function.
+This reveals a widget that allows us investigate various details about the kernel:
+- its general properties, such as name, parameters, fields, target, ...;
+- its code, represented in the *pystencils IR syntax*;
+- the same code, in native C++/CUDA syntax;
+- and a visual representation of its abstract syntax tree.
+
+```{code-cell} ipython3
+ps.inspect(kernel)
+```
+
+## Configuring the Code Generator
+
+The code generation engine can be configured using a wide range of options.
+This section aims at explaining the majority of these options,
+their interaction and effects, use cases and caveats.
+
+
+### Target Specification
+
+Pystencils supports code generation for a variety of CPU and GPU hardware.
+
+```{eval-rst}
+.. currentmodule:: pystencils.config
+
+.. autosummary::
+  :nosignatures:
+
+  CreateKernelConfig.target
+
+.. module:: pystencils.target
+
+.. autosummary::
+  :toctree: generated
+  :nosignatures:
+  :template: autosummary/recursive_class.rst
+
+  Target
+```
+
+### Data Types
+
+To produce valid output code, the code generator has to figure out the data types of each
+symbol, expression, and assignment occuring inside a kernel.
+This happens roughly according to the following rules:
+ - **Field Accesses:** Each field has a fixed data type set at its creation, which is also applied to
+   each access to that field.
+ - **Symbols:** Symbols obtain their data types from two sources. 
+   A symbol occuring first on the left-hand side of an assignment receives the data type that
+   was inferred for the right-hand side expression of that assignment.
+   Symbols occuring first inside some expression on the right-hand side of an assignment, on the other
+   hand, receive the {any}`default_dtype <CreateKernelConfig.default_dtype>` set in the {any}`CreateKernelConfig`.
+
+We can observe this behavior by setting up a kernel including several fields with different data types:
+
+```{code-cell} ipython3
+from pystencils.sympyextensions import CastFunc
+
+f = ps.fields("f: float32[2D]")
+g = ps.fields("g: float16[2D]")
+
+x, y, z = sp.symbols("x, y, z")
+
+assignments = [
+  ps.Assignment(x, 42),
+  ps.Assignment(y, f(0) + x),
+  ps.Assignment(z, g(0))
+]
+
+cfg = ps.CreateKernelConfig(
+  default_dtype="float32",
+  index_dtype="int32"
+)
+
+kernel = ps.create_kernel(assignments, cfg)
+```
+
+We can take a look at the result produced by the code generator after parsing the above kernel.
+Inspecting the internal representation of the kernel's body and loop nest,
+we see that `x` has received the `float32` type,
+which was specified via the {py:data}`default_dtype <CreateKernelConfig.default_dtype>` option.
+The symbol `y`, on the other hand, has inherited its data type `float16` from the access to the field `g`
+on its declaration's right-hand side.
+Also, we can observe that the loop counters and symbols related to the field's memory layout
+are using the `int32` data type, as specified in {py:data}`index_dtype <CreateKernelConfig.index_dtype>`:
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+driver = ps.kernelcreation.get_driver(cfg, retain_intermediates=True)
+kernel = driver(assignments)
+ps.inspect(driver.intermediates.materialized_ispace, show_cpp=False)
+```
+
+:::{note}
+To learn more about inspecting code after different stages of the code generator, refer to [this section](#section_codegen_stages).
+:::
+
+```{eval-rst}
+.. currentmodule:: pystencils.config
+
+.. autosummary::
+  :nosignatures:
+
+  CreateKernelConfig.default_dtype
+  CreateKernelConfig.index_dtype
+```
+
+### The Iteration Space
+
+The *domain fields* a kernel operates on are understood to reside on a common,
+one-, two- or three-dimensional computational grid.
+The grid points may be understood as vertices or cells, depending on the application.
+When executed, the kernel performs a computation and updates values on all, or a specific subset
+of, these grid points.
+The set of points the kernel actually operates on is defined by its *iteration space*.
+
+There are three distinct options to control the iteration space in the code generator,
+only one of which can be specified at a time:
+ - The ``ghost_layers`` option allows to specify a number of layers of grid points on all
+   domain borders that should be excluded from iteration;
+ - The ``iteration_slice`` option allows to describe the iteration space using Pythonic slice objects;
+ - The ``index_field`` option can be used to realize a sparse list-based iteration by passing a special
+   *index field* which holds a list of all points that should be processed.
+
+:::{note}
+  The points within a kernel's iteration space are understood to be processed concurrently and in
+  no particular order;
+  the output of any kernel that relies on some specific iteration order is therefore undefined.
+  (When running on a GPU, all grid points might in fact be processed in perfect simultaniety!)
+:::
+
+```{eval-rst}
+.. currentmodule:: pystencils.config
+
+.. autosummary::
+  :nosignatures:
+
+  CreateKernelConfig.ghost_layers
+  CreateKernelConfig.iteration_slice
+  CreateKernelConfig.index_field
+```
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+
+def _draw_ispace(f_arr):
+    n, m = f_arr.shape
+    fig, ax = plt.subplots()
+    
+    ax.set_xticks(np.arange(0, m, 4))
+    ax.set_yticks(np.arange(0, n, 4))
+    # ax.set_xticklabels([])
+    # ax.set_yticklabels([])
+
+    ax.set_xticks(np.arange(-.5, m, 1), minor=True)
+    ax.set_yticks(np.arange(-.5, n, 1), minor=True)
+    
+    ax.grid(which="minor", linewidth=2)
+    ax.tick_params(which='minor', bottom=False, left=False)
+    
+    ax.imshow(f_arr, interpolation="none", aspect="equal", origin="lower")
+```
+
+#### Specifying Ghost Layers
+
+One way to alter the iteration space is by introducing ghost layers on the domain borders.
+These layers of grid points are stripped from the iterations, and can be used to hold
+boundary values or exchange data in MPI-parallel simulations.
+
+##### Automatic Ghost Layers
+
+The easiest way to define an iteration space with ghost layers
+is to set `ghost_layers=ps.config.AUTO`, which is also the default
+when no iteration space options are specified.
+In this case, the code generator will examine the kernel to find the maximum range
+of its stencil -- that is, the maximum neighbor offset encountered in any field access.
+If, for instance, a neighbor node in $x$-direction with offset $k$ is accessed by the kernel,
+it cannot legally execute on the outermost $k$ layers of nodes in that direction since it would
+access memory out-of-bounds.
+Therefore, an automatic number of $k$ ghost layers at each domain border is inferred.
+As we can see in the example below, the number of inferred ghost layers at each domain border will be set to the maximum required in any dimension.
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+
+u, v = ps.fields("u, v: [2D]")
+```
+
+To illustrate, the following kernel accesses neighbor nodes with a maximum offset of two:
+
+```{code-cell} ipython3
+ranged_update = ps.Assignment(u.center(), v[-2, -1] + v[2, 1])
+
+cfg = ps.CreateKernelConfig(ghost_layers=ps.config.AUTO)
+kernel = ps.create_kernel(ranged_update, cfg)
+```
+
+With `ghost_layers=ps.config.AUTO`, its iteration space will look like this (yellow cells are included, purple cells excluded).
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+f = ps.fields("f: float64[2D]")
+assignments = [
+    ranged_update,
+    ps.Assignment(f(0), 1)
+]
+kernel = ps.create_kernel(assignments).compile()
+
+f_arr = np.zeros((16, 16))
+u_arr = np.zeros_like(f_arr)
+v_arr = np.zeros_like(f_arr)
+
+kernel(f=f_arr, u=u_arr, v=v_arr)
+
+_draw_ispace(f_arr)
+```
+
+##### Uniform and Nonuniform Ghost Layers
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+
+def _show_ispace(cfg):
+    f = ps.fields("f: float64[2D]")
+    assignments = [
+        ps.Assignment(f(0), 1)
+    ]
+    kernel = ps.create_kernel(assignments, cfg).compile()
+
+    f_arr = np.zeros((16, 16))
+    kernel(f=f_arr)
+
+    _draw_ispace(f_arr)
+```
+
+Setting `ghost_layers` to a number will remove that many layers from the iteration space in each dimension:
+
+```{code-cell} ipython3
+cfg = ps.CreateKernelConfig(
+    ghost_layers=1
+)
+```
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+_show_ispace(cfg)
+```
+
+Ghost layers can also be specified individually for each dimension and lower/upper borders,
+by passing a sequence with either a single integer or a pair of integers per dimension:
+
+```{code-cell} ipython3
+cfg = ps.CreateKernelConfig(
+    ghost_layers=[(2, 1), 3]
+)
+```
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+_show_ispace(cfg)
+```
+
+#### Iteration Slices
+
+Using the `iteration_slice` option, we can assert much finer control on the kernel's iteration space
+by specifying it using sequences of Python {py:class}`slice` objects.
+
+We can quickly create those using `ps.make_slice`, using the `start:stop:step` slice notation.
+The easiest case is to set the iteration space with fixed numerical limits:
+
+```{code-cell} ipython3
+cfg = ps.CreateKernelConfig(
+    iteration_slice=ps.make_slice[3:-4, 9:14]
+)
+```
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+_show_ispace(cfg)
+```
+
+##### Strided Iteration
+
+It is also possible to set up a strided iteration that skips over a fixed number of elements.
+The following example processes only every second line in $y$-direction, using the slice `::2`:
+
+```{code-cell} ipython3
+cfg = ps.CreateKernelConfig(
+    iteration_slice=ps.make_slice[::2, 3:-3]
+)
+```
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+_show_ispace(cfg)
+```
+
+(example_triangular_iteration)=
+##### Triangular Iteration
+
+Iteration slices are not limited to constant numerical values; they can be arbitrarily complex
+*SymPy* expressions.
+By using the counter symbol for the first dimension to define the iteration limits of the second,
+we can produce a triangular iteration pattern:
+
+```{code-cell} ipython3
+y = ps.DEFAULTS.spatial_counters[0]
+cfg = ps.CreateKernelConfig(
+    iteration_slice=ps.make_slice[:, y:]
+)
+```
+
+:::{warning}
+This type of dependency is restricted by the ordering of the iteration space dimensions:
+The limits of a dimension can only depend on the counters of dimensions that are *slower*
+than itself.
+The ordering of dimensions is determined by the memory layout of the kernels' fields;
+see also the [section on memory layouts](#section_memory_layout).
+:::
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+_show_ispace(cfg)
+```
+
+##### Red-Black Iteration
+
+Using a case distinction for the second dimension's start index, we can even produce
+a checkerboard pattern, as required for e.g. red-black Gauss-Seidel-type smoothers.
+We use the integer remainder ({any}`int_rem`) to distinguish between even- and odd-numbered rows,
+set the start value accordingly using {any}`sp.Piecewise <sympy.functions.elementary.piecewise.Piecewise>`,
+and use a step size of two:
+
+$$
+  start(y)=
+    \begin{cases}
+      0 & \quad \text{if } y \; \mathrm{rem} \; 2 = 0 \\ 
+      1 & \quad \text{otherwise}
+    \end{cases}
+$$
+
+
+```{code-cell} ipython3
+from pystencils.sympyextensions.integer_functions import int_rem
+
+y = ps.DEFAULTS.spatial_counters[0]
+start = sp.Piecewise(
+    (0, sp.Eq(int_rem(y, 2), 0)),
+    (1, True)
+)
+cfg = ps.CreateKernelConfig(
+    iteration_slice=ps.make_slice[:, start::2]
+)
+```
+
+:::{warning}
+The restrictions on dimension ordering of the triangular iteration example apply
+to the checkerboard-iteration as well.
+:::
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+_show_ispace(cfg)
+```
+
+(section_memory_layout)=
+## Memory Layout and Dimension Ordering
+
+:::{admonition} Developer To Do
+Briefly explain about field memory layouts, cache locality, coalesced memory accesses (on GPU and vector CPUs),
+and the need for correct ordering of the dimensions (loop order on CPU, thread indexing order on GPU).
+:::
+
+(section_codegen_stages)=
+## Advanced: Understanding the Stages of the Code Generator
+
+While translating a set of symbolic definitions to a kernel, the code generator of pystencils
+goes through a number of stages, gradually extending and transforming the AST.
+Pystencils allows you to retrieve and inspect the intermediate results produced by the
+code generator, in order to better understand the process of kernel translation.
+This can be immensely helpful when tracking down bugs or trying to explain unexpected
+output code.
+
+To get access to the intermediate results, the code generator has to be invoked in a slightly different way.
+Instead of just calling `create_kernel`, we directly create the so-called *driver* and instruct it to
+store its intermediate ASTs:
+
+```{code-cell} ipython3
+:tags: [remove-cell]
+u_src, u_dst, f = ps.fields("u_src, u_dst, f: float32[2D]")
+h = sp.Symbol("h")
+
+cfg = ps.CreateKernelConfig(
+  target=ps.Target.X86_AVX512,
+  default_dtype="float32",
+  cpu_optim=ps.CpuOptimConfig(
+    openmp=True,
+    vectorize=ps.VectorizationConfig(
+        assume_inner_stride_one=True
+    )
+  )
+)
+
+assignments = [
+  ps.Assignment(
+    u_dst[0,0], (h**2 * f[0, 0] + u_src[1, 0] + u_src[-1, 0] + u_src[0, 1] + u_src[0, -1]) / 4
+  )
+]
+```
+
+```{code-cell} ipython3
+driver = ps.kernelcreation.get_driver(cfg, retain_intermediates=True)
+kernel = driver(assignments)
+ps.inspect(driver.intermediates)
+```
+
+## API: Kernel Parameters and Function Objects
+
+```{eval-rst}
+.. module:: pystencils.backend.kernelfunction
+
+.. autosummary::
+  :toctree: generated
+  :nosignatures:
+  :template: autosummary/entire_class.rst
+
+  KernelParameter
+  KernelFunction
+  GpuKernelFunction
+```
diff --git a/docs/source/reference/kernelcreation.rst b/docs/source/reference/kernelcreation.rst
deleted file mode 100644
index 7ea20d6b64f0371754143a7468c430c46f6254ec..0000000000000000000000000000000000000000
--- a/docs/source/reference/kernelcreation.rst
+++ /dev/null
@@ -1,61 +0,0 @@
-.. _page_kernel_creation:
-
-***************
-Kernel Creation
-***************
-
-Targets
-=======
-
-.. module:: pystencils.target
-
-.. autosummary::
-    :toctree: autoapi
-    :nosignatures:
-    :template: autosummary/recursive_class.rst
-
-    Target
-
-
-Configuration
-=============
-
-.. module:: pystencils.config
-
-.. autosummary::
-    :toctree: autoapi
-    :nosignatures:
-    :template: autosummary/entire_class.rst
-
-    CreateKernelConfig
-    CpuOptimConfig
-    OpenMpConfig
-    VectorizationConfig
-    GpuIndexingConfig
-
-
-Creation
-========
-
-.. module:: pystencils.kernelcreation
-
-.. autosummary::
-    :toctree: autoapi
-    :nosignatures:
-
-    create_kernel
-
-
-Kernel Parameters and Function Objects
-======================================
-
-.. module:: pystencils.backend.kernelfunction
-
-.. autosummary::
-    :toctree: autoapi
-    :nosignatures:
-    :template: autosummary/entire_class.rst
-
-    KernelParameter
-    KernelFunction
-    GpuKernelFunction
diff --git a/docs/source/reference/symbolic_language.rst b/docs/source/reference/symbolic_language.rst
index f56b8e372a3aa888e42cc9661c9dcce09a21c019..63b94e04d5026d8210c37db9f2d43f36159aa846 100644
--- a/docs/source/reference/symbolic_language.rst
+++ b/docs/source/reference/symbolic_language.rst
@@ -4,14 +4,6 @@
 Symbolic Language
 *****************
 
-.. toctree::
-    :maxdepth: 2
-    :hidden:
-
-    field
-    sympyextensions
-
-
 Pystencils allows you to define near-arbitrarily complex numerical kernels in its symbolic
 language, which is based on the computer algebra system `SymPy <https://www.sympy.org>`_.
 The pystencils code generator is able to parse and translate a large portion of SymPy's
@@ -64,7 +56,7 @@ An assignment collection contains two separate lists of assignments:
   into fields.
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
     :template: autosummary/recursive_class.rst
 
diff --git a/docs/source/reference/types.rst b/docs/source/reference/types.rst
index 041b0cb2a5dbabede1054cbc261d256bd628be73..3df1337703c75b21ac8eb579e6e01f040f379108 100644
--- a/docs/source/reference/types.rst
+++ b/docs/source/reference/types.rst
@@ -11,7 +11,7 @@ Type Creation and Conversion
 ----------------------------
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
     create_type
@@ -34,7 +34,7 @@ unless you have very particular needs.
     :parts: 1
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
     :template: autosummary/entire_class.rst
 
@@ -82,10 +82,10 @@ Exceptions
 .. currentmodule:: pystencils.types
 
 .. autosummary::
-    :toctree: autoapi
+    :toctree: generated
     :nosignatures:
 
-    pystencils.types.PsTypeError
+    PsTypeError
 
 
 Implementation Details
diff --git a/pyproject.toml b/pyproject.toml
index 4c629cc7a56c40b63576464a8b43ee8bc8454b46..d9a33c9d7b148541c5c7ce4e21aac7c6565d1600 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -46,12 +46,13 @@ use_cython = [
 ]
 doc = [
     'sphinx',
-    'furo',
-    'nbsphinx',
+    'pydata-sphinx-theme==0.15.4',
+    'sphinx-book-theme==1.1.3',  # workaround for https://github.com/executablebooks/sphinx-book-theme/issues/865
     'sphinxcontrib-bibtex',
     'sphinx_autodoc_typehints',
     'pandoc',
     'sphinx_design',
+    'myst-nb'
 ]
 tests = [
     'pytest',
diff --git a/src/pystencils/__init__.py b/src/pystencils/__init__.py
index 66533a0b7a71ad867582e9159b04d1c7c78561cf..b2cdeca07d6040e198f23f1b5666352fdfb991be 100644
--- a/src/pystencils/__init__.py
+++ b/src/pystencils/__init__.py
@@ -5,6 +5,7 @@ from .defaults import DEFAULTS
 from . import fd
 from . import stencil as stencil
 from .display_utils import get_code_obj, get_code_str, show_code, to_dot
+from .inspection import inspect
 from .field import Field, FieldType, fields
 from .types import create_type, create_numeric_type
 from .cache import clear_cache
@@ -37,7 +38,6 @@ from .sympyextensions.typed_sympy import TypedSymbol, DynamicType
 from .sympyextensions import SymbolCreator
 from .datahandling import create_data_handling
 
-
 __all__ = [
     "Field",
     "FieldType",
@@ -63,6 +63,7 @@ __all__ = [
     "to_dot",
     "get_code_obj",
     "get_code_str",
+    "inspect",
     "AssignmentCollection",
     "Assignment",
     "AddAugmentedAssignment",
diff --git a/src/pystencils/backend/emission/__init__.py b/src/pystencils/backend/emission/__init__.py
index b38b0c459b0a408b87476faeb7e395f9a4822838..8d413d4c22a4ec382cf2a1fc6e2d29ca1c83f2d1 100644
--- a/src/pystencils/backend/emission/__init__.py
+++ b/src/pystencils/backend/emission/__init__.py
@@ -1,4 +1,5 @@
+from .base_printer import EmissionError
 from .c_printer import emit_code, CAstPrinter
 from .ir_printer import emit_ir, IRAstPrinter
 
-__all__ = ["emit_code", "CAstPrinter", "emit_ir", "IRAstPrinter"]
+__all__ = ["emit_code", "CAstPrinter", "emit_ir", "IRAstPrinter", "EmissionError"]
diff --git a/src/pystencils/backend/emission/base_printer.py b/src/pystencils/backend/emission/base_printer.py
index 9b1d5481a79447dcf70e9706c5d11450b18da22b..50cd1bfeaf7f97295e4c6c557fa26acf933c04b7 100644
--- a/src/pystencils/backend/emission/base_printer.py
+++ b/src/pystencils/backend/emission/base_printer.py
@@ -189,7 +189,7 @@ class BasePrinter(ABC):
                 pc.indent_level += self._indent_width
                 interior = "\n".join(self.visit(stmt, pc) for stmt in statements) + "\n"
                 pc.indent_level -= self._indent_width
-                return pc.indent("{\n") + interior + pc.indent("}\n")
+                return pc.indent("{\n") + interior + pc.indent("}")
 
             case PsStatement(expr):
                 return pc.indent(f"{self.visit(expr, pc)};")
diff --git a/src/pystencils/backend/emission/c_printer.py b/src/pystencils/backend/emission/c_printer.py
index 0efe875887c75f08df20f825cdc1411c6de9ae96..95e27bd66732f04e3d20767cf8c6d35d0cfd2450 100644
--- a/src/pystencils/backend/emission/c_printer.py
+++ b/src/pystencils/backend/emission/c_printer.py
@@ -5,7 +5,7 @@ from pystencils.backend.memory import PsSymbol
 from .base_printer import BasePrinter
 
 from ..kernelfunction import KernelFunction
-from ...types import PsType, PsArrayType, PsScalarType
+from ...types import PsType, PsArrayType, PsScalarType, PsTypeError
 from ..ast.expressions import PsBufferAcc
 from ..ast.vector import PsVecMemAcc
 
@@ -23,7 +23,10 @@ class CAstPrinter(BasePrinter):
     def visit(self, node: PsAstNode, pc: PrinterCtx) -> str:
         match node:
             case PsVecMemAcc():
-                raise EmissionError("Cannot print vectorized array accesses to C code.")
+                raise EmissionError(
+                    f"Unable to print C code for vector memory access {node}.\n"
+                    f"Vectorized memory accesses must be mapped to intrinsics before emission."
+                )
 
             case PsBufferAcc():
                 raise EmissionError(
@@ -33,7 +36,7 @@ class CAstPrinter(BasePrinter):
 
             case _:
                 return super().visit(node, pc)
-            
+
     def _symbol_decl(self, symb: PsSymbol):
         dtype = symb.get_dtype()
 
@@ -52,11 +55,12 @@ class CAstPrinter(BasePrinter):
     def _constant_literal(self, constant: PsConstant):
         dtype = constant.get_dtype()
         if not isinstance(dtype, PsScalarType):
-            raise EmissionError(
-                "Cannot print literals for non-scalar constants."
-            )
+            raise EmissionError("Cannot print literals for non-scalar constants.")
 
         return dtype.create_literal(constant.value)
 
     def _type_str(self, dtype: PsType):
-        return dtype.c_string()
+        try:
+            return dtype.c_string()
+        except PsTypeError:
+            raise EmissionError(f"Unable to print type {dtype} as a C data type.")
diff --git a/src/pystencils/backend/emission/ir_printer.py b/src/pystencils/backend/emission/ir_printer.py
index 4986f1a7f2c32339d236f1edd6640d1db4e9aee4..124ce200d3aab9e3b111dd0481bd8bc7faad817f 100644
--- a/src/pystencils/backend/emission/ir_printer.py
+++ b/src/pystencils/backend/emission/ir_printer.py
@@ -59,7 +59,7 @@ class IRAstPrinter(BasePrinter):
 
                 stride_code = "" if stride is None else f", stride={stride}"
 
-                code = f"vec_load< {lanes}{stride_code} >({ptr_code}, {offset_code})"
+                code = f"vec_memacc< {lanes}{stride_code} >({ptr_code}, {offset_code})"
                 return pc.parenthesize(code, Ops.Subscript)
 
             case PsVecBroadcast(lanes, operand):
diff --git a/src/pystencils/backend/kernelfunction.py b/src/pystencils/backend/kernelfunction.py
index afd54c1107e13e73d2141cd9b0d7da2e97f0ef3e..e2161590e7023728d55b35f7355d25ea94e21438 100644
--- a/src/pystencils/backend/kernelfunction.py
+++ b/src/pystencils/backend/kernelfunction.py
@@ -259,6 +259,8 @@ def create_cpu_kernel_function(
 
 
 class GpuKernelFunction(KernelFunction):
+    """Internal representation of a kernel function targeted at CUDA GPUs."""
+
     def __init__(
         self,
         body: PsBlock,
@@ -277,6 +279,7 @@ class GpuKernelFunction(KernelFunction):
 
     @property
     def threads_range(self) -> GpuThreadsRange | None:
+        """Object exposing the total size of the launch grid this kernel expects to be executed with."""
         return self._threads_range
 
 
diff --git a/src/pystencils/backend/platforms/generic_gpu.py b/src/pystencils/backend/platforms/generic_gpu.py
index 4c990429d8fd33f800dbf4f1f7797b7520c93b39..975d39d22ec7edeb2e6e640a4460c30509756973 100644
--- a/src/pystencils/backend/platforms/generic_gpu.py
+++ b/src/pystencils/backend/platforms/generic_gpu.py
@@ -49,6 +49,15 @@ class GpuThreadsRange:
     @property
     def dim(self) -> int:
         return self._dim
+    
+    def __str__(self) -> str:
+        rep = "GpuThreadsRange { "
+        rep += "; ".join(f"{x}: {w}" for x, w in zip("xyz", self._num_work_items))
+        rep += " }"
+        return rep
+    
+    def _repr_html_(self) -> str:
+        return str(self)
 
     @staticmethod
     def _from_full_ispace(ispace: FullIterationSpace) -> GpuThreadsRange:
diff --git a/src/pystencils/config.py b/src/pystencils/config.py
index c08ddc16198627adba97169e02724371eca62158..506f7fd786ca3b38fec1cef83c9ec289206b4662 100644
--- a/src/pystencils/config.py
+++ b/src/pystencils/config.py
@@ -33,7 +33,12 @@ class _AUTO_TYPE:
 
 
 AUTO = _AUTO_TYPE()
-"""Special value that can be passed to some options for invoking automatic behaviour."""
+"""Special value that can be passed to some options for invoking automatic behaviour.
+
+Currently, these options permit `AUTO`:
+
+- `ghost_layers <CreateKernelConfig.ghost_layers>`
+"""
 
 
 @dataclass
diff --git a/src/pystencils/inspection.py b/src/pystencils/inspection.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb03a1c8da31a479784e0c99185eb6c6f760533d
--- /dev/null
+++ b/src/pystencils/inspection.py
@@ -0,0 +1,276 @@
+from typing import overload
+
+from .backend.ast import PsAstNode
+from .backend.emission import CAstPrinter, IRAstPrinter, EmissionError
+from .backend.kernelfunction import KernelFunction
+from .kernelcreation import StageResult, CodegenIntermediates
+from abc import ABC, abstractmethod
+
+_UNABLE_TO_DISPLAY_CPP = """
+<div>
+    <b>Unable to display C code for this abstract syntax tree</b>
+    <p>
+    This intermediate abstract syntax tree contains nodes that cannot be
+    printed as valid C code.
+    </p>
+</div>
+"""
+
+_GRAPHVIZ_NOT_IMPLEMENTED = """
+<div>
+    <b>AST Visualization Unavailable</b>
+    <p>
+    AST visualization using GraphViz is not implemented yet.
+    </p>
+</div>
+"""
+
+_ERR_MSG = """
+<div style="font-family: monospace; background-color: #EEEEEE; white-space: nowrap; overflow-x: scroll">
+    {}
+</div>
+"""
+
+
+class CodeInspectionBase(ABC):
+    def __init__(self) -> None:
+        self._ir_printer = IRAstPrinter(annotate_constants=False)
+        self._c_printer = CAstPrinter()
+
+    def _ir_tab(self, ir_obj: PsAstNode | KernelFunction):
+        import ipywidgets as widgets
+
+        ir = self._ir_printer(ir_obj)
+        ir_tab = widgets.HTML(self._highlight_as_cpp(ir))
+        self._apply_tab_layout(ir_tab)
+        return ir_tab
+
+    def _cpp_tab(self, ir_obj: PsAstNode | KernelFunction):
+        import ipywidgets as widgets
+
+        try:
+            cpp = self._c_printer(ir_obj)
+            cpp_tab = widgets.HTML(self._highlight_as_cpp(cpp))
+        except EmissionError as e:
+            cpp_tab = widgets.VBox(
+                children=[
+                    widgets.HTML(_UNABLE_TO_DISPLAY_CPP),
+                    widgets.Accordion(
+                        children=[widgets.HTML(_ERR_MSG.format(e.args[0]))],
+                        titles=["Error Details"],
+                    ),
+                ]
+            )
+        self._apply_tab_layout(cpp_tab)
+        return cpp_tab
+
+    def _graphviz_tab(self, ir_obj: PsAstNode | KernelFunction):
+        import ipywidgets as widgets
+
+        graphviz_tab = widgets.HTML(_GRAPHVIZ_NOT_IMPLEMENTED)
+        self._apply_tab_layout(graphviz_tab)
+        return graphviz_tab
+
+    def _apply_tab_layout(self, tab):
+        tab.layout.display = "inline-block"
+        tab.layout.padding = "0 15pt 0 0"
+
+    def _highlight_as_cpp(self, code: str) -> str:
+        from pygments import highlight
+        from pygments.formatters import HtmlFormatter
+        from pygments.lexers import CppLexer
+
+        formatter = HtmlFormatter(
+            prestyles="white-space: pre;",
+        )
+        html_code = highlight(code, CppLexer(), formatter)
+        return html_code
+
+    def _ipython_display_(self):
+        from IPython.display import display
+
+        display(self._widget())
+
+    @abstractmethod
+    def _widget(self): ...
+
+
+class AstInspection(CodeInspectionBase):
+    """Inspect an abstract syntax tree produced by the code generation backend.
+
+    **Interactive:** This class can be used in Jupyter notebooks to interactively
+    explore an abstract syntax tree.
+    """
+
+    def __init__(
+        self,
+        ast: PsAstNode,
+        show_ir: bool = True,
+        show_cpp: bool = True,
+        show_graph: bool = True,
+    ):
+        super().__init__()
+        self._ast = ast
+        self._show_ir = show_ir
+        self._show_cpp = show_cpp
+        self._show_graph = show_graph
+
+    def _widget(self):
+        import ipywidgets as widgets
+
+        tabs = []
+        if self._show_ir:
+            tabs.append(self._ir_tab(self._ast))
+        if self._show_cpp:
+            tabs.append(self._cpp_tab(self._ast))
+        if self._show_graph:
+            tabs.append(self._graphviz_tab(self._ast))
+
+        tabs = widgets.Tab(children=tabs)
+        tabs.titles = ["IR Code", "C Code", "AST Visualization"]
+
+        tabs.layout.height = "250pt"
+
+        return tabs
+
+
+class KernelInspection(CodeInspectionBase):
+    def __init__(
+        self,
+        kernel: KernelFunction,
+        show_ir: bool = True,
+        show_cpp: bool = True,
+        show_graph: bool = True,
+    ) -> None:
+        super().__init__()
+        self._kernel = kernel
+        self._show_ir = show_ir
+        self._show_cpp = show_cpp
+        self._show_graph = show_graph
+
+    def _widget(self):
+        import ipywidgets as widgets
+
+        tabs = []
+        if self._show_ir:
+            tabs.append(self._ir_tab(self._kernel))
+        if self._show_cpp:
+            tabs.append(self._cpp_tab(self._kernel))
+        if self._show_graph:
+            tabs.append(self._graphviz_tab(self._kernel))
+
+        tabs = widgets.Tab(children=tabs)
+        tabs.titles = ["IR Code", "C Code", "AST Visualization"]
+
+        tabs.layout.height = "250pt"
+
+        return tabs
+
+
+class IntermediatesInspection:
+    def __init__(
+        self,
+        intermediates: CodegenIntermediates,
+        show_ir: bool = True,
+        show_cpp: bool = True,
+        show_graph: bool = True,
+    ):
+        self._intermediates = intermediates
+        self._show_ir = show_ir
+        self._show_cpp = show_cpp
+        self._show_graph = show_graph
+
+    def _ipython_display_(self):
+        from IPython.display import display
+        import ipywidgets as widgets
+
+        stages = self._intermediates.available_stages
+
+        previews: list[AstInspection] = [
+            AstInspection(
+                stage.ast,
+                show_ir=self._show_ir,
+                show_cpp=self._show_cpp,
+                show_graph=self._show_graph,
+            )
+            for stage in stages
+        ]
+        labels: list[str] = [stage.label for stage in stages]
+
+        code_views = [p._widget() for p in previews]
+        for v in code_views:
+            v.layout.width = "100%"
+
+        select_label = widgets.HTML("<div><b>Code Generator Stages</b></div>")
+        select = widgets.Select(options=labels)
+        select.layout.height = "250pt"
+
+        selection_box = widgets.VBox([select_label, select])
+        selection_box.layout.overflow = "visible"
+
+        preview_label = widgets.HTML("<div><b>Preview</b></div>")
+        preview_stack = widgets.Stack(children=code_views)
+        preview_stack.layout.overflow = "hidden"
+
+        preview_box = widgets.VBox([preview_label, preview_stack])
+
+        widgets.jslink((select, "index"), (preview_stack, "selected_index"))
+
+        grid = widgets.GridBox(
+            [selection_box, preview_box],
+            layout=widgets.Layout(grid_template_columns="max-content auto"),
+        )
+
+        display(grid)
+
+
+@overload
+def inspect(obj: PsAstNode): ...
+
+
+@overload
+def inspect(obj: KernelFunction): ...
+
+
+@overload
+def inspect(obj: StageResult): ...
+
+
+@overload
+def inspect(obj: CodegenIntermediates): ...
+
+
+def inspect(obj, show_ir: bool = True, show_cpp: bool = True, show_graph: bool = True):
+    """Interactively inspect various products of the code generator.
+
+    When run inside a Jupyter notebook, this function displays an inspection widget
+    for the following types of objects:
+    - `PsAstNode`
+    - `KernelFunction`
+    - `StageResult`
+    - `CodegenIntermediates`
+    """
+
+    from IPython.display import display
+
+    match obj:
+        case PsAstNode():
+            preview = AstInspection(
+                obj, show_ir=show_ir, show_cpp=show_cpp, show_graph=show_cpp
+            )
+        case KernelFunction():
+            preview = KernelInspection(
+                obj, show_ir=show_ir, show_cpp=show_cpp, show_graph=show_cpp
+            )
+        case StageResult(ast, _):
+            preview = AstInspection(
+                ast, show_ir=show_ir, show_cpp=show_cpp, show_graph=show_cpp
+            )
+        case CodegenIntermediates():
+            preview = IntermediatesInspection(
+                obj, show_ir=show_ir, show_cpp=show_cpp, show_graph=show_cpp
+            )
+        case _:
+            raise ValueError(f"Cannot inspect object of type {type(obj)}")
+
+    display(preview)
diff --git a/src/pystencils/kernelcreation.py b/src/pystencils/kernelcreation.py
index 548fbc9bba8c1606fbba2929324e9cea273b73b3..096d644e121a6760ccd1472420e1a5fbbecda48f 100644
--- a/src/pystencils/kernelcreation.py
+++ b/src/pystencils/kernelcreation.py
@@ -1,5 +1,7 @@
+from __future__ import annotations
+
 from typing import cast, Sequence
-from dataclasses import replace
+from dataclasses import dataclass, replace
 
 from .target import Target
 from .config import (
@@ -10,6 +12,7 @@ from .config import (
 )
 from .backend import KernelFunction
 from .types import create_numeric_type, PsIntegerType, PsScalarType
+from .backend.ast import PsAstNode
 from .backend.ast.structural import PsBlock, PsLoop
 from .backend.kernelcreation import (
     KernelCreationContext,
@@ -73,8 +76,12 @@ def create_kernel(
     return driver(assignments)
 
 
+def get_driver(cfg: CreateKernelConfig, *, retain_intermediates: bool = False):
+    return DefaultKernelCreationDriver(cfg, retain_intermediates)
+
+
 class DefaultKernelCreationDriver:
-    def __init__(self, cfg: CreateKernelConfig):
+    def __init__(self, cfg: CreateKernelConfig, retain_intermediates: bool = False):
         self._cfg = cfg
 
         idx_dtype = create_numeric_type(self._cfg.index_dtype)
@@ -88,6 +95,15 @@ class DefaultKernelCreationDriver:
         self._target = self._cfg.get_target()
         self._platform = self._get_platform()
 
+        if retain_intermediates:
+            self._intermediates = CodegenIntermediates()
+        else:
+            self._intermediates = None
+
+    @property
+    def intermediates(self) -> CodegenIntermediates | None:
+        return self._intermediates
+
     def __call__(
         self,
         assignments: AssignmentCollection | Sequence[AssignmentBase] | AssignmentBase,
@@ -106,10 +122,16 @@ class DefaultKernelCreationDriver:
                     kernel_body, self._ctx.get_iteration_space()
                 )
 
+        if self._intermediates is not None:
+            self._intermediates.materialized_ispace = kernel_ast.clone()
+
         #   Fold and extract constants
         elim_constants = EliminateConstants(self._ctx, extract_constant_exprs=True)
         kernel_ast = cast(PsBlock, elim_constants(kernel_ast))
 
+        if self._intermediates is not None:
+            self._intermediates.constants_eliminated = kernel_ast.clone()
+
         #   Target-Specific optimizations
         if self._cfg.target.is_cpu():
             kernel_ast = self._transform_for_cpu(kernel_ast)
@@ -124,6 +146,9 @@ class DefaultKernelCreationDriver:
         select_functions = SelectFunctions(self._platform)
         kernel_ast = cast(PsBlock, select_functions(kernel_ast))
 
+        if self._intermediates is not None:
+            self._intermediates.lowered = kernel_ast.clone()
+
         #   Late canonicalization pass: Canonicalize new symbols introduced by LowerToC
 
         canonicalize = CanonicalizeSymbols(self._ctx, True)
@@ -194,15 +219,24 @@ class DefaultKernelCreationDriver:
         typify = Typifier(self._ctx)
         kernel_body = typify(kernel_body)
 
+        if self._intermediates is not None:
+            self._intermediates.parsed_body = kernel_body.clone()
+
         return kernel_body
 
     def _transform_for_cpu(self, kernel_ast: PsBlock):
         canonicalize = CanonicalizeSymbols(self._ctx, True)
         kernel_ast = cast(PsBlock, canonicalize(kernel_ast))
 
+        if self._intermediates is not None:
+            self._intermediates.cpu_canonicalize = kernel_ast.clone()
+
         hoist_invariants = HoistLoopInvariantDeclarations(self._ctx)
         kernel_ast = cast(PsBlock, hoist_invariants(kernel_ast))
 
+        if self._intermediates is not None:
+            self._intermediates.cpu_hoist_invariants = kernel_ast.clone()
+
         cpu_cfg = self._cfg.cpu_optim
 
         if cpu_cfg is None:
@@ -224,6 +258,9 @@ class DefaultKernelCreationDriver:
             add_omp = AddOpenMP(self._ctx, params)
             kernel_ast = cast(PsBlock, add_omp(kernel_ast))
 
+            if self._intermediates is not None:
+                self._intermediates.cpu_openmp = kernel_ast.clone()
+
         if cpu_cfg.use_cacheline_zeroing:
             raise NotImplementedError("CL-zeroing not implemented yet")
 
@@ -279,9 +316,15 @@ class DefaultKernelCreationDriver:
 
         kernel_ast = vectorizer.vectorize_select_loops(kernel_ast, loop_predicate)
 
+        if self._intermediates is not None:
+            self._intermediates.cpu_vectorize = kernel_ast.clone()
+
         select_intrin = SelectIntrinsics(self._ctx, self._platform)
         kernel_ast = cast(PsBlock, select_intrin(kernel_ast))
 
+        if self._intermediates is not None:
+            self._intermediates.cpu_select_intrins = kernel_ast.clone()
+
         return kernel_ast
 
     def _get_platform(self) -> Platform:
@@ -327,6 +370,60 @@ class DefaultKernelCreationDriver:
         )
 
 
+@dataclass
+class StageResult:
+    ast: PsAstNode
+    label: str
+
+
+class StageResultSlot:
+    def __init__(self, description: str | None = None):
+        self._description = description
+        self._name: str
+        self._lookup: str
+
+    def __set_name__(self, owner, name: str):
+        self._name = name
+        self._lookup = f"_{name}"
+
+    def __get__(self, obj, objtype=None) -> StageResult | None:
+        if obj is None:
+            return None
+
+        ast = getattr(obj, self._lookup, None)
+        if ast is not None:
+            descr = self._name if self._description is None else self._description
+            return StageResult(ast, descr)
+        else:
+            return None
+
+    def __set__(self, obj, val: PsAstNode | None):
+        setattr(obj, self._lookup, val)
+
+
+class CodegenIntermediates:
+    """Intermediate results produced by the code generator."""
+
+    parsed_body = StageResultSlot("Freeze & Type Deduction")
+    materialized_ispace = StageResultSlot("Iteration Space Materialization")
+    constants_eliminated = StageResultSlot("Constant Elimination")
+    cpu_canonicalize = StageResultSlot("CPU: Symbol Canonicalization")
+    cpu_hoist_invariants = StageResultSlot("CPU: Hoisting of Loop Invariants")
+    cpu_vectorize = StageResultSlot("CPU: Vectorization")
+    cpu_select_intrins = StageResultSlot("CPU: Intrinsics Selection")
+    cpu_openmp = StageResultSlot("CPU: OpenMP Instrumentation")
+    lowered = StageResultSlot("C Language Lowering")
+
+    @property
+    def available_stages(self) -> Sequence[StageResult]:
+        all_results: list[StageResult | None] = [
+            getattr(self, name)
+            for name, slot in CodegenIntermediates.__dict__.items()
+            if isinstance(slot, StageResultSlot)
+        ]
+        return tuple(filter(lambda r: r is not None, all_results))  # type: ignore
+
+
 def create_staggered_kernel(
     assignments, target: Target = Target.CPU, gpu_exclusive_conditions=False, **kwargs
 ):
diff --git a/src/pystencils/target.py b/src/pystencils/target.py
index 7f26c4466f8a9cd08de8b00bf4e7002bbc820fe0..5d897dd7ebd0415494161b42c2192d4eaf08adbd 100644
--- a/src/pystencils/target.py
+++ b/src/pystencils/target.py
@@ -87,7 +87,7 @@ class Target(Flag):
     """
 
     GPU = CUDA
-    """Alias for backward compatibility."""
+    """Alias for `Target.CUDA`, for backward compatibility."""
 
     SYCL = _GPU | _SYCL
     """SYCL kernel target.