diff --git a/user_config/.editorconfig b/user_config/.editorconfig
new file mode 100644
index 0000000000000000000000000000000000000000..18b3b9e50de5c7e2f57e168d8e5f203310508f3c
--- /dev/null
+++ b/user_config/.editorconfig
@@ -0,0 +1,30 @@
+# Config is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style for every file
+[*]
+# Set default charset
+charset = utf-8
+end_of_line = lf
+# Do not insert final new line at the end of file
+insert_final_newline = false
+# Automatically remove trailing space at end of line
+trim_trailing_whitespace = true
+# Size of indentation (either tabs or space)
+indent_size = 2
+# Type of indentation (either tabs or space)
+indent_style = space
+# Maximum length (in number of chars) for a line
+max_line_length = 80
+
+# Python specific syntax
+[*.py]
+# Size of indentation (either tabs or space)
+indent_size = 4
+
+# Yaml specific syntax
+[*.{yaml,yml}]
+# Maximum length (in number of chars) for a line
+max_line_length = 120
diff --git a/user_config/.gitignore b/user_config/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7938e741567ac01e4e80ae1a6d82b6d716b79cca
--- /dev/null
+++ b/user_config/.gitignore
@@ -0,0 +1,877 @@
+# Project Specific Gitignore
+
+.vimrc.local
+.tmuxinator.yml
+.old/
+.tmp/
+
+### BEGIN MKDOCS TEMPLATE ###
+### WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG ! ###
+### Modified content will be overwritten when updating.          ###
+
+# Created by https://www.toptal.com/developers/gitignore/api/linux,ansible,macos,windows,python,direnv,archive,archives,backup,emacs,vim,code,hugo,latex,nohup,ssh,tags,test,vagrant,virtualenv,zsh,dotenv,venv
+# Edit at https://www.toptal.com/developers/gitignore?templates=linux,ansible,macos,windows,python,direnv,archive,archives,backup,emacs,vim,code,hugo,latex,nohup,ssh,tags,test,vagrant,virtualenv,zsh,dotenv,venv
+
+### Ansible ###
+*.retry
+
+### Archive ###
+
+### Mostly from https://en.wikipedia.org/wiki/List_of_archive_formats
+
+## Archiving only
+# The traditional archive format on Unix-like systems, now used mainly for the
+# creation of static libraries.
+*.a
+*.ar
+# RPM files consist of metadata concatenated with (usually) a cpio archive.
+# Newer RPM systems also support other archives, as cpio is becoming obsolete.
+# cpio is also used with initramfs.
+*.cpio
+
+# A self-extracting archive that uses the Bourne shell (sh).
+*.shar
+# A system for storing multiple files. LBR archives typically contained files
+# processed by SQ, or the archive itself was compressed with SQ. LBR archives
+# that were compressed with SQ ended with the extension .LQR
+*.LBR
+# An archive format originally used mainly for archiving and distribution of
+# the exact, nearly-exact, or custom-modified contents of an optical storage
+# medium such as a CD-ROM or DVD-ROM. However, it can be used to archive the
+# contents of other storage media, selected partitions, folders, and/or files.
+# The resulting archive is typically optimized for convenient rendering to
+# (re-)writable CD or DVD media.
+*.iso
+# A library format used primarily on the Commodore 64 and 128 lines of
+# computers. This bears no resemblance to the DOS LBR format. While library files
+# were quick to implement (a number of programs exist to work with them) they are
+# crippled in that they cannot grow with use: once a file has been created it
+# cannot be amended (files added, changed or deleted) without recreating the
+# entire file.
+*.lbr
+# An archive format used by Mozilla for storing binary diffs. Used in
+# conjunction with bzip2.
+*.mar
+# A common archive format used on Unix-like systems. Generally used in
+# conjunction with compressors such as gzip, bzip2, compress or xz to create
+# .tar.gz, .tar.bz2, .tar.Z or tar.xz files.
+*.tar
+
+# Package managers
+# Red Hat Package Manager
+*.rpm
+# Debian package
+*.deb
+# MicroSoft Installer
+*.msi
+*.msm
+*.msp
+# Mozilla package installer
+*.xpi
+# Ruby Package
+*.gem
+
+
+### Archives ###
+# It's better to unpack these files and commit the raw source because
+# git has its own built in compression methods.
+*.7z
+*.jar
+*.rar
+*.zip
+*.gz
+*.gzip
+*.tgz
+*.bzip
+*.bzip2
+*.bz2
+*.xz
+*.lzma
+*.cab
+*.xar
+
+# Packing-only formats
+
+# Package management formats
+*.dmg
+*.egg
+*.txz
+
+### Backup ###
+*.bak
+*.gho
+*.ori
+*.orig
+*.tmp
+
+### Code ###
+.vscode/*
+!.vscode/tasks.json
+!.vscode/launch.json
+*.code-workspace
+
+### direnv ###
+.direnv
+.envrc
+.envrc.ini
+
+### dotenv ###
+.env
+
+### Emacs ###
+# -*- mode: gitignore; -*-
+*~
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+*.elc
+auto-save-list
+tramp
+.\#*
+
+# Org-mode
+.org-id-locations
+*_archive
+ltximg/**
+
+# flymake-mode
+*_flymake.*
+
+# eshell files
+/eshell/history
+/eshell/lastdir
+
+# elpa packages
+/elpa/
+
+# reftex files
+*.rel
+
+# AUCTeX auto folder
+/auto/
+
+# cask packages
+.cask/
+dist/
+
+# Flycheck
+flycheck_*.el
+
+# server auth directory
+/server/
+
+# projectiles files
+.projectile
+
+# directory configuration
+.dir-locals.el
+
+# network security
+/network-security.data
+
+
+### Hugo ###
+# Generated files by hugo
+/public/
+/resources/_gen/
+hugo_stats.json
+
+# Executable may be added to repository
+hugo.exe
+hugo.darwin
+hugo.linux
+
+### LaTeX ###
+## Core latex/pdflatex auxiliary files:
+*.aux
+*.lof
+*.log
+*.lot
+*.fls
+*.out
+*.toc
+*.fmt
+*.fot
+*.cb
+*.cb2
+.*.lb
+
+## Intermediate documents:
+*.dvi
+*.xdv
+*-converted-to.*
+# these rules might exclude image files for figures etc.
+# *.ps
+# *.eps
+# *.pdf
+
+## Generated if empty string is given at "Please type another file name for output:"
+.pdf
+
+## Bibliography auxiliary files (bibtex/biblatex/biber):
+*.bbl
+*.bcf
+*.blg
+*-blx.aux
+*-blx.bib
+*.run.xml
+
+## Build tool auxiliary files:
+*.fdb_latexmk
+*.synctex
+*.synctex(busy)
+*.synctex.gz
+*.synctex.gz(busy)
+*.pdfsync
+
+## Build tool directories for auxiliary files
+# latexrun
+latex.out/
+
+## Auxiliary and intermediate files from other packages:
+# algorithms
+*.alg
+*.loa
+
+# achemso
+acs-*.bib
+
+# amsthm
+*.thm
+
+# beamer
+*.nav
+*.pre
+*.snm
+*.vrb
+
+# changes
+*.soc
+
+# comment
+*.cut
+
+# cprotect
+*.cpt
+
+# elsarticle (documentclass of Elsevier journals)
+*.spl
+
+# endnotes
+*.ent
+
+# fixme
+*.lox
+
+# feynmf/feynmp
+*.mf
+*.mp
+*.t[1-9]
+*.t[1-9][0-9]
+*.tfm
+
+#(r)(e)ledmac/(r)(e)ledpar
+*.end
+*.?end
+*.[1-9]
+*.[1-9][0-9]
+*.[1-9][0-9][0-9]
+*.[1-9]R
+*.[1-9][0-9]R
+*.[1-9][0-9][0-9]R
+*.eledsec[1-9]
+*.eledsec[1-9]R
+*.eledsec[1-9][0-9]
+*.eledsec[1-9][0-9]R
+*.eledsec[1-9][0-9][0-9]
+*.eledsec[1-9][0-9][0-9]R
+
+# glossaries
+*.acn
+*.acr
+*.glg
+*.glo
+*.gls
+*.*-glg
+*.*-glo
+*.*-gls
+*.glsdefs
+*.lzo
+*.lzs
+
+# uncomment this for glossaries-extra (will ignore makeindex's style files!)
+# *.ist
+
+# gnuplottex
+*-gnuplottex-*
+
+# gregoriotex
+*.gaux
+*.gtex
+
+# htlatex
+*.4ct
+*.4tc
+*.idv
+*.lg
+*.trc
+*.xref
+
+# hyperref
+*.brf
+
+# knitr
+*-concordance.tex
+# TODO Comment the next line if you want to keep your tikz graphics files
+*.tikz
+*-tikzDictionary
+
+# listings
+*.lol
+
+# luatexja-ruby
+*.ltjruby
+
+# makeidx
+*.idx
+*.ilg
+*.ind
+
+# minitoc
+*.maf
+*.mlf
+*.mlt
+*.mtc
+*.mtc[0-9]*
+*.slf[0-9]*
+*.slt[0-9]*
+*.stc[0-9]*
+
+# minted
+_minted*
+*.pyg
+
+# morewrites
+*.mw
+
+# nomencl
+*.nlg
+*.nlo
+*.nls
+
+# pax
+*.pax
+
+# pdfpcnotes
+*.pdfpc
+
+# sagetex
+*.sagetex.sage
+*.sagetex.py
+*.sagetex.scmd
+
+# scrwfile
+*.wrt
+
+# sympy
+*.sout
+*.sympy
+sympy-plots-for-*.tex/
+
+# pdfcomment
+*.upa
+*.upb
+
+# pythontex
+*.pytxcode
+pythontex-files-*/
+
+# tcolorbox
+*.listing
+
+# thmtools
+*.loe
+
+# TikZ & PGF
+*.dpth
+*.md5
+*.auxlock
+
+# todonotes
+*.tdo
+
+# vhistory
+*.hst
+*.ver
+
+# easy-todo
+*.lod
+
+# xcolor
+*.xcp
+
+# xmpincl
+*.xmpi
+
+# xindy
+*.xdy
+
+# xypic precompiled matrices and outlines
+*.xyc
+*.xyd
+
+# endfloat
+*.ttt
+*.fff
+
+# Latexian
+TSWLatexianTemp*
+
+## Editors:
+# WinEdt
+*.sav
+
+# Texpad
+.texpadtmp
+
+# LyX
+*.lyx~
+
+# Kile
+*.backup
+
+# gummi
+.*.swp
+
+# KBibTeX
+*~[0-9]*
+
+# TeXnicCenter
+*.tps
+
+# auto folder when using emacs and auctex
+./auto/*
+*.el
+
+# expex forward references with \gathertags
+*-tags.tex
+
+# standalone packages
+*.sta
+
+# Makeindex log files
+*.lpz
+
+# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
+# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
+# Uncomment the next line to have this generated file ignored.
+#*Notes.bib
+
+### LaTeX Patch ###
+# LIPIcs / OASIcs
+*.vtc
+
+# glossaries
+*.glstex
+
+### Linux ###
+
+# temporary files which can be created if a process still has a handle open of
+# a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon

+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### Nohup ###
+nohup.out
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+downloads/
+eggs/
+.eggs/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+pytestdebug.log
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+doc/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in
+#   version control. However, in case of collaboration, if having
+#   platform-specific dependencies or dependencies having no cross-platform
+#   support, pipenv may install dependencies that don't work, or not install
+#   all needed dependencies.
+#Pipfile.lock
+
+# poetry
+#poetry.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+# .env
+.env/
+.venv/
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+pythonenv*
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# operating system-related files
+# file properties cache/storage on macOS
+*.DS_Store
+# thumbnail cache on Windows
+Thumbs.db
+
+# profiling data
+.prof
+
+
+### SSH ###
+**/.ssh/id_*
+**/.ssh/*_id_*
+**/.ssh/known_hosts
+
+### Tags ###
+# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
+TAGS
+.TAGS
+!TAGS/
+tags
+.tags
+!tags/
+gtags.files
+GTAGS
+GRTAGS
+GPATH
+GSYMS
+cscope.files
+cscope.out
+cscope.in.out
+cscope.po.out
+
+
+### Test ###
+### Ignore all files that could be used to test your code and
+### you wouldn't want to push
+
+# Reference https://en.wikipedia.org/wiki/Metasyntactic_variable
+
+# Most common
+*foo
+*bar
+*fubar
+*foobar
+*baz
+
+# Less common
+*qux
+*quux
+*bongo
+*bazola
+*ztesch
+
+# UK, Australia
+*wibble
+*wobble
+*wubble
+*flob
+*blep
+*blah
+*boop
+*beep
+
+# Japanese
+*hoge
+*piyo
+*fuga
+*hogera
+*hogehoge
+
+# Portugal, Spain
+*fulano
+*sicrano
+*beltrano
+*mengano
+*perengano
+*zutano
+
+# France, Italy, the Netherlands
+*toto
+*titi
+*tata
+*tutu
+*pipppo
+*pluto
+*paperino
+*aap
+*noot
+*mies
+
+# Other names that would make sense
+*tests
+*testsdir
+*testsfile
+*testsfiles
+*test
+*testdir
+*testfile
+*testfiles
+*testing
+*testingdir
+*testingfile
+*testingfiles
+*temp
+*tempdir
+*tempfile
+*tempfiles
+*tmp
+*tmpdir
+*tmpfile
+*tmpfiles
+*lol
+
+### Vagrant ###
+# General
+.vagrant/
+
+# Log files (if you are creating logs in debug mode, uncomment this)
+# *.log
+
+### Vagrant Patch ###
+*.box
+
+### venv ###
+# Virtualenv
+# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
+[Bb]in
+[Ii]nclude
+[Ll]ib
+[Ll]ib64
+[Ll]ocal
+[Ss]cripts
+pyvenv.cfg
+.venv
+pip-selfcheck.json
+
+### Vim ###
+# Swap
+[._]*.s[a-v][a-z]
+!*.svg  # comment out if you don't need vector files
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+
+# Session
+Session.vim
+Sessionx.vim
+
+# Temporary
+.netrwhist
+# Auto-generated tag files
+# Persistent undo
+[._]*.un~
+
+### VirtualEnv ###
+# Virtualenv
+# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.msix
+
+# Windows shortcuts
+*.lnk
+
+### Zsh ###
+# Zsh compiled script + zrecompile backup
+*.zwc
+*.zwc.old
+
+# Zsh completion-optimization dumpfile
+*zcompdump*
+
+# Zsh zcalc history
+.zcalc_history
+
+# A popular plugin manager's files
+._zinit
+.zinit_lstupd
+
+# zdharma/zshelldoc tool's files
+zsdoc/data
+
+# robbyrussell/oh-my-zsh/plugins/per-directory-history plugin's files
+# (when set-up to store the history in the local directory)
+.directory_history
+
+# MichaelAquilina/zsh-autoswitch-virtualenv plugin's files
+# (for Zsh plugins using Python)
+
+# Zunit tests' output
+/tests/_output/*
+!/tests/_output/.gitkeep
+
+# End of https://www.toptal.com/developers/gitignore/api/linux,ansible,macos,windows,python,direnv,archive,archives,backup,emacs,vim,code,hugo,latex,nohup,ssh,tags,test,vagrant,virtualenv,zsh,dotenv,venv
+
+### END MKDOCS TEMPLATE ###
+
+# ******************************************************************************
+# VIM MODELINE
+# vim: ft=gitignore
+# ******************************************************************************
diff --git a/user_config/.gitlab-ci.yml b/user_config/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0ed8f5a8dbb98aa933ce9a8ceb8fd74e03e73c7e
--- /dev/null
+++ b/user_config/.gitlab-ci.yml
@@ -0,0 +1,162 @@
+---
+# GLOBAL CONFIGURATION
+# =============================================================================
+# YAML Anchors
+# -----------------------------------------------------------------------------
+# This CI file haevily make use of YAML anchors for multiple reasons:
+#   - Avoid writing twice the same block of codes
+#   - Resuse block of codes
+#   - Make the CI more generic and easily extensible or modifiable
+# See https://docs.gitlab.com/ee/ci/yaml/README.html#anchors
+
+# Define base workflow
+# https://docs.gitlab.com/ee/ci/yaml/README.html#workflow
+workflow:
+  rules:
+    # Do not run CI when commit title have
+    # WIP, NO-CI or 🚧 (gitmoji for "work in progress", aka :construction:)
+    - if: $CI_COMMIT_TITLE =~ /.*(WIP|NO-CI|🚧|:construction:).*/
+      when: never
+    # Do not run CI if repo is not on gitlab.liris.cnrs.fr
+    - if: $CI_SERVER_HOST =~ /^gitlab.liris.cnrs.fr/
+
+### BEGIN MKDOCS TEMPLATE ###
+### WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG ! ###
+### Modified content will be overwritten when updating. ###
+
+# Include other gitlab-ci.yml files
+include:
+  - local: docs/.gitlab-ci.yml
+
+### END MKDOCS TEMPLATE ###
+
+# Stages jobs will pass through with anchors to avoid updating stage in multiple
+# place within this file. Now renaming a stage can be done directly after the
+# anchor name below.
+# https://docs.gitlab.com/ee/ci/yaml/README.html#stage
+stages:
+  - &pre_test pre_test
+  - &test test
+  - &build build
+  - &deploy deploy
+  - &post_deploy post_deploy
+
+# Global variables shared for all jobs
+# https://docs.gitlab.com/ee/ci/yaml/README.html#variables
+variables:
+  PIP_CACHE_DIR: "${CI_PROJECT_DIR}/.cache/pip"
+
+# Images anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#image
+# Basic docker image -> docker:latest image
+.image_docker: &image_docker
+  image: docker:latest
+
+# Before scripts anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#before_script
+.before_script_python_dependencies: &before_script_python_dependencies
+  before_script:
+    # Add python dependencies
+    - apk update
+    # Install base package required for mkdocs builds
+    - apk add --no-cache --update-cache
+        build-base
+        python3-dev
+        py3-pip
+        py3-virtualenv
+        bash
+        git
+        gcc
+    # Create virtual environment
+    - virtualenv .venv
+    # Activate virtual environment
+    - source .venv/bin/activate
+
+# Rules anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#rules
+# Defining bash regexp test
+.rules_regexp:
+  - &rules_regexp_dev $CI_COMMIT_BRANCH =~ /^((release|feature|hotfix|bugfix)-|merge_request_)*/
+  - &rules_regexp_pre_prod $CI_COMMIT_BRANCH =~ /(develop|master)/
+  - &rules_regexp_prod $CI_COMMIT_TAG
+
+# Defining rules that now replace only to run jobs under specific condition
+# and define variables
+.rules_dev: &rules_dev
+  if: *rules_regexp_dev
+  variables:
+    CI_DEPLOY_TYPE: "dev"
+
+.rules_pre_prod: &rules_pre_prod
+  if: *rules_regexp_pre_prod
+  variables:
+    CI_DEPLOY_TYPE: "pre_prod"
+
+.rules_prod: &rules_prod
+  if: *rules_regexp_prod
+  variables:
+    CI_DEPLOY_TYPE: "prod"
+
+# Tag anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#tag
+# Run jobs in regular docker
+.tag_docker: &tag_docker
+  tags:
+    - docker
+
+# Stages anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#stage
+# This can be seen as overbloated while overuse of YAML anchors, but the
+# advantage is that if we rename a stage, we will just need to rename it at the
+# start of this CI.
+.stage_pre_test: &stage_pre_test
+  stage: *pre_test
+
+.stage_test: &stage_test
+  stage: *test
+
+.stage_build: &stage_build
+  stage: *build
+
+.stage_deploy: &stage_deploy
+  stage: *deploy
+
+.stage_post_deploy: &stage_post_deploy
+  stage: *post_deploy
+
+# =============================================================================
+# CI JOBS
+# =============================================================================
+# Jobs in test stage
+# -----------------------------------------------------------------------------
+test_tox_format_python:
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *stage_test
+  <<: *before_script_python_dependencies
+  script:
+    # Install python tox
+    - pip3 install tox
+    # Run tox
+    - tox -e format_python
+
+test_tox_format_shell:
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *stage_test
+  <<: *before_script_python_dependencies
+  script:
+    # Install python tox
+    - pip3 install tox
+    # Run tox
+    - tox -e format_shell
+
+# *****************************************************************************
+# VIM MODELINE
+# vim: fdm=indent
+# *****************************************************************************
diff --git a/user_config/.yamllint b/user_config/.yamllint
new file mode 100644
index 0000000000000000000000000000000000000000..67598ce0364db49fb507fd1e794ba2607a9c2239
--- /dev/null
+++ b/user_config/.yamllint
@@ -0,0 +1,36 @@
+---
+# Based on ansible-lint config
+extends: default
+
+ignore: |
+  .*
+
+rules:
+  braces:
+    max-spaces-inside: 1
+    level: error
+  brackets:
+    max-spaces-inside: 1
+    level: error
+  colons:
+    max-spaces-after: -1
+    level: error
+  commas:
+    max-spaces-after: -1
+    level: error
+  comments: disable
+  comments-indentation: disable
+  document-start: disable
+  empty-lines:
+    max: 3
+    level: error
+  hyphens:
+    level: error
+  indentation: disable
+  key-duplicates: enable
+  line-length: disable
+  new-line-at-end-of-file: disable
+  new-lines:
+    type: unix
+  trailing-spaces: disable
+  truthy: disable
diff --git a/user_config/LICENSE b/user_config/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..38175a42bf945894a6498017cacc882acbe09001
--- /dev/null
+++ b/user_config/LICENSE
@@ -0,0 +1,28 @@
+MIT License
+
+Copyright (c) 2020 Romain Deville <code@romaindeville.fr>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+<!-- BEGIN MKDOCS TEMPLATE -->
+<!--
+WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+Modified content will be overwritten when updating
+-->
+<!-- END MKDOCS TEMPLATE -->
diff --git a/user_config/README.md b/user_config/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d927077de1c7aa0a66658c3d090ae6d5f2edfbfe
--- /dev/null
+++ b/user_config/README.md
@@ -0,0 +1,83 @@
+<div align="center" style="text-align: center;">
+
+  <!-- Project Title -->
+  <a href="<TPL:REPO_URL>">
+    <img src="docs/assets/img/meta/<TPL:REPO_NAME>_logo.png" width="100px">
+    <h1><TPL:REPO_NAME_FIRST_UPPERCASE></h1>
+  </a>
+
+  <!-- Project Badges -->
+  [![License][license_badge]][license]
+  [![Build Status][build_status_badge]][build_status]
+
+--------------------------------------------------------------------------------
+
+TODO: Short description as written in `docs/_data/repo.yaml`
+
+--------------------------------------------------------------------------------
+
+[repo_url]: <TPL:REPO_URL>
+[license_badge]: https://img.shields.io/badge/License-MIT%2FBeer%20Ware-blue?style=flat-square&logo=open-source-initiative
+[license]: LICENSE
+[build_status_badge]: <TPL:REPO_URL>/badges/master/pipeline.svg?style=flat-square&logo=appveyor
+[build_status]: <TPL:REPO_URL>/commits/master
+
+## Table of Content
+
+* [Project Documentation](#project-documentation)
+
+<!-- BEGIN MKDOCS TEMPLATE -->
+<!--
+     WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+     Modified content will be overwritten when updating
+-->
+
+## Project Documentation
+
+The complete documentation of the project can be accessed via its [Online
+Documentation][online_doc].
+
+If, for any reason, the link to the [Online Documentation][online_doc] is
+broken, you can generate its documention locally on your computer (since the
+documentation is jointly stored within the repository).
+
+To do so, you will need the following requirements:
+
+  - Python >= 3.8
+  - Pip3 with Python >= 3.8
+
+First setup a temporary python virtual environment and activate it:
+
+```bash
+# Create the temporary virtual environment
+python3 -m venv .temporary_venv
+# Activate it
+source .temporary_venv/bin/activate
+```
+Now, install required dependencies to render the documentation using
+[mkdocs][mkdocs] in the python virtual environment:
+
+```bash
+pip3 install -r requirements.docs.txt
+```
+
+Now you can easily render the documentation using [mkdocs][mkdocs] through the
+usage of the following command (some logs will be outputed to stdout):
+
+```bash
+# Assuming you are at the root of the repo
+# If there is a `mkdocs.local.yml`
+mkdocs serve -f mkdocs.local.yml
+# If there is no `mkdocs.local.yml`, only `mkdocs.yml`
+mkdocs serve
+```
+
+You can now browse the full documentation by visiting
+[http://localhost:8000][localhost].
+
+[localhost]: https://localhost:8000
+[mkdocs]: https://www.mkdocs.org/
+
+<!-- END MKDOCS TEMPLATE -->
+
+[online_doc]: <TPL:REPO_ONLINE_DOC_URL>/index.html
diff --git a/user_config/docs/.gitlab-ci.yml b/user_config/docs/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..248d657364b62a5103cf120664880f7675d3237a
--- /dev/null
+++ b/user_config/docs/.gitlab-ci.yml
@@ -0,0 +1,421 @@
+---
+# GLOBAL CONFIGURATION
+# =============================================================================
+# YAML Anchors
+# -----------------------------------------------------------------------------
+# This CI file haevily make use of YAML anchors for multiple reasons:
+#   - Avoid writing twice the same block of codes
+#   - Resuse block of codes
+#   - Make the CI more generic and easily extensible or modifiable
+# See https://docs.gitlab.com/ee/ci/yaml/README.html#anchors
+
+# Define base workflow
+# https://docs.gitlab.com/ee/ci/yaml/README.html#workflow
+workflow:
+  rules:
+    # Do not run CI when commit title have
+    # WIP, NO-CI or 🚧 (gitmoji for "work in progress", aka :construction:)
+    - if: $CI_COMMIT_TITLE =~ /.*(WIP|NO-CI|🚧|:construction:).*/
+      when: never
+    # Do not run CI if repo is not on framagit
+    - if: $CI_SERVER_HOST =~ /^gitlab.liris.cnrs.fr/
+
+# Stages jobs will pass through with anchors to avoid updating stage in multiple
+# place within this file. Now renaming a stage can be done directly after the
+# anchor name below.
+# https://docs.gitlab.com/ee/ci/yaml/README.html#stage
+stages:
+  - &pre_test pre_test
+  - &test test
+  - &build build
+  - &deploy deploy
+  - &post_deploy post_deploy
+
+# Global variables shared for all jobs
+# https://docs.gitlab.com/ee/ci/yaml/README.html#variables
+variables:
+  PIP_CACHE_DIR: "${CI_PROJECT_DIR}/.cache/pip"
+
+# Images anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#image
+# Basic docker image -> docker:latest image
+.image_docker: &image_docker
+  image: docker:latest
+
+# Before scripts anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#before_script
+.before_script_python_dependencies: &before_script_python_dependencies
+  # Add python dependencies
+  - apk update
+  # Install base package required for mkdocs builds
+  - apk add --no-cache --update-cache
+      build-base
+      python3-dev
+      py3-pip
+      py3-virtualenv
+      bash
+      git
+      gcc
+  # Create virtual environment
+  - virtualenv .venv
+  # Activate virtual environment
+  - source .venv/bin/activate
+
+.before_script_prepare_deployment: &before_script_prepare_deployment
+  # Add rsync dependencies
+  - apk update
+  - apk add --no-cache --update-cache
+      rsync
+      git
+  # Ensure ssh configuration folder exists
+  - mkdir -p ~/.ssh
+  # Ensure permission on this folder are right
+  - chmod 700 ~/.ssh
+  # Trust the perso LIRIS website
+  - echo "${SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts
+  # Ensure permission on the previously written file are right
+  - chmod 600 ~/.ssh/known_hosts
+  # Start the SSH agent
+  - eval $(ssh-agent -s)
+  # Add the private SSH key to be able to connect to the perso LIRIS website
+  - echo "${SSH_PRIVATE_KEY}" | tr -d '\r' | ssh-add -
+
+.before_script_export_variable: &before_script_export_variable
+  # Update values of some variables depending on the CI_DEPLOY_TYPE
+  # This could be shortened but gitlab-ci does not support bash variable substitution
+  - |
+    case ${CI_DEPLOY_TYPE} in
+      "dev")
+        export RSYNC_DEST="${RSYNC_DEST}/dev/"
+        export ONLINE_DEST="${ONLINE_DEST}/dev/"
+      ;;
+      "pre_prod")
+        export RSYNC_DEST="${RSYNC_DEST}/pre_prod/"
+        export ONLINE_DEST="${ONLINE_DEST}/pre_prod/"
+      ;;
+      "prod")
+        export RSYNC_DEST="${RSYNC_DEST}/"
+        export ONLINE_DEST="${ONLINE_DEST}/"
+      ;;
+      *)
+        echo -e "\e[31mERROR - Variable \`CI_DEPLOY_TYPE\` is not defined !"
+        return 1
+      ;;
+    esac
+
+# Rules anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#rules
+# Defining bash regexp test
+.rules_regexp:
+  - &rules_regexp_dev $CI_COMMIT_BRANCH =~ /^((release|feature|hotfix|bugfix)-|merge_request_)*/
+  - &rules_regexp_pre_prod $CI_COMMIT_BRANCH =~ /(develop|master)/
+  - &rules_regexp_prod $CI_COMMIT_TAG
+  - &rules_regexp_trigger_main (($CI_COMMIT_BRANCH =~ /(develop|master)/) || $CI_COMMIT_TAG) && ($MAIN_PROJECT != null && $MAIN_PROJECT != $CI_PROJECT_PATH)
+  - &rules_regexp_trigger_info (($CI_COMMIT_BRANCH =~ /(develop|master)/) || $CI_COMMIT_TAG) && $MAIN_PROJECT == null
+
+# Defining rules that now replace only to run jobs under specific condition
+# and define variables
+.rules_dev: &rules_dev
+  if: *rules_regexp_dev
+  variables:
+    CI_DEPLOY_TYPE: "dev"
+
+.rules_pre_prod: &rules_pre_prod
+  if: *rules_regexp_pre_prod
+  variables:
+    CI_DEPLOY_TYPE: "pre_prod"
+
+.rules_prod: &rules_prod
+  if: *rules_regexp_prod
+  variables:
+    CI_DEPLOY_TYPE: "prod"
+
+.rules_trigger_main: &rules_trigger_main
+  if: *rules_regexp_trigger_main
+
+.rules_trigger_info: &rules_trigger_info
+  if: *rules_regexp_trigger_info
+
+# Tag anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#tag
+# Run jobs in regular docker
+.tag_docker: &tag_docker
+  tags:
+    - docker
+
+# Stages anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#stage
+# This can be seen as overbloated while overuse of YAML anchors, but the
+# advantage is that if we rename a stage, we will just need to rename it at the
+# start of this CI.
+.stage_pre_test: &stage_pre_test
+  stage: *pre_test
+
+.stage_test: &stage_test
+  stage: *test
+
+.stage_build: &stage_build
+  stage: *build
+
+.stage_deploy: &stage_deploy
+  stage: *deploy
+
+.stage_post_deploy: &stage_post_deploy
+  stage: *post_deploy
+
+# Cache anchors
+# -----------------------------------------------------------------------------
+# https://docs.gitlab.com/ee/ci/yaml/README.html#cache
+# Setup a global cache to avoid having to reinstall pip and package dependencies
+# every time.
+# **REMARK** For this to work, runners must be on the same server and docker
+# executor must mount /cache
+.cache_python: &cache_python
+  cache:
+    # Cache dependencies shared within the same branche
+    # https://docs.gitlab.com/ee/ci/yaml/README.html#cachekey
+    key: "$CI_COMMIT_BRANCH"
+    # Let us cache python dependencies
+    # https://docs.gitlab.com/ee/ci/caching/#caching-python-dependencies
+    paths:
+      - .cache/pip
+      - .venv/
+    # Save cache all the time, even if jobs failed
+    # https://docs.gitlab.com/ee/ci/yaml/README.html#cachewhen
+    when: always
+
+.cache_python_pull: &cache_python_pull
+  cache:
+    # Cache dependencies shared across all branches but separated by jobs
+    # https://docs.gitlab.com/ee/ci/yaml/README.html#cachekey
+    key: "$CI_COMMIT_BRANCH"
+    # Let us cache python dependencies
+    # https://docs.gitlab.com/ee/ci/caching/#caching-python-dependencies
+    paths:
+      - .cache/pip
+      - .venv/
+    # Setup policy to only pull python cache when we know jobs does not update
+    # content of python cache.
+    # https://docs.gitlab.com/ee/ci/yaml/README.html#cachepolicy
+    policy: pull
+
+# =============================================================================
+# CI JOBS
+# =============================================================================
+# Jobs in pre_test stage
+# -----------------------------------------------------------------------------
+# Template jobs script to ensure required variables are sets.
+script_pre_test_ensure_variable: &script_pre_test_ensure_variable
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *stage_pre_test
+  before_script:
+    - *before_script_export_variable
+  script:
+    - export ERROR="false"
+    - |
+      if [[ -z "${SSH_KNOWN_HOSTS}" ]]
+      then
+        echo -e "\e[31mERROR - Variable \`SSH_KNOWN_HOSTS)\` is not defined !"
+        export ERROR="true"
+      fi
+    - |
+      if [[ -z "${SSH_PRIVATE_KEY}" ]]
+      then
+        echo -e "\e[31mERROR - Variable \`SSH_PRIVATE_KEY\` is not defined !"
+        export ERROR="true"
+      fi
+    - |
+      if [[ -z "${ONLINE_DEST}" ]]
+      then
+        echo -e "\e[31mERROR - Variable \`ONLINE_DEST\` is not defined !"
+        export ERROR="true"
+      fi
+    - |
+      if [[ -z "${RSYNC_DEST}" ]]
+      then
+        echo -e "\e[31mERROR - Variable \`RSYNC_DEST\` is not defined !"
+        export ERROR="true"
+      fi
+    - |
+      if [[ "${ERROR}" == "true" ]]
+      then
+        echo -e "\e[31mERROR - At least one required variable is not defined !"
+        return 1
+      fi
+  rules:
+    - *rules_prod
+    - *rules_pre_prod
+    - *rules_dev
+
+# Jobs in test stage
+# -----------------------------------------------------------------------------
+test_build_local:
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *cache_python
+  <<: *stage_test
+  before_script:
+    - *before_script_python_dependencies
+  script:
+    # Install python test requirements
+    - pip3 install -r requirements.docs.txt
+    # Build local documentation
+    - mkdocs build -f mkdocs.local.yml -d site_local
+  rules:
+    - exists:
+      - mkdocs.local.yaml
+
+test_build:
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *cache_python
+  <<: *stage_test
+  before_script:
+    - *before_script_python_dependencies
+  script:
+    # Install python test requirements
+    - pip3 install -r requirements.docs.txt
+    # Build local documentation
+    - mkdocs build -d site
+
+# Jobs in build stage
+# -----------------------------------------------------------------------------
+build_html:
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *cache_python_pull
+  <<: *stage_build
+  before_script:
+    - *before_script_python_dependencies
+  script:
+    # Install python documentations requirements
+    - pip3 install -r requirements.docs.txt
+    # Build the documentation
+    - mkdocs build
+  artifacts:
+    paths:
+      - site/
+
+# Jobs in deploy stage
+# -----------------------------------------------------------------------------
+# Template jobs script deploy previously built html documentation.
+script_deploy_html: &script_deploy_html
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *stage_deploy
+  needs:
+    - build_html
+  before_script:
+    - *before_script_export_variable
+    - *before_script_prepare_deployment
+  script:
+    - git fetch --all
+    - export LAST_TAG="$(git describe --tags `git rev-list --tags --max-count=1`)"
+    - export LAST_TAG="${LAST_TAG/v/}"
+    - export LAST_TAG="${LAST_TAG%.*}"
+    - |
+      case "${CI_DEPLOY_TYPE}" in
+        "dev")
+          if [[ -n "${RSYNC_BASE_PATH}" ]];
+          then
+            export PROJECT_PATH="/${CI_COMMIT_BRANCH}/${RSYNC_BASE_PATH}/";
+          else
+            export PROJECT_PATH="/${CI_COMMIT_BRANCH}/"
+          fi
+          ;;
+        "pre_prod")
+          if [[ -n "${RSYNC_BASE_PATH}" ]];
+          then
+            export PROJECT_PATH="/${CI_COMMIT_BRANCH}/${RSYNC_BASE_PATH}/";
+          else
+            export PROJECT_PATH="/${CI_COMMIT_BRANCH}/"
+          fi
+          ;;
+        "prod")
+          if [[ -n "${RSYNC_BASE_PATH}" ]];
+          then
+            export PROJECT_PATH="/${RSYNC_BASE_PATH}/";
+          else
+            export PROJECT_PATH="/"
+          fi
+          ;;
+      esac
+    - export RSYNC_PATH="${PROJECT_PATH}${LAST_TAG}"
+    - export ONLINE_PATH="${ONLINE_DEST}${PROJECT_PATH}latest"
+    - mkdir -p "tmp/${RSYNC_PATH}"
+    - mv site/* "tmp/${RSYNC_PATH}/"
+    - |
+      if [[ -f "tmp/${RSYNC_PATH}/versions.json" ]]
+      then
+        cp tmp/${RSYNC_PATH}/versions.json tmp/${RSYNC_PATH}/../versions.json
+      fi
+    - ln -s "${LAST_TAG}" "latest"
+    - mv "latest" "tmp/${PROJECT_PATH}"
+    - echo -e "
+      <!DOCTYPE html>\n
+      <html>\n
+      <head>\n
+        <meta charset='utf-8'>\n
+        <title>Redirecting</title>\n
+        <noscript>\n
+          <meta http-equiv='refresh' content='1; url=${ONLINE_PATH}' />\n
+        </noscript>\n
+        <script>\n
+          window.location.replace('${ONLINE_PATH}');\n
+        </script>\n
+      </head>\n
+      <body>\n
+        Redirecting to <a href='${ONLINE_PATH}'>${ONLINE_PATH}</a>...\n
+      </body>\n
+      </html>" > tmp/${PROJECT_PATH}/index.html
+    - rsync -Oavz "tmp/" "${RSYNC_DEST}"
+  rules:
+    - *rules_prod
+    - *rules_pre_prod
+    - *rules_dev
+
+# Jobs in post_deploy stage
+# -----------------------------------------------------------------------------
+trigger_main_repo:
+  <<: *stage_post_deploy
+  trigger:
+    include:
+      - project: $MAIN_PROJECT
+        ref: $CI_COMMIT_BRANCH
+        file: $MAIN_PROJECT_CI_PATH/.gitlab-ci.yml
+    strategy: depend
+  variables:
+    MAIN_PROJECT_CI_PATH: ${MAIN_PROJECT_CI_PATH:-"."}
+  rules:
+    - *rules_trigger_main
+
+inform_triggers_variables:
+  <<: *tag_docker
+  <<: *image_docker
+  <<: *stage_post_deploy
+  script:
+    - |
+      if [[ -z "${MAIN_PROJECT}" ]]
+      then
+       echo -e "\e[32m
+          INFO - To trigger a main repo documentation CI, you can set \\n
+          INFO - variable \`MAIN_PROJECT\`. Otherwise, you have nothing\\n
+          INFO - to do. If the CI you want to run is not at the root of\\n
+          INFO - the repo defined by variable \`MAIN_PROJECT\`. You can\\n
+          INFO - set the variable \`MAIN_PROJECT_CI_PATH\` which define\\n
+          INFO - the path to the file \`gitlab-ci.yaml\` to be run in  \\n
+          INFO - the \`MAIN_PROJECT\`."
+      fi
+  rules:
+    - *rules_trigger_info
+
+# *****************************************************************************
+# VIM MODELINE
+# vim: fdm=indent
+# *****************************************************************************
diff --git a/user_config/docs/_data/vars.yaml b/user_config/docs/_data/vars.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..020a79c7d23ff5c5d38347426280b22dea849631
--- /dev/null
+++ b/user_config/docs/_data/vars.yaml
@@ -0,0 +1,91 @@
+# Extra Data Information & Customization
+# ===========================================================================
+# Dictionnary storing variables to be used as "Jinja2" variables within
+# markdown files and _data/plugins.py
+
+# Mkdocs.yaml
+# ---------------------------------------------------------------------------
+# Here you can overwrite main key you could find in mkdocs.yaml
+
+# The name of your site, if not specified, will be the entry `name` of the repo in
+# `_data/repo_name.yaml`
+#site_name: "Your Site Name"
+
+# The site description of your site, if not specified will be the description
+# of the repo in `_data/repo_name.yaml`
+#site_desc: "A short description"
+
+# The url of your site, if not specified, then the site_url will be build from
+# the key `site_base_url` below and the `url_slug_with_namespace` in
+# `_data/repo_name.yaml`. If `site_base_url` is not specified, then value of
+# `site_url` will not be overwritten.
+#site_url: "https://my_site.tld"
+
+# The name or company which old the copyright. No need to specify any date
+# as it will be built based on the first commit of your repo. If not specify,
+# then no copyright will be shown on the footer of the documentation.
+copyright: "LIRIS - PAGoDA"
+
+# Name of your repo, if not specified, will be the key `mkdocs_repo_name` in
+# `_data/repo_name.yaml` If value is EXACTLY "!!git_platform", then the value
+# will be `git_platform["name"]` (see below).
+#repo_name: "My Repo Name"
+
+# URL to the source code of your repo. If not specified, will be build from
+# `git_platform["url"]` (see below) and `repo_name["git_slug_with_namespace"]`
+# in `_data/repo_name.yaml`.
+#repo_url: "https://mygit.tld/namespace/repo_name
+
+# You can override every entry of the `theme` key in `mkdocs.yaml`, here.
+# Usefull to override templated mkdocs.
+#
+# REMARK, ONLY FOR MATERIAL-MKDOCS THEME
+#   If `theme["logo"]` is not specified, i.e. path to the logo image, then it
+#   will be set to the value of the key `repo_name["logo"]` in
+#   `_data/repo_name.yaml` if specified.
+#
+#   If `theme["favicon"]` is not specified, i.e. path to the favicon image,
+#   then it will be set to the value of the key `repo_name["logo"]` in
+#   `_data/repo_name.yaml` if specified.
+#
+#   If `theme["icon"]["repo"]` is not specified, i.e. icon "path" (see
+#   https://squidfunk.github.io/mkdocs-material/reference/icons-emojis/) that
+#   will be shown on the top rigt corner in front off the repo name, then it
+#   will be set to the value of the key `git_platform["icon"]` (see below).
+#theme:
+#  logo: "path/to/logo.svg"
+#  icon:
+#    repo:  fontawesome/brands/gitlab
+#  favicon: "path/to/favicon.svg"
+
+# Main repo configuration
+# ---------------------------------------------------------------------------
+# Here you can specify variable about your main repo documentation
+
+# The base url of your site, e.g. if you are using multiple nested
+# documentation build with monorepo, you might want to share the same base URL
+# for all your repo, then build link from the repo["url_slug_with_namespace"].
+site_base_url: "https://projet.liris.cnrs.fr/pagoda"
+
+
+# Git platform
+# ---------------------------------------------------------------------------
+# In this REQUIRED section you will be able to specify some information for you
+# git platform hosting your repo. This section will be used to automatically
+# setup configuration for mkdocs such as `repo_url`, theme["icon"]["repo"] etc.
+
+# Main dict entry
+git_platform:
+  # The logo of the git platform you use. Not used in mkdocs configuration but
+  # can be used in markdown documentation file.
+  logo: " "
+  # Icon "path" (see
+  # https://squidfunk.github.io/mkdocs-material/reference/icons-emojis/) that
+  # will be shown on the top rigt corner in front off the repo name if not
+  # specified in `theme["icon"]["repo"]`.
+  icon: "fontawesome/brands/gitlab"
+  # Name of the platform you use.
+  name: "Gitlab LIRIS"
+  # URL of the platform you use, to be able to set `repo_url` for mkdocs
+  # configuration.
+  url: "https://gitlab.liris.cnrs.fr/"
diff --git a/user_config/docs/about/code_of_conduct.md b/user_config/docs/about/code_of_conduct.md
new file mode 100644
index 0000000000000000000000000000000000000000..24ff31057e8d4bf09785a4628be885252e6b05fb
--- /dev/null
+++ b/user_config/docs/about/code_of_conduct.md
@@ -0,0 +1,140 @@
+{% set curr_repo=subs("TODO") %}
+
+<!-- BEGIN MKDOCS TEMPLATE -->
+<!--
+WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+Modified content will be overwritten when updating
+-->
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+  overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+  advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+  address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at:
+{% for i_maintainer in curr_repo.maintainers %}
+  - **[📧 {{ i_maintainer.name }} <{{ i_maintainer.mail }}>](mailto:{{ i_maintainer.mail }})**
+{% endfor %}
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior,  harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the
+[Contributor Covenant](https://www.contributor-covenant.org),
+version 2.0, available at
+[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq).
+Translations are available at
+[https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations).
+
+<!-- END MKDOCS TEMPLATE -->
diff --git a/user_config/docs/about/contributing.md b/user_config/docs/about/contributing.md
new file mode 100644
index 0000000000000000000000000000000000000000..3d6e9ce43010fa92d5a39a0a9e6b5d8ded435406
--- /dev/null
+++ b/user_config/docs/about/contributing.md
@@ -0,0 +1,54 @@
+{% set curr_repo=subs("TODO") %}
+
+<!-- BEGIN MKDOCS TEMPLATE -->
+<!--
+WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+Modified content will be overwritten when updating
+-->
+
+# Contributing
+
+This project welcomes contributions from developers and users in the open source
+community. Contributions can be made in a number of ways, a few examples are :
+
+  * Code patch via pull requests
+  * Documentation improvements
+  * Bug reports and patch reviews
+  * Proposition of new features
+  * etc.
+
+## Reporting an Issue
+
+Please include as much details as you can when reporting an issue in the [issue
+trackers][issue_tracker]. If the problem is visual (for instance, wrong
+documentation rendering) please add a screenshot.
+
+[issue_tracker]: {{ git_platform.url }}{{ curr_repo.git_slug_with_namespace }}/-/issues
+
+## Submitting Pull Requests
+
+Once you are happy with your changes or you are ready for some feedback, push it
+to your fork and send a pull request. For a change to be accepted it will most
+likely need to have tests and documentation if it is a new feature.
+
+For more information, you can refers to the main [developers
+guides][developers_guides] which is the common resources I use for all
+my projects. There you will find:
+
+  * [Syntax Guide][syntax_guide], which describe syntax guidelines per language
+    to follow if you want to contribute.
+  * [Contributing workflow][contributing_workflow], which provide an example
+   of the workflow I used for the development.
+
+[developers_guides]: {{ site_base_url }}/latest/dev_guides/index.html
+[syntax_guide]: {{ site_base_url }}/latest/dev_guides/style_guides/index.html
+[contributing_workflow]: {{ site_base_url }}/latest/dev_guides/developer_guidelines.html
+
+## Community
+
+Finally, every member of the community should follow this [Code of
+conduct][code_of_conduct].
+
+[code_of_conduct]: code_of_conduct.md
+
+<!-- END MKDOCS TEMPLATE -->
diff --git a/user_config/docs/about/data_privacy.md b/user_config/docs/about/data_privacy.md
new file mode 100644
index 0000000000000000000000000000000000000000..ed984630b86a220337782f220aa1120da19b1925
--- /dev/null
+++ b/user_config/docs/about/data_privacy.md
@@ -0,0 +1,21 @@
+# Data Privacy
+
+In itself, [Material for MkDocs][mkdocs_material] theme use for this
+documentation does not perform any tracking and should adhere to the General
+Data Protection Regulation (GDPR).
+
+Moreover, no third-party services are used in this documentation, i.e. it does
+not use google-fonts, google-analytics, neither Disqus.
+
+Any rendering tools, such as [tablesort][tablesort], etc. are served locally
+without using CDN or call to external website. The aims are to :
+
+- Render the documentation with stable tools (i.e. documentation may not be
+  using latest version of previously mentionned tools),
+- Avoid useless network requests to external CDN,
+- Render the documentation even if the user  has web browser add-on which filter
+  javascript such as [uMatrix][uMatrix].
+
+[mkdocs_material]: https://squidfunk.github.io/mkdocs-material/data-privacy/
+[tablesort]: https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/tablesort.min.js
+[uMatrix]: https://github.com/gorhill/uMatrix
diff --git a/user_config/docs/about/index.md b/user_config/docs/about/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..554f348e9e39e6f4d591d0353118c8a5dc17a1ac
--- /dev/null
+++ b/user_config/docs/about/index.md
@@ -0,0 +1,9 @@
+# About
+
+In this part of the documentation, you can consult:
+
+  - [Code of Conduct](code_of_conduct.md)
+  - [Contributing](contributing.md)
+  - [Data Privacy](data_privacy.md)
+  - [License](license.md)
+  - [Release Notes](release_notes.md)
diff --git a/user_config/docs/about/license.md b/user_config/docs/about/license.md
new file mode 100644
index 0000000000000000000000000000000000000000..3d1eb864857f94b31dc4d7c8159d5fa996c1fafc
--- /dev/null
+++ b/user_config/docs/about/license.md
@@ -0,0 +1,36 @@
+{% set curr_repo=subs("TODO") %}
+
+<!-- BEGIN MKDOCS TEMPLATE -->
+<!--
+WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+Modified content will be overwritten when updating
+-->
+
+
+## MIT License
+
+{{ date_copyright }}
+
+{% for i_maintainer in curr_repo.maintainers %}
+  - [{{ i_maintainer.name }}](mailto:{{ i_maintainer.mail }})
+{% endfor %}
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+<!-- END MKDOCS TEMPLATE -->
diff --git a/user_config/docs/about/release_notes.md b/user_config/docs/about/release_notes.md
new file mode 100644
index 0000000000000000000000000000000000000000..035109b6ea5d406ef10f816fc4bac560cdc6d11c
--- /dev/null
+++ b/user_config/docs/about/release_notes.md
@@ -0,0 +1,10 @@
+<!-- BEGIN MKDOCS TEMPLATE -->
+<!--
+WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+Modified content will be overwritten when updating
+-->
+
+# Release Notes
+
+<!-- END MKDOCS TEMPLATE -->
+
diff --git a/user_config/docs/index.md b/user_config/docs/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..694f243c997bf37d079fa90225fdb24135d6c10b
--- /dev/null
+++ b/user_config/docs/index.md
@@ -0,0 +1,33 @@
+---
+hide:
+  - navigation # Hide navigation
+  - toc        # Hide table of contents
+---
+
+{% set curr_repo=subs("mkdocs_template") %}
+
+<!-- BEGIN MKDOCS TEMPLATE -->
+<!--
+WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+Modified content will be overwritten when updating
+-->
+
+<div align="center">
+
+  <!-- Project Title -->
+  <a href="{{ git_platform.url }}{{ curr_repo.repo_path_with_namespace }}">
+    <img src="{{ curr_repo.logo }}" width="200px">
+    <h1>{{ curr_repo.name }}</h1>
+  </a>
+
+<hr>
+
+{{ to_html(curr_repo.desc) }}
+
+<hr>
+
+</div>
+
+--------------------------------------------------------------------------------
+
+<!-- END MKDOCS TEMPLATE -->
diff --git a/user_config/docs/theme/css/colors.css b/user_config/docs/theme/css/colors.css
new file mode 100644
index 0000000000000000000000000000000000000000..c53cd05f2651eb012fa066332ed93e021153dcab
--- /dev/null
+++ b/user_config/docs/theme/css/colors.css
@@ -0,0 +1,261 @@
+@charset "UTF-8";
+
+:root
+{
+  --md_color__red_50           : 255 , 235 , 238 ; /* rgba(255 , 235 , 238 ) */
+  --md_color__red_100          : 255 , 205 , 210 ; /* rgba(255 , 205 , 210 ) */
+  --md_color__red_200          : 239 , 154 , 154 ; /* rgba(239 , 154 , 154 ) */
+  --md_color__red_300          : 229 , 115 , 115 ; /* rgba(229 , 115 , 115 ) */
+  --md_color__red_400          : 239 , 83  , 80  ; /* rgba(239 , 83  , 80  ) */
+  --md_color__red_500          : 244 , 67  , 54  ; /* rgba(244 , 67  , 54  ) */
+  --md_color__red_600          : 229 , 57  , 53  ; /* rgba(229 , 57  , 53  ) */
+  --md_color__red_700          : 211 , 47  , 47  ; /* rgba(211 , 47  , 47  ) */
+  --md_color__red_800          : 198 , 40  , 40  ; /* rgba(198 , 40  , 40  ) */
+  --md_color__red_900          : 183 , 28  , 28  ; /* rgba(183 , 28  , 28  ) */
+  --md_color__red_A100         : 255 , 138 , 128 ; /* rgba(255 , 138 , 128 ) */
+  --md_color__red_A200         : 255 , 82  , 82  ; /* rgba(255 , 82  , 82  ) */
+  --md_color__red_A400         : 255 , 23  , 68  ; /* rgba(255 , 23  , 68  ) */
+  --md_color__red_A700         : 213 , 0   , 0   ; /* rgba(213 , 0   , 0   ) */
+  --md_color__pink_50          : 252 , 228 , 236 ; /* rgba(252 , 228 , 236 ) */
+  --md_color__pink_100         : 248 , 187 , 208 ; /* rgba(248 , 187 , 208 ) */
+  --md_color__pink_200         : 244 , 143 , 177 ; /* rgba(244 , 143 , 177 ) */
+  --md_color__pink_300         : 240 , 98  , 146 ; /* rgba(240 , 98  , 146 ) */
+  --md_color__pink_400         : 236 , 64  , 122 ; /* rgba(236 , 64  , 122 ) */
+  --md_color__pink_500         : 233 , 30  , 99  ; /* rgba(233 , 30  , 99  ) */
+  --md_color__pink_600         : 216 , 27  , 96  ; /* rgba(216 , 27  , 96  ) */
+  --md_color__pink_700         : 194 , 24  , 91  ; /* rgba(194 , 24  , 91  ) */
+  --md_color__pink_800         : 173 , 20  , 87  ; /* rgba(173 , 20  , 87  ) */
+  --md_color__pink_900         : 136 , 14  , 79  ; /* rgba(136 , 14  , 79  ) */
+  --md_color__pink_A100        : 255 , 128 , 171 ; /* rgba(255 , 128 , 171 ) */
+  --md_color__pink_A200        : 255 , 64  , 129 ; /* rgba(255 , 64  , 129 ) */
+  --md_color__pink_A400        : 245 , 0   , 87  ; /* rgba(245 , 0   , 87  ) */
+  --md_color__pink_A700        : 197 , 17  , 98  ; /* rgba(197 , 17  , 98  ) */
+  --md_color__purple_50        : 243 , 229 , 245 ; /* rgba(243 , 229 , 245 ) */
+  --md_color__purple_100       : 225 , 190 , 231 ; /* rgba(225 , 190 , 231 ) */
+  --md_color__purple_200       : 206 , 147 , 216 ; /* rgba(206 , 147 , 216 ) */
+  --md_color__purple_300       : 186 , 104 , 200 ; /* rgba(186 , 104 , 200 ) */
+  --md_color__purple_400       : 171 , 71  , 188 ; /* rgba(171 , 71  , 188 ) */
+  --md_color__purple_500       : 156 , 39  , 176 ; /* rgba(156 , 39  , 176 ) */
+  --md_color__purple_600       : 142 , 36  , 170 ; /* rgba(142 , 36  , 170 ) */
+  --md_color__purple_700       : 123 , 31  , 162 ; /* rgba(123 , 31  , 162 ) */
+  --md_color__purple_800       : 106 , 27  , 154 ; /* rgba(106 , 27  , 154 ) */
+  --md_color__purple_900       :  74 , 20  , 140 ; /* rgba(74  , 20  , 140 ) */
+  --md_color__purple_A100      : 234 , 128 , 252 ; /* rgba(234 , 128 , 252 ) */
+  --md_color__purple_A200      : 224 , 64  , 251 ; /* rgba(224 , 64  , 251 ) */
+  --md_color__purple_A400      : 213 , 0   , 249 ; /* rgba(213 , 0   , 249 ) */
+  --md_color__purple_A700      : 170 , 0   , 255 ; /* rgba(170 , 0   , 255 ) */
+  --md_color__deep_purple_50   : 237 , 231 , 246 ; /* rgba(237 , 231 , 246 ) */
+  --md_color__deep_purple_100  : 209 , 196 , 233 ; /* rgba(209 , 196 , 233 ) */
+  --md_color__deep_purple_200  : 179 , 157 , 219 ; /* rgba(179 , 157 , 219 ) */
+  --md_color__deep_purple_300  : 149 , 117 , 205 ; /* rgba(149 , 117 , 205 ) */
+  --md_color__deep_purple_400  : 126 , 87  , 194 ; /* rgba(126 , 87  , 194 ) */
+  --md_color__deep_purple_500  : 103 , 58  , 183 ; /* rgba(103 , 58  , 183 ) */
+  --md_color__deep_purple_600  :  94 , 53  , 177 ; /* rgba(94  , 53  , 177 ) */
+  --md_color__deep_purple_700  :  81 , 45  , 168 ; /* rgba(81  , 45  , 168 ) */
+  --md_color__deep_purple_800  :  69 , 39  , 160 ; /* rgba(69  , 39  , 160 ) */
+  --md_color__deep_purple_900  :  49 , 27  , 146 ; /* rgba(49  , 27  , 146 ) */
+  --md_color__deep_purple_A100 : 179 , 136 , 255 ; /* rgba(179 , 136 , 255 ) */
+  --md_color__deep_purple_A200 : 124 , 77  , 255 ; /* rgba(124 , 77  , 255 ) */
+  --md_color__deep_purple_A400 : 101 , 31  , 255 ; /* rgba(101 , 31  , 255 ) */
+  --md_color__deep_purple_A700 :  98 , 0   , 234 ; /* rgba(98  , 0   , 234 ) */
+  --md_color__indigo_50        : 232 , 234 , 246 ; /* rgba(232 , 234 , 246 ) */
+  --md_color__indigo_100       : 197 , 202 , 233 ; /* rgba(197 , 202 , 233 ) */
+  --md_color__indigo_200       : 159 , 168 , 218 ; /* rgba(159 , 168 , 218 ) */
+  --md_color__indigo_300       : 121 , 134 , 203 ; /* rgba(121 , 134 , 203 ) */
+  --md_color__indigo_400       :  92 , 107 , 192 ; /* rgba(92  , 107 , 192 ) */
+  --md_color__indigo_500       :  63 , 81  , 181 ; /* rgba(63  , 81  , 181 ) */
+  --md_color__indigo_600       :  57 , 73  , 171 ; /* rgba(57  , 73  , 171 ) */
+  --md_color__indigo_700       :  48 , 63  , 159 ; /* rgba(48  , 63  , 159 ) */
+  --md_color__indigo_800       :  40 , 53  , 147 ; /* rgba(40  , 53  , 147 ) */
+  --md_color__indigo_900       :  26 , 35  , 126 ; /* rgba(26  , 35  , 126 ) */
+  --md_color__indigo_A100      : 140 , 158 , 255 ; /* rgba(140 , 158 , 255 ) */
+  --md_color__indigo_A200      :  83 , 109 , 254 ; /* rgba(83  , 109 , 254 ) */
+  --md_color__indigo_A400      :  61 , 90  , 254 ; /* rgba(61  , 90  , 254 ) */
+  --md_color__indigo_A700      :  48 , 79  , 254 ; /* rgba(48  , 79  , 254 ) */
+  --md_color__blue_50          : 227 , 242 , 253 ; /* rgba(227 , 242 , 253 ) */
+  --md_color__blue_100         : 187 , 222 , 251 ; /* rgba(187 , 222 , 251 ) */
+  --md_color__blue_200         : 144 , 202 , 249 ; /* rgba(144 , 202 , 249 ) */
+  --md_color__blue_300         : 100 , 181 , 246 ; /* rgba(100 , 181 , 246 ) */
+  --md_color__blue_400         :  66 , 165 , 245 ; /* rgba(66  , 165 , 245 ) */
+  --md_color__blue_500         :  33 , 150 , 243 ; /* rgba(33  , 150 , 243 ) */
+  --md_color__blue_600         :  30 , 136 , 229 ; /* rgba(30  , 136 , 229 ) */
+  --md_color__blue_700         :  25 , 118 , 210 ; /* rgba(25  , 118 , 210 ) */
+  --md_color__blue_800         :  21 , 101 , 192 ; /* rgba(21  , 101 , 192 ) */
+  --md_color__blue_900         :  13 , 71  , 161 ; /* rgba(13  , 71  , 161 ) */
+  --md_color__blue_A100        : 130 , 177 , 255 ; /* rgba(130 , 177 , 255 ) */
+  --md_color__blue_A200        :  68 , 138 , 255 ; /* rgba(68  , 138 , 255 ) */
+  --md_color__blue_A400        :  41 , 121 , 255 ; /* rgba(41  , 121 , 255 ) */
+  --md_color__blue_A700        :  41 , 98  , 255 ; /* rgba(41  , 98  , 255 ) */
+  --md_color__light_blue_50    : 225 , 245 , 254 ; /* rgba(225 , 245 , 254 ) */
+  --md_color__light_blue_100   : 179 , 229 , 252 ; /* rgba(179 , 229 , 252 ) */
+  --md_color__light_blue_200   : 129 , 212 , 250 ; /* rgba(129 , 212 , 250 ) */
+  --md_color__light_blue_300   :  79 , 195 , 247 ; /* rgba(79  , 195 , 247 ) */
+  --md_color__light_blue_400   :  41 , 182 , 246 ; /* rgba(41  , 182 , 246 ) */
+  --md_color__light_blue_500   :   3 , 169 , 244 ; /* rgba(3   , 169 , 244 ) */
+  --md_color__light_blue_600   :   3 , 155 , 229 ; /* rgba(3   , 155 , 229 ) */
+  --md_color__light_blue_700   :   2 , 136 , 209 ; /* rgba(2   , 136 , 209 ) */
+  --md_color__light_blue_800   :   2 , 119 , 189 ; /* rgba(2   , 119 , 189 ) */
+  --md_color__light_blue_900   :   1 , 87  , 155 ; /* rgba(1   , 87  , 155 ) */
+  --md_color__light_blue_A100  : 128 , 216 , 255 ; /* rgba(128 , 216 , 255 ) */
+  --md_color__light_blue_A200  :  64 , 196 , 255 ; /* rgba(64  , 196 , 255 ) */
+  --md_color__light_blue_A400  :   0 , 176 , 255 ; /* rgba(0   , 176 , 255 ) */
+  --md_color__light_blue_A700  :   0 , 145 , 234 ; /* rgba(0   , 145 , 234 ) */
+  --md_color__cyan_50          : 224 , 247 , 250 ; /* rgba(224 , 247 , 250 ) */
+  --md_color__cyan_100         : 178 , 235 , 242 ; /* rgba(178 , 235 , 242 ) */
+  --md_color__cyan_200         : 128 , 222 , 234 ; /* rgba(128 , 222 , 234 ) */
+  --md_color__cyan_300         :  77 , 208 , 225 ; /* rgba(77  , 208 , 225 ) */
+  --md_color__cyan_400         :  38 , 198 , 218 ; /* rgba(38  , 198 , 218 ) */
+  --md_color__cyan_500         :   0 , 188 , 212 ; /* rgba(0   , 188 , 212 ) */
+  --md_color__cyan_600         :   0 , 172 , 193 ; /* rgba(0   , 172 , 193 ) */
+  --md_color__cyan_700         :   0 , 151 , 167 ; /* rgba(0   , 151 , 167 ) */
+  --md_color__cyan_800         :   0 , 131 , 143 ; /* rgba(0   , 131 , 143 ) */
+  --md_color__cyan_900         :   0 , 96  , 100 ; /* rgba(0   , 96  , 100 ) */
+  --md_color__cyan_A100        : 132 , 255 , 255 ; /* rgba(132 , 255 , 255 ) */
+  --md_color__cyan_A200        :  24 , 255 , 255 ; /* rgba(24  , 255 , 255 ) */
+  --md_color__cyan_A400        :   0 , 229 , 255 ; /* rgba(0   , 229 , 255 ) */
+  --md_color__cyan_A700        :   0 , 184 , 212 ; /* rgba(0   , 184 , 212 ) */
+  --md_color__teal_50          : 224 , 242 , 241 ; /* rgba(224 , 242 , 241 ) */
+  --md_color__teal_100         : 178 , 223 , 219 ; /* rgba(178 , 223 , 219 ) */
+  --md_color__teal_200         : 128 , 203 , 196 ; /* rgba(128 , 203 , 196 ) */
+  --md_color__teal_300         :  77 , 182 , 172 ; /* rgba(77  , 182 , 172 ) */
+  --md_color__teal_400         :  38 , 166 , 154 ; /* rgba(38  , 166 , 154 ) */
+  --md_color__teal_500         :   0 , 150 , 136 ; /* rgba(0   , 150 , 136 ) */
+  --md_color__teal_600         :   0 , 137 , 123 ; /* rgba(0   , 137 , 123 ) */
+  --md_color__teal_700         : 0   , 121 , 107 ; /* rgba(0   , 121 , 107 ) */
+  --md_color__teal_800         : 0   , 105 , 92  ; /* rgba(0   , 105 , 92  ) */
+  --md_color__teal_900         : 0   , 77  , 64  ; /* rgba(0   , 77  , 64  ) */
+  --md_color__teal_A100        : 167 , 255 , 235 ; /* rgba(167 , 255 , 235 ) */
+  --md_color__teal_A200        : 100 , 255 , 218 ; /* rgba(100 , 255 , 218 ) */
+  --md_color__teal_A400        : 29  , 233 , 182 ; /* rgba(29  , 233 , 182 ) */
+  --md_color__teal_A700        : 0   , 191 , 165 ; /* rgba(0   , 191 , 165 ) */
+  --md_color__green_50         : 232 , 245 , 233 ; /* rgba(232 , 245 , 233 ) */
+  --md_color__green_100        : 200 , 230 , 201 ; /* rgba(200 , 230 , 201 ) */
+  --md_color__green_200        : 165 , 214 , 167 ; /* rgba(165 , 214 , 167 ) */
+  --md_color__green_300        : 129 , 199 , 132 ; /* rgba(129 , 199 , 132 ) */
+  --md_color__green_400        : 102 , 187 , 106 ; /* rgba(102 , 187 , 106 ) */
+  --md_color__green_500        : 76  , 175 , 80  ; /* rgba(76  , 175 , 80  ) */
+  --md_color__green_600        : 67  , 160 , 71  ; /* rgba(67  , 160 , 71  ) */
+  --md_color__green_700        : 56  , 142 , 60  ; /* rgba(56  , 142 , 60  ) */
+  --md_color__green_800        : 46  , 125 , 50  ; /* rgba(46  , 125 , 50  ) */
+  --md_color__green_900        : 27  , 94  , 32  ; /* rgba(27  , 94  , 32  ) */
+  --md_color__green_A100       : 185 , 246 , 202 ; /* rgba(185 , 246 , 202 ) */
+  --md_color__green_A200       : 105 , 240 , 174 ; /* rgba(105 , 240 , 174 ) */
+  --md_color__green_A400       : 0   , 230 , 118 ; /* rgba(0   , 230 , 118 ) */
+  --md_color__green_A700       : 0   , 200 , 83  ; /* rgba(0   , 200 , 83  ) */
+  --md_color__light_green_50   : 241 , 248 , 233 ; /* rgba(241 , 248 , 233 ) */
+  --md_color__light_green_100  : 220 , 237 , 200 ; /* rgba(220 , 237 , 200 ) */
+  --md_color__light_green_200  : 197 , 225 , 165 ; /* rgba(197 , 225 , 165 ) */
+  --md_color__light_green_300  : 174 , 213 , 129 ; /* rgba(174 , 213 , 129 ) */
+  --md_color__light_green_400  : 156 , 204 , 101 ; /* rgba(156 , 204 , 101 ) */
+  --md_color__light_green_500  : 139 , 195 , 74  ; /* rgba(139 , 195 , 74  ) */
+  --md_color__light_green_600  : 124 , 179 , 66  ; /* rgba(124 , 179 , 66  ) */
+  --md_color__light_green_700  : 104 , 159 , 56  ; /* rgba(104 , 159 , 56  ) */
+  --md_color__light_green_800  : 85  , 139 , 47  ; /* rgba(85  , 139 , 47  ) */
+  --md_color__light_green_900  : 51  , 105 , 30  ; /* rgba(51  , 105 , 30  ) */
+  --md_color__light_green_A100 : 204 , 255 , 144 ; /* rgba(204 , 255 , 144 ) */
+  --md_color__light_green_A200 : 178 , 255 , 89  ; /* rgba(178 , 255 , 89  ) */
+  --md_color__light_green_A400 : 118 , 255 , 3   ; /* rgba(118 , 255 , 3   ) */
+  --md_color__light_green_A700 : 100 , 221 , 23  ; /* rgba(100 , 221 , 23  ) */
+  --md_color__lime_50          : 249 , 251 , 231 ; /* rgba(249 , 251 , 231 ) */
+  --md_color__lime_100         : 240 , 244 , 195 ; /* rgba(240 , 244 , 195 ) */
+  --md_color__lime_200         : 230 , 238 , 156 ; /* rgba(230 , 238 , 156 ) */
+  --md_color__lime_300         : 220 , 231 , 117 ; /* rgba(220 , 231 , 117 ) */
+  --md_color__lime_400         : 212 , 225 , 87  ; /* rgba(212 , 225 , 87  ) */
+  --md_color__lime_500         : 205 , 220 , 57  ; /* rgba(205 , 220 , 57  ) */
+  --md_color__lime_600         : 192 , 202 , 51  ; /* rgba(192 , 202 , 51  ) */
+  --md_color__lime_700         : 175 , 180 , 43  ; /* rgba(175 , 180 , 43  ) */
+  --md_color__lime_800         : 158 , 157 , 36  ; /* rgba(158 , 157 , 36  ) */
+  --md_color__lime_900         : 130 , 119 , 23  ; /* rgba(130 , 119 , 23  ) */
+  --md_color__lime_A100        : 244 , 255 , 129 ; /* rgba(244 , 255 , 129 ) */
+  --md_color__lime_A200        : 238 , 255 , 65  ; /* rgba(238 , 255 , 65  ) */
+  --md_color__lime_A400        : 198 , 255 , 0   ; /* rgba(198 , 255 , 0   ) */
+  --md_color__lime_A700        : 174 , 234 , 0   ; /* rgba(174 , 234 , 0   ) */
+  --md_color__yellow_50        : 255 , 253 , 231 ; /* rgba(255 , 253 , 231 ) */
+  --md_color__yellow_100       : 255 , 249 , 196 ; /* rgba(255 , 249 , 196 ) */
+  --md_color__yellow_200       : 255 , 245 , 157 ; /* rgba(255 , 245 , 157 ) */
+  --md_color__yellow_300       : 255 , 241 , 118 ; /* rgba(255 , 241 , 118 ) */
+  --md_color__yellow_400       : 255 , 238 , 88  ; /* rgba(255 , 238 , 88  ) */
+  --md_color__yellow_500       : 255 , 235 , 59  ; /* rgba(255 , 235 , 59  ) */
+  --md_color__yellow_600       : 253 , 216 , 53  ; /* rgba(253 , 216 , 53  ) */
+  --md_color__yellow_700       : 251 , 192 , 45  ; /* rgba(251 , 192 , 45  ) */
+  --md_color__yellow_800       : 249 , 168 , 37  ; /* rgba(249 , 168 , 37  ) */
+  --md_color__yellow_900       : 245 , 127 , 23  ; /* rgba(245 , 127 , 23  ) */
+  --md_color__yellow_A100      : 255 , 255 , 141 ; /* rgba(255 , 255 , 141 ) */
+  --md_color__yellow_A200      : 255 , 255 , 0   ; /* rgba(255 , 255 , 0   ) */
+  --md_color__yellow_A400      : 255 , 234 , 0   ; /* rgba(255 , 234 , 0   ) */
+  --md_color__yellow_A700      : 255 , 214 , 0   ; /* rgba(255 , 214 , 0   ) */
+  --md_color__amber_50         : 255 , 248 , 225 ; /* rgba(255 , 248 , 225 ) */
+  --md_color__amber_100        : 255 , 236 , 179 ; /* rgba(255 , 236 , 179 ) */
+  --md_color__amber_200        : 255 , 224 , 130 ; /* rgba(255 , 224 , 130 ) */
+  --md_color__amber_300        : 255 , 213 , 79  ; /* rgba(255 , 213 , 79  ) */
+  --md_color__amber_400        : 255 , 202 , 40  ; /* rgba(255 , 202 , 40  ) */
+  --md_color__amber_500        : 255 , 193 , 7   ; /* rgba(255 , 193 , 7   ) */
+  --md_color__amber_600        : 255 , 179 , 0   ; /* rgba(255 , 179 , 0   ) */
+  --md_color__amber_700        : 255 , 160 , 0   ; /* rgba(255 , 160 , 0   ) */
+  --md_color__amber_800        : 255 , 143 , 0   ; /* rgba(255 , 143 , 0   ) */
+  --md_color__amber_900        : 255 , 111 , 0   ; /* rgba(255 , 111 , 0   ) */
+  --md_color__amber_A100       : 255 , 229 , 127 ; /* rgba(255 , 229 , 127 ) */
+  --md_color__amber_A200       : 255 , 215 , 64  ; /* rgba(255 , 215 , 64  ) */
+  --md_color__amber_A400       : 255 , 196 , 0   ; /* rgba(255 , 196 , 0   ) */
+  --md_color__amber_A700       : 255 , 171 , 0   ; /* rgba(255 , 171 , 0   ) */
+  --md_color__orange_50        : 255 , 243 , 224 ; /* rgba(255 , 243 , 224 ) */
+  --md_color__orange_100       : 255 , 224 , 178 ; /* rgba(255 , 224 , 178 ) */
+  --md_color__orange_200       : 255 , 204 , 128 ; /* rgba(255 , 204 , 128 ) */
+  --md_color__orange_300       : 255 , 183 , 77  ; /* rgba(255 , 183 , 77  ) */
+  --md_color__orange_400       : 255 , 167 , 38  ; /* rgba(255 , 167 , 38  ) */
+  --md_color__orange_500       : 255 , 152 , 0   ; /* rgba(255 , 152 , 0   ) */
+  --md_color__orange_600       : 251 , 140 , 0   ; /* rgba(251 , 140 , 0   ) */
+  --md_color__orange_700       : 245 , 124 , 0   ; /* rgba(245 , 124 , 0   ) */
+  --md_color__orange_800       : 239 , 108 , 0   ; /* rgba(239 , 108 , 0   ) */
+  --md_color__orange_900       : 230 , 81  , 0   ; /* rgba(230 , 81  , 0   ) */
+  --md_color__orange_A100      : 255 , 209 , 128 ; /* rgba(255 , 209 , 128 ) */
+  --md_color__orange_A200      : 255 , 171 , 64  ; /* rgba(255 , 171 , 64  ) */
+  --md_color__orange_A400      : 255 , 145 , 0   ; /* rgba(255 , 145 , 0   ) */
+  --md_color__orange_A700      : 255 , 109 , 0   ; /* rgba(255 , 109 , 0   ) */
+  --md_color__deep_orange_50   : 251 , 233 , 231 ; /* rgba(251 , 233 , 231 ) */
+  --md_color__deep_orange_100  : 255 , 204 , 188 ; /* rgba(255 , 204 , 188 ) */
+  --md_color__deep_orange_200  : 255 , 171 , 145 ; /* rgba(255 , 171 , 145 ) */
+  --md_color__deep_orange_300  : 255 , 138 , 101 ; /* rgba(255 , 138 , 101 ) */
+  --md_color__deep_orange_400  : 255 , 112 , 67  ; /* rgba(255 , 112 , 67  ) */
+  --md_color__deep_orange_500  : 255 , 87  , 34  ; /* rgba(255 , 87  , 34  ) */
+  --md_color__deep_orange_600  : 244 , 81  , 30  ; /* rgba(244 , 81  , 30  ) */
+  --md_color__deep_orange_700  : 230 , 74  , 25  ; /* rgba(230 , 74  , 25  ) */
+  --md_color__deep_orange_800  : 216 , 67  , 21  ; /* rgba(216 , 67  , 21  ) */
+  --md_color__deep_orange_900  : 191 , 54  , 12  ; /* rgba(191 , 54  , 12  ) */
+  --md_color__deep_orange_A100 : 255 , 158 , 128 ; /* rgba(255 , 158 , 128 ) */
+  --md_color__deep_orange_A200 : 255 , 110 , 64  ; /* rgba(255 , 110 , 64  ) */
+  --md_color__deep_orange_A400 : 255 , 61  , 0   ; /* rgba(255 , 61  , 0   ) */
+  --md_color__deep_orange_A700 : 221 , 44  , 0   ; /* rgba(221 , 44  , 0   ) */
+  --md_color__brown_50         : 239 , 235 , 233 ; /* rgba(239 , 235 , 233 ) */
+  --md_color__brown_100        : 215 , 204 , 200 ; /* rgba(215 , 204 , 200 ) */
+  --md_color__brown_200        : 188 , 170 , 164 ; /* rgba(188 , 170 , 164 ) */
+  --md_color__brown_300        : 161 , 136 , 127 ; /* rgba(161 , 136 , 127 ) */
+  --md_color__brown_400        : 141 , 110 , 99  ; /* rgba(141 , 110 , 99  ) */
+  --md_color__brown_500        : 121 , 85  , 72  ; /* rgba(121 , 85  , 72  ) */
+  --md_color__brown_600        : 109 , 76  , 65  ; /* rgba(109 , 76  , 65  ) */
+  --md_color__brown_700        : 93  , 64  , 55  ; /* rgba(93  , 64  , 55  ) */
+  --md_color__brown_800        : 78  , 52  , 46  ; /* rgba(78  , 52  , 46  ) */
+  --md_color__brown_900        : 62  , 39  , 35  ; /* rgba(62  , 39  , 35  ) */
+  --md_color__grey_50          : 250 , 250 , 250 ; /* rgba(250 , 250 , 250 ) */
+  --md_color__grey_100         : 245 , 245 , 245 ; /* rgba(245 , 245 , 245 ) */
+  --md_color__grey_200         : 238 , 238 , 238 ; /* rgba(238 , 238 , 238 ) */
+  --md_color__grey_300         : 224 , 224 , 224 ; /* rgba(224 , 224 , 224 ) */
+  --md_color__grey_400         : 189 , 189 , 189 ; /* rgba(189 , 189 , 189 ) */
+  --md_color__grey_500         : 158 , 158 , 158 ; /* rgba(158 , 158 , 158 ) */
+  --md_color__grey_600         : 117 , 117 , 117 ; /* rgba(117 , 117 , 117 ) */
+  --md_color__grey_700         : 97  , 97  , 97  ; /* rgba(97  , 97  , 97  ) */
+  --md_color__grey_800         : 66  , 66  , 66  ; /* rgba(66  , 66  , 66  ) */
+  --md_color__grey_900         : 33  , 33  , 33  ; /* rgba(33  , 33  , 33  ) */
+  --md_color__blue_grey_50     : 236 , 239 , 241 ; /* rgba(236 , 239 , 241 ) */
+  --md_color__blue_grey_100    : 207 , 216 , 220 ; /* rgba(207 , 216 , 220 ) */
+  --md_color__blue_grey_200    : 176 , 190 , 197 ; /* rgba(176 , 190 , 197 ) */
+  --md_color__blue_grey_300    : 144 , 164 , 174 ; /* rgba(144 , 164 , 174 ) */
+  --md_color__blue_grey_400    : 120 , 144 , 156 ; /* rgba(120 , 144 , 156 ) */
+  --md_color__blue_grey_500    : 96  , 125 , 139 ; /* rgba(96  , 125 , 139 ) */
+  --md_color__blue_grey_600    : 84  , 110 , 122 ; /* rgba(84  , 110 , 122 ) */
+  --md_color__blue_grey_700    : 69  , 90  , 100 ; /* rgba(69  , 90  , 100 ) */
+  --md_color__blue_grey_800    : 55  , 71  , 79  ; /* rgba(55  , 71  , 79  ) */
+  --md_color__blue_grey_900    : 38  , 50  , 56  ; /* rgba(38  , 50  , 56  ) */
+  --md_color__black            : 0   , 0   , 0   ; /* rgba(0   , 0   , 0   ) */
+  --md_color__white            : 255 , 255 , 255 ; /* rgba(255 , 255 , 255 ) */
+}
diff --git a/user_config/docs/theme/css/extra.css b/user_config/docs/theme/css/extra.css
new file mode 100644
index 0000000000000000000000000000000000000000..ce4244b4b71115c5ba316f3abfa0bb40b8bb3c6d
--- /dev/null
+++ b/user_config/docs/theme/css/extra.css
@@ -0,0 +1,4 @@
+.image-center {
+  display : block;
+  margin  : auto;
+}
\ No newline at end of file
diff --git a/user_config/docs/theme/css/python_markdown_extension.css b/user_config/docs/theme/css/python_markdown_extension.css
new file mode 100644
index 0000000000000000000000000000000000000000..9b4cdb2f3da5db1230ee3f5b5163d18446e34ae3
--- /dev/null
+++ b/user_config/docs/theme/css/python_markdown_extension.css
@@ -0,0 +1,307 @@
+@charset "UTF-8";
+
+/* Codehilight */
+:root [data-md-color-scheme="rdeville-dark"] .highlight [data-linenos]::before
+{
+  /* Default line numbers */
+  color: var(--md-default-fg-color--lightest);
+}
+
+:root [data-md-color-scheme="rdeville-dark"] .highlight [data-linenos].special::before
+{
+  /* Special line numbers, i.e. when alternating line colors*/
+  background-color:var(--md-code-special-bg-color);
+}
+
+:root [data-md-color-scheme="rdeville-light"] .highlight [data-linenos]::before
+{
+  /* Default line numbers */
+  color: var(--md-default-fg-color--darkest);
+}
+
+:root [data-md-color-scheme="rdeville-light"] .highlight [data-linenos].special::before
+{
+  /* Special line numbers, i.e. when alternating line colors*/
+  background-color:var(--md-code-special-bg-color);
+}
+
+/* Superfences tabs */
+:root [data-md-color-scheme="rdeville-dark"] .md-typeset .tabbed-set > input:not(.focus-visible) + label
+{
+  /* Tab background not focus */
+  background: var(--md-default-bg-color--light);
+  color: var(--md-default-fg-color--lightest);
+}
+
+:root [data-md-color-scheme="rdeville-dark"] .md-typeset .tabbed-set > input:checked + label,
+:root [data-md-color-scheme="rdeville-dark"] .md-typeset .tabbed-content
+{
+  /* Tab and content focus */
+  background: var(--md-default-bg-color--dark);
+  color: var(--md-default-fg-color);
+}
+
+:root [data-md-color-scheme="rdeville-light"] .md-typeset .tabbed-set > input:not(.focus-visible) + label
+{
+  /* Tab background not focus */
+  background: var(--md-default-bg-color--darkest);
+  color: var(--md-default-fg-color--darkest);
+}
+
+:root [data-md-color-scheme="rdeville-light"] .md-typeset .tabbed-set > input:checked + label,
+:root [data-md-color-scheme="rdeville-light"] .md-typeset .tabbed-content
+{
+  /* Tab and content focus */
+  background: var(--md-default-bg-color--lightest);
+  color: var(--md-default-fg-color);
+}
+
+/* Codehilight */
+.md-typeset .highlight .special::before
+{
+  background-color:var(--md-code-special-bg-color);
+}
+
+.md-typeset .highlighttable .linenodiv .special
+{
+  background-color : var(--md-code-special-bg-color)
+}
+
+/* Progress bar */
+.progress-label
+{
+  position    : absolute;
+  text-align  : center;
+  font-weight : 700;
+  width       : 100%;
+  margin      : 0;
+  line-height : 1.2rem;
+  white-space : nowrap;
+  overflow    : hidden;
+}
+
+.md-typeset .progress.candystripe-animate .progress-bar
+{
+ -webkit-animation:animate-stripes 3s linear infinite;
+  animation:animate-stripes 3s linear infinite
+}
+
+:root [data-md-color-scheme="rdeville-light"] .md-typeset .progress.candystripe .progress-bar
+{
+  background-image: linear-gradient(
+    135deg,
+    rgba(var(--md_color__white),0.25) 27%,
+    transparent 27%,
+    transparent 52%,
+    rgba(var(--md_color__white),0.25) 52%,
+    rgba(var(--md_color__white),0.25) 77%,
+    transparent 77%,
+    transparent);
+  background-size:2rem 2rem
+}
+
+:root [data-md-color-scheme="rdeville-dark"] .md-typeset .progress.candystripe .progress-bar
+{
+  background-image: linear-gradient(
+    135deg,
+    rgba(var(--md_color__black),0.25) 27%,
+    transparent 27%,
+    transparent 52%,
+    rgba(var(--md_color__black),0.25) 52%,
+    rgba(var(--md_color__black),0.25) 77%,
+    transparent 77%,
+    transparent);
+  background-size:2rem 2rem
+}
+
+.progress-bar
+{
+  height           : 1.2rem;
+  float            : left;
+  background-color : var(--md-code-bf-color);
+}
+
+.md-typeset .progress
+{
+  display          : block;
+  width            : 100%;
+  margin           : 0.5rem 0;
+  height           : 1.2rem;
+  background-color : var(--md-code-bg-color);
+  position         : relative;
+}
+
+.progress-100plus .progress-bar
+{
+  background-color: rgba(var(--md_color__green_500));
+}
+
+.progress-80plus .progress-bar
+{
+  background-color: rgba(var(--md_color__light_green_500));
+}
+
+.progress-60plus .progress-bar
+{
+  background-color: rgba(var(--md_color__lime_500));
+}
+
+.progress-40plus .progress-bar
+{
+  background-color: rgba(var(--md_color__yellow_500));
+}
+
+.progress-20plus .progress-bar
+{
+  background-color: rgba(var(--md_color__amber_500));
+}
+
+.progress-0plus .progress-bar
+{
+  background-color: rgba(var(--md_color__red_500));
+}
+
+.default-color .progress-bar
+{
+  background-color : var(--md-primary-fg-color);
+}
+
+.default-color .progress-bar
+{
+  background-color : var(--md-primary-fg-color);
+}
+
+.red-color .progress-bar
+{
+  background-color : rgba(var(--md_color__red_500),1);
+}
+
+.pink-color .progress-bar
+{
+  background-color : rgba(var(--md_color__pink_500),1);
+}
+
+.purple-color .progress-bar
+{
+  background-color : rgba(var(--md_color__purple_500),1);
+}
+
+.deep-purple-color .progress-bar
+{
+  background-color : rgba(var(--md_color__deep_purple_500),1);
+}
+
+.indigo-color .progress-bar
+{
+  background-color : rgba(var(--md_color__indigo_500),1);
+}
+
+.blue-color .progress-bar
+{
+  background-color : rgba(var(--md_color__blue_500),1);
+}
+
+.light-blue-color .progress-bar
+{
+  background-color : rgba(var(--md_color__light_blue_500),1);
+}
+
+.cyan-color .progress-bar
+{
+  background-color : rgba(var(--md_color__cyan_500),1);
+}
+
+.teal-color .progress-bar
+{
+  background-color : rgba(var(--md_color__teal_500),1);
+}
+
+.green-color .progress-bar
+{
+  background-color : rgba(var(--md_color__green_500),1);
+}
+
+.light-green-color .progress-bar
+{
+  background-color : rgba(var(--md_color__light_green_500),1);
+}
+
+.lime-color .progress-bar
+{
+  background-color : rgba(var(--md_color__lime_500),1);
+}
+
+.yellow-color .progress-bar
+{
+  background-color : rgba(var(--md_color__yellow_500),1);
+}
+
+.amber-color .progress-bar
+{
+  background-color : rgba(var(--md_color__amber_500),1);
+}
+
+.orange-color .progress-bar
+{
+  background-color : rgba(var(--md_color__orange_500),1);
+}
+
+.deep-orange-color .progress-bar
+{
+  background-color : rgba(var(--md_color__deep_orange_500),1);
+}
+
+.brown-color .progress-bar
+{
+  background-color : rgba(var(--md_color__brown_500),1);
+}
+
+.grey-color .progress-bar
+{
+  background-color : rgba(var(--md_color__grey_500),1);
+}
+
+.blue-grey-color .progress-bar
+{
+  background-color : rgba(var(--md_color__blue_grey_500),1);
+}
+
+.rounded  .progress-bar
+{
+  border-top-right-radius : 1em;
+  border-bottom-right-radius : 1em;
+}
+
+@-webkit-keyframes animate-stripes
+{
+ 0% {
+  background-position:0 0
+ }
+ 100% {
+  background-position:6rem 0
+ }
+}
+
+@keyframes animate-stripes
+{
+ 0%
+ {
+  background-position:0 0
+ }
+ 100%
+ {
+  background-position:6rem 0
+ }
+}
+
+/* Tasklist */
+
+.md-typeset [type="checkbox"]:checked + .task-list-indicator::before
+{
+  background-color: rgba(var(--md_color__green_500),1);
+}
+
+/* *****************************************************************************
+ * VIM MODELINE
+ * vim: fdm=indent
+ * ****************************************************************************/
diff --git a/user_config/docs/theme/css/theme.css b/user_config/docs/theme/css/theme.css
new file mode 100644
index 0000000000000000000000000000000000000000..b5ba63f9a8f5fe419f08c16c7c09c11e5b884790
--- /dev/null
+++ b/user_config/docs/theme/css/theme.css
@@ -0,0 +1,1167 @@
+@charset "UTF-8";
+
+/* DARK THEME
+ * =============================================================================
+ */
+:root [data-md-color-scheme="pagoda-dark"]
+{
+  /* MAIN CONFIGURATION
+   * ---------------------------------------------------------------------------
+   */
+  /* Default background colors */
+  --md-default-bg-color--true-dark  : rgba(var(--md_color__grey_900), 1.00);
+  --md-default-bg-color--darkest    : rgba(var(--md_color__grey_900), 0.50);
+  --md-default-bg-color--darker     : rgba(var(--md_color__grey_900), 0.25);
+  --md-default-bg-color--dark       : rgba(var(--md_color__grey_900), 0.10);
+  --md-default-bg-color             : rgba(var(--md_color__grey_800), 1.00);
+  --md-default-bg-color--light      : rgba(var(--md_color__grey_700), 0.10);
+  --md-default-bg-color--lighter    : rgba(var(--md_color__grey_700), 0.25);
+  --md-default-bg-color--lightest   : rgba(var(--md_color__grey_700), 0.50);
+  --md-default-bg-color--true-light : rgba(var(--md_color__grey_700), 1.00);
+
+  /* Default foreground colors */
+  --md-default-fg-color--true-dark  : rgba(var(--md_color__grey_200), 1.00);
+  --md-default-fg-color--darkest    : rgba(var(--md_color__grey_200), 0.50);
+  --md-default-fg-color--darker     : rgba(var(--md_color__grey_200), 0.25);
+  --md-default-fg-color--dark       : rgba(var(--md_color__grey_200), 0.10);
+  --md-default-fg-color             : rgba(var(--md_color__grey_100), 1.00);
+  --md-default-fg-color--light      : rgba(var(--md_color__grey_50),  0.10);
+  --md-default-fg-color--lighter    : rgba(var(--md_color__grey_50),  0.25);
+  --md-default-fg-color--lightest   : rgba(var(--md_color__grey_50),  0.50);
+  --md-default-fg-color--true-light : rgba(var(--md_color__grey_50),  1.00);
+
+  /* Default font color */
+  --md-typeset-color             : var(--md-default-fg-color);
+  /* Hyperlink font color */
+  --md-typeset-a-color           : var(--md-primary-fg-color);
+
+  /* Font color for mark */
+  --md-typeset-mark-color        : rgba(var(--md_color__yellow_800),0.50);
+  --md-typeset-del-color         : rgba(var(--md_color__red_800),0.50);
+  --md-typeset-ins-color         : rgba(var(--md_color__green_800),0.50);
+
+  /* CODE BLOCKS
+   * ---------------------------------------------------------------------------
+   */
+  /* Code blocks background */
+  --md-code-fg-color             : rgba(var(--md_color__grey_200),1.00);
+  /* Code blocks foreground */
+  --md-code-bg-color             : rgba(var(--md_color__grey_900),1.00);
+  /* Color when line is highlighted */
+  --md-code-hl-color             : rgba(var(--md_color__yellow_500),0.25);
+
+  /* SYNTAX HIGHLIGHT
+   * ---------------------------------------------------------------------------
+   */
+  /* Color when line number shown and alternated */
+  --md-code-special-bg-color     : rgba(var(--md_color__blue_grey_900),1.00);
+  /* Color for builtin */
+  --md-code-hl-builtin-color     : rgba(var(--md_color__blue_300)     ,1.00);
+  /* Color for comment */
+  --md-code-hl-comment-color     : rgba(var(--md_color__grey_100)     ,0.50);
+  /* Color for constant method */
+  --md-code-hl-constant-color    : rgba(var(--md_color__purple_300),1.00);
+  /* Color for method */
+  --md-code-hl-function-color    : rgba(var(--md_color__blue_300),1.00);
+  /* Color for generic keyword, such as emph, strong, etc */
+  --md-code-hl-generic-color     : rgba(var(--md_color__grey_50),1.00);
+  /* Color for keyword */
+  --md-code-hl-keyword-color     : rgba(var(--md_color__purple_300),1.00);
+  /* Color for name keyword, such as variable name, etc */
+  --md-code-hl-name-color        : var(--md-code-fg-color);
+  /* Color for number */
+  --md-code-hl-number-color      : rgba(var(--md_color__red_300),1.00);
+  /* Color for operator */
+  --md-code-hl-operator-color    : rgba(var(--md_color__purple_300),1.00);
+  /* Color for punctuation */
+  --md-code-hl-punctuation-color : rgba(var(--md_color__amber_300),1.00);
+  /* Color for special character such as '\n' */
+  --md-code-hl-special-color     : rgba(var(--md_color__amber_900),1.00);
+  /* Color for string */
+  --md-code-hl-string-color      : rgba(var(--md_color__red_300),1.00);
+  /* Color for variables, such as tag in html */
+  --md-code-hl-variable-color    : rgba(var(--md_color__green_300,1));
+
+  /* KEYBOARD KEYS
+   * ---------------------------------------------------------------------------
+   */
+  /* Color when showing keyboard keys */
+  --md-typeset-kbd-color         : rgba(var(--md_color__grey_700) , 1.00);
+  --md-typeset-kbd-accent-color  : rgba(var(--md_color__grey_800) , 0.66);
+  --md-typeset-kbd-border-color  : rgba(var(--md_color__grey_900) , 0.66);
+
+  /* FOOTER
+   * ---------------------------------------------------------------------------
+   */
+  /* Footer configuration */
+  --md-footer-fg-color           : rgba(var(--md_color__grey_100) , 1.00);
+  --md-footer-fg-color--light    : rgba(var(--md_color__grey_100) , 0.5);
+  --md-footer-fg-color--lighter  : rgba(var(--md_color__grey_100) , 0.25);
+  --md-footer-bg-color           : rgba(var(--md_color__grey_900) , 0.5);
+  --md-footer-bg-color--dark     : rgba(var(--md_color__grey_900) , 1.00);
+
+  /* ADMONITION
+   * ---------------------------------------------------------------------------
+   */
+  /* Default admonition color */
+  --md-admonition-fg-color       : var(--md-default-fg-color);
+  --md-admonition-bg-color       : var(--md-default-bg-color);
+}
+
+/* LIGHT THEME
+ * =============================================================================
+ */
+:root [data-md-color-scheme="pagoda-light"]
+{
+  /* MAIN CONFIGURATION
+   * ---------------------------------------------------------------------------
+   */
+  /* Default background colors */
+  --md-default-bg-color--true-dark  : rgba(var(--md_color__grey_300), 1.00);
+  --md-default-bg-color--darkest  : rgba(var(--md_color__grey_300), 0.50);
+  --md-default-bg-color--darker   : rgba(var(--md_color__grey_300), 0.25);
+  --md-default-bg-color--dark     : rgba(var(--md_color__grey_300), 0.10);
+  --md-default-bg-color           : rgba(var(--md_color__grey_200), 1.00);
+  --md-default-bg-color--light    : rgba(var(--md_color__grey_100), 0.10);
+  --md-default-bg-color--lighter  : rgba(var(--md_color__grey_100), 0.25);
+  --md-default-bg-color--lightest : rgba(var(--md_color__grey_100), 0.50);
+  --md-default-bg-color--true-light : rgba(var(--md_color__grey_100), 1.00);
+
+  /* Default foreground colors */
+  --md-default-fg-color--true-dark  : rgba(var(--md_color__grey_900), 1.00);
+  --md-default-fg-color--darkest  : rgba(var(--md_color__grey_900), 0.50);
+  --md-default-fg-color--darker   : rgba(var(--md_color__grey_900), 0.25);
+  --md-default-fg-color--dark     : rgba(var(--md_color__grey_900), 0.10);
+  --md-default-fg-color           : rgba(var(--md_color__grey_800), 1.00);
+  --md-default-fg-color--light    : rgba(var(--md_color__grey_700), 0.10);
+  --md-default-fg-color--lighter  : rgba(var(--md_color__grey_700), 0.25);
+  --md-default-fg-color--lightest : rgba(var(--md_color__grey_700), 0.50);
+  --md-default-fg-color--true-light : rgba(var(--md_color__grey_700), 1.00);
+
+  /* Default font color */
+  --md-typeset-color             : var(--md-default-fg-color);
+  /* Hyperlink font color */
+  --md-typeset-a-color           : var(--md-primary-fg-color);
+
+  /* Font color for mark */
+  --md-typeset-mark-color        : rgba(var(--md_color__yellow_200) , 0.50);
+  --md-typeset-del-color         : rgba(var(--md_color__red_200)    , 0.50);
+  --md-typeset-ins-color         : rgba(var(--md_color__green_200)  , 0.50);
+
+  /* CODE BLOCKS
+   * ---------------------------------------------------------------------------
+   */
+  /* Code blocks background */
+  --md-code-fg-color             : rgba(var(--md_color__grey_800),1.00);
+  /* Code blocks foreground */
+  --md-code-bg-color             : rgba(var(--md_color__grey_100),1.00);
+  /* Color when line is highlighted */
+  --md-code-hl-color             : rgba(var(--md_color__yellow_500),0.25);
+
+  /* SYNTAX HIGHLIGHT
+   * ---------------------------------------------------------------------------
+   */
+  /* Color when line number shown and alternated */
+  --md-code-special-bg-color     : rgba(var(--md_color__blue_grey_100),1.00);
+  /* Color for builtin */
+  --md-code-hl-builtin-color     : rgba(var(--md_color__blue_700));
+  /* Color for comment */
+  --md-code-hl-comment-color     : rgba(var(--md_color__grey_900),0.50);
+  /* Color for constant method */
+  --md-code-hl-constant-color    : rgba(var(--md_color__purple_700),1.00);
+  /* Color for method */
+  --md-code-hl-function-color    : rgba(var(--md_color__blue_700),1.00);
+  /* Color for generic keyword, such as emph, strong, etc */
+  --md-code-hl-generic-color     : rgba(var(--md_color__grey_900),1.00);
+  /* Color for keyword */
+  --md-code-hl-keyword-color     : rgba(var(--md_color__purple_700),1.00);
+  /* Color for name keyword, such as variable name, etc */
+  --md-code-hl-name-color        : var(--md-code-fg-color);
+  /* Color for number */
+  --md-code-hl-number-color      : rgba(var(--md_color__red_700),1.00);
+  /* Color for operator */
+  --md-code-hl-operator-color    : rgba(var(--md_color__purple_700),1.00);
+  /* Color for punctuation */
+  --md-code-hl-punctuation-color : rgba(var(--md_color__amber_700),1.00);
+  /* Color for special character such as '\n' */
+  --md-code-hl-special-color     : rgba(var(--md_color__amber_100),1.00);
+  /* Color for string */
+  --md-code-hl-string-color      : rgba(var(--md_color__red_700),1.00);
+  /* Color for variables, such as tag in html */
+  --md-code-hl-variable-color    : rgba(var(--md_color__green_700,1));
+
+  /* KEYBOARD KEYS
+   * ---------------------------------------------------------------------------
+   */
+  /* Color when showing keyboard keys */
+  --md-typeset-kbd-color         : rgba(var(--md_color__grey_300),1.00);
+  --md-typeset-kbd-accent-color  : rgba(var(--md_color__grey_400),0.66);
+  --md-typeset-kbd-border-color  : rgba(var(--md_color__grey_500),0.66);
+
+  /* FOOTER
+   * ---------------------------------------------------------------------------
+   */
+  /* Footer configuration */
+  --md-footer-fg-color           : rgba(var(--md_color__grey_900),1.00);
+  --md-footer-fg-color--light    : rgba(var(--md_color__grey_900),0.5);
+  --md-footer-fg-color--lighter  : rgba(var(--md_color__grey_900),0.25);
+  --md-footer-bg-color           : rgba(var(--md_color__grey_100),0.5);
+  --md-footer-bg-color--dark     : rgba(var(--md_color__grey_100),1.00);
+
+  /* ADMONITION
+   * ---------------------------------------------------------------------------
+   */
+  /* Default admonition color */
+  --md-admonition-fg-color       : var(--md-default-fg-color);
+  --md-admonition-bg-color       : var(--md-default-bg-color);
+}
+
+/* PRIMARY COLOR PALETTE
+ * =============================================================================
+ */
+:root [data-md-color-primary="pagoda-red-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__red_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__red_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__red_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__red_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-red-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__red_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__red_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__red_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__red_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-pink-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__pink_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__pink_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__pink_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__pink_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-pink-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__pink_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__pink_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__pink_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__pink_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-purple-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__purple_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__purple_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__purple_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__purple_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-purple-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__purple_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__purple_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__purple_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__purple_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-deep-purple-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__deep_purple_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__deep_purple_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__deep_purple_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__deep_purple_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-deep-purple-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__deep_purple_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__deep_purple_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__deep_purple_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__deep_purple_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-indigo-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__indigo_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__indigo_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__indigo_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__indigo_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-indigo-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__indigo_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__indigo_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__indigo_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__indigo_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-blue-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__blue_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__blue_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__blue_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__blue_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-blue-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__blue_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__blue_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__blue_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__blue_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-light-blue-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__light_blue_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__light_blue_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__light_blue_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__light_blue_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-light-blue-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__light_blue_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__light_blue_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__light_blue_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__light_blue_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-cyan-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__cyan_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__cyan_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__cyan_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__cyan_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-cyan-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__cyan_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__cyan_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__cyan_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__cyan_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-teal-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__teal_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__teal_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__teal_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__teal_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-teal-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__teal_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__teal_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__teal_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__teal_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-green-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__green_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__green_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__green_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__green_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-green-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__green_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__green_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__green_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__green_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-light-green-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__light_green_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__light_green_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__light_green_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__light_green_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-light-green-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__light_green_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__light_green_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__light_green_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__light_green_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-lime-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__lime_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__lime_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__lime_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__lime_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-lime-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__lime_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__lime_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__lime_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__lime_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-yellow-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__yellow_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__yellow_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__yellow_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__yellow_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-yellow-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__yellow_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__yellow_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__yellow_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__yellow_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-amber-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__amber_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__amber_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__amber_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__amber_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-amber-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__amber_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__amber_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__amber_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__amber_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-orange-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__orange_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__orange_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__orange_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__orange_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-orange-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__orange_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__orange_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__orange_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__orange_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-deep-orange-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__deep_orange_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__deep_orange_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__deep_orange_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__deep_orange_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-deep-orange-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__deep_orange_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__deep_orange_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__deep_orange_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__deep_orange_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-brown-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__brown_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__brown_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__brown_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__brown_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-brown-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__brown_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__brown_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__brown_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__brown_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-grey-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__grey_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__grey_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__grey_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__grey_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-grey-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__grey_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__grey_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__grey_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__grey_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-blue-grey-dark"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__blue_grey_400),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__blue_grey_400),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__blue_grey_300),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__blue_grey_500),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-primary="pagoda-blue-grey-light"]
+{
+  --md-primary-fg-color              : rgba(var(--md_color__blue_grey_600),1.00);
+  --md-primary-fg-color--transparent : rgba(var(--md_color__blue_grey_600),0.10);
+  --md-primary-fg-color--light       : rgba(var(--md_color__blue_grey_500),1.00);
+  --md-primary-fg-color--dark        : rgba(var(--md_color__blue_grey_700),1.00);
+  --md-primary-bg-color              : var(--md-default-bg-color);
+  --md-primary-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+/* ACCENT COLOR PALETTE
+ * =============================================================================
+ */
+:root [data-md-color-accent="pagoda-red-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__red_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__red_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__red_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__red_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-red-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__red_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__red_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__red_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__red_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-pink-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__pink_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__pink_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__pink_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__pink_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-pink-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__pink_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__pink_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__pink_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__pink_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-purple-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__purple_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__purple_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__purple_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__purple_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-purple-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__purple_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__purple_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__purple_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__purple_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-deep-purple-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__deep_purple_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__deep_purple_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__deep_purple_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__deep_purple_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-deep-purple-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__deep_purple_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__deep_purple_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__deep_purple_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__deep_purple_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-indigo-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__indigo_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__indigo_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__indigo_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__indigo_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-indigo-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__indigo_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__indigo_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__indigo_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__indigo_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-blue-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__blue_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__blue_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__blue_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__blue_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-blue-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__blue_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__blue_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__blue_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__blue_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-light-blue-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__light_blue_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__light_blue_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__light_blue_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__light_blue_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-light-blue-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__light_blue_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__light_blue_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__light_blue_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__light_blue_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-cyan-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__cyan_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__cyan_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__cyan_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__cyan_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-cyan-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__cyan_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__cyan_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__cyan_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__cyan_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-teal-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__teal_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__teal_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__teal_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__teal_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-teal-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__teal_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__teal_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__teal_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__teal_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-green-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__green_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__green_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__green_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__green_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-green-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__green_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__green_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__green_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__green_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-light-green-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__light_green_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__light_green_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__light_green_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__light_green_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-light-green-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__light_green_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__light_green_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__light_green_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__light_green_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-lime-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__lime_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__lime_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__lime_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__lime_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-lime-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__lime_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__lime_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__lime_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__lime_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-yellow-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__yellow_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__yellow_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__yellow_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__yellow_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-yellow-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__yellow_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__yellow_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__yellow_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__yellow_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-amber-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__amber_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__amber_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__amber_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__amber_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-amber-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__amber_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__amber_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__amber_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__amber_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-orange-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__orange_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__orange_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__orange_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__orange_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-orange-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__orange_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__orange_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__orange_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__orange_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-deep-orange-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__deep_orange_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__deep_orange_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__deep_orange_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__deep_orange_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-deep-orange-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__deep_orange_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__deep_orange_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__deep_orange_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__deep_orange_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-brown-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__brown_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__brown_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__brown_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__brown_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-brown-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__brown_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__brown_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__brown_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__brown_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-grey-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__grey_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__grey_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__grey_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__grey_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-grey-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__grey_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__grey_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__grey_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__grey_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-blue-grey-dark"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__blue_grey_400),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__blue_grey_400),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__blue_grey_300),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__blue_grey_500),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+:root [data-md-color-accent="pagoda-blue-grey-light"]
+{
+  --md-accent-fg-color              : rgba(var(--md_color__blue_grey_600),1.00);
+  --md-accent-fg-color--transparent : rgba(var(--md_color__blue_grey_600),0.10);
+  --md-accent-fg-color--light       : rgba(var(--md_color__blue_grey_500),1.00);
+  --md-accent-fg-color--dark        : rgba(var(--md_color__blue_grey_700),1.00);
+  --md-accent-bg-color              : var(--md-default-bg-color);
+  --md-accent-bg-color--light       : var(--md-default-bg-color--light);
+}
+
+/* Title style */
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset h1,
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset h2
+{
+  color: var(--md-default-fg-color--true-light);
+}
+
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset h3,
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset h4
+{
+  color: var(--md-default-fg-color--lightest);
+}
+
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset h5,
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset h6
+{
+  color: var(--md-default-fg-color--lighter);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-typeset h1,
+:root [data-md-color-scheme="pagoda-light"] .md-typeset h2
+{
+  color: var(--md-default-fg-color--true-dark);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-typeset h3,
+:root [data-md-color-scheme="pagoda-light"] .md-typeset h4
+{
+  color: var(--md-default-fg-color--darkest);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-typeset h5,
+:root [data-md-color-scheme="pagoda-light"] .md-typeset h6
+{
+  color: var(--md-default-fg-color--darker);
+}
+
+/* Header style */
+.md-header
+{
+  border-bottom-width: 1%;
+  border-bottom-style: solid;
+  border-bottom-color: var(--md-primary-fg-color--light);
+  color: var(--md-primary-fg-color);
+}
+
+:root [data-md-color-scheme="pagoda-dark"]  .md-header
+{
+  background-color: rgba(var(--md_color__grey_900),1.00);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-header
+{
+  background-color: rgba(var(--md_color__grey_100),1.00);
+}
+
+/* Footer style */
+.md-footer-meta
+{
+  border-top-width: 1%;
+  border-top-style: solid;
+  border-top-color: var(--md-primary-fg-color--light);
+  color: var(--md-primary-fg-color);
+}
+
+:root [data-md-color-scheme="pagoda-dark"] .md-footer-meta
+{
+  background-color: rgba(var(--md_color__grey_900),1.00);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-footer-meta
+{
+  background-color: rgba(var(--md_color__grey_100),1.00);
+}
+
+/* Source part on the header on the top right */
+.md-header-nav__source
+{
+  float: right;
+  width: 20%;
+}
+
+:root [data-md-color-scheme="pagoda-light"]  .md-typeset table:not([class]) thead
+{
+  background: var(--md-default-fg-color--darkest);
+  color: var(--md-default-fg-color--lightest)
+}
+
+:root [data-md-color-scheme="pagoda-dark"]  .md-typeset table:not([class]) thead
+{
+  background: var(--md-default-fg-color--lightest);
+  color: var(--md-default-fg-color--darkest)
+}
+
+/* Table of content */
+:root [data-md-color-scheme="pagoda-dark"] .md-nav__link[data-md-state="blur"]
+{
+  color: var(--md-default-fg-color--dark);
+}
+
+:root [data-md-color-scheme="pagoda-dark"] .md-nav__link[data-md-state="blur"]:hover
+{
+  color: var(--md-accent-fg-color);
+}
+
+:root [data-md-color-scheme="pagoda-dark"] .md-nav__list li
+{
+  color: var(--md-default-fg-color--true-light);
+}
+
+:root [data-md-color-scheme="pagoda-dark"] .md-nav__list li ul li
+{
+  color: var(--md-default-fg-color--lightest);
+}
+
+:root [data-md-color-scheme="pagoda-dark"] .md-nav__list li ul li ul li
+{
+  color: var(--md-default-fg-color--lighter);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-nav__link[data-md-state="blur"]
+{
+  color: var(--md-default-fg-color--light);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-nav__link[data-md-state="blur"]:hover
+{
+  color: var(--md-accent-fg-color);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-nav__list li
+{
+  color: var(--md-default-fg-color--true-dark);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-nav__list li ul li
+{
+  color: var(--md-default-fg-color--darkest);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-nav__list li ul li ul li
+{
+  color: var(--md-default-fg-color--darker);
+}
+
+/* Blockquote */
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset blockquote
+{
+  color: var(--md-default-fg-color--lightest);
+  border-left: .2rem solid var(--md-default-fg-color--lightest);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-typeset blockquote
+{
+  color: var(--md-default-fg-color--darkest);
+  border-left: .2rem solid var(--md-default-fg-color--darkest);
+}
+
+/* Abbrevations */
+:root [data-md-color-scheme="pagoda-dark"] .md-typeset abbr
+{
+  border-bottom: .05em dotted var(--md-default-fg-color--lightest);
+  cursor: help;
+  text-decoration: var(--md-default-fg-color--lightest);
+}
+
+:root [data-md-color-scheme="pagoda-light"] .md-typeset abbr
+{
+  border-bottom: .05em dotted var(--md-default-fg-color--darkest);
+  cursor: help;
+  text-decoration: var(--md-default-fg-color--darkest);
+}
+
+/* nav */
+.md-nav--primary .md-nav__title
+{
+  color: var(--md-default-fg-color);
+}
+
+/* *****************************************************************************
+ * VIM MODELINE
+ * vim: fdm=indent
+ * ****************************************************************************/
diff --git a/user_config/docs/theme/js/extra.js b/user_config/docs/theme/js/extra.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ceccdafba5a152c428250e1f70c0c37300e00ab
--- /dev/null
+++ b/user_config/docs/theme/js/extra.js
@@ -0,0 +1,91 @@
+/*
+ * LIGHTGALLERY
+ * ----------------------------------------------------------------------------
+ * Lightgallery extra javascript
+ * From: https://github.com/g-provost/lightgallery-markdown
+ */
+
+/*
+ * Loading lightgallery
+ */
+var elements = document.getElementsByClassName("lightgallery");
+for(var i=0; i<elements.length; i++) {
+  lightGallery(elements[i]);
+}
+
+/*
+ * Loading video plugins for lightgallery
+ */
+lightGallery(document.getElementById('html5-videos'));
+
+/*
+ * Loading parameter to auto-generate thumbnails for vimeo/youtube video
+ */
+lightGallery(document.getElementById('video-thumbnails'), {
+    loadYoutubeThumbnail: true,
+    youtubeThumbSize: 'default',
+    loadVimeoThumbnail: true,
+    vimeoThumbSize: 'thumbnail_medium',
+});
+
+/*
+ * Table Sort
+ * ----------------------------------------------------------------------------
+ * Code snippet to allow sorting table
+ * From: https://squidfunk.github.io/mkdocs-material/reference/data-tables/#sortable-tables
+ */
+document$.subscribe(function() {
+  var tables = document.querySelectorAll("article table")
+  tables.forEach(function(table) {
+    new Tablesort(table)
+  })
+})
+
+
+/*
+ * Mermaid Configuration to support dark/light switching
+ * ----------------------------------------------------------------------------
+ * Table Sort
+ * Optional config
+ * If your document is not specifying `data-md-color-scheme` for color schemes
+ * you just need to specify `default`.
+ */
+window.mermaidConfig = {
+  "rdeville-light": {
+    startOnLoad: false,
+    theme: "default",
+    flowchart: {
+      htmlLabels: false
+    },
+    er: {
+      useMaxWidth: false
+    },
+    sequence: {
+      useMaxWidth: false,
+      /*
+       * Mermaid handles Firefox a little different. For some reason, it
+       * doesn't attach font sizes to the labels in Firefox. If we specify the
+       * documented defaults, font sizes are written to the labels in Firefox.
+       */
+      noteFontWeight: "14px",
+      actorFontSize: "14px",
+      messageFontSize: "16px"
+    }
+  },
+  "rdeville-dark": {
+    startOnLoad: false,
+    theme: "dark",
+    flowchart: {
+      htmlLabels: false
+    },
+    er: {
+      useMaxWidth: false
+    },
+    sequence: {
+      useMaxWidth: false,
+      noteFontWeight: "14px",
+      actorFontSize: "14px",
+      messageFontSize: "16px"
+    }
+  }
+}
diff --git a/user_config/docs/theme/js/tablesort.min.js b/user_config/docs/theme/js/tablesort.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..1dfaae7d6ca0174dd193c896f9d19e445c5fbbe8
--- /dev/null
+++ b/user_config/docs/theme/js/tablesort.min.js
@@ -0,0 +1,6 @@
+/*!
+ * tablesort v5.2.1 (2020-06-02)
+ * http://tristen.ca/tablesort/demo/
+ * Copyright (c) 2020 ; Licensed MIT
+*/
+!function(){function a(b,c){if(!(this instanceof a))return new a(b,c);if(!b||"TABLE"!==b.tagName)throw new Error("Element must be a table");this.init(b,c||{})}var b=[],c=function(a){var b;return window.CustomEvent&&"function"==typeof window.CustomEvent?b=new CustomEvent(a):(b=document.createEvent("CustomEvent"),b.initCustomEvent(a,!1,!1,void 0)),b},d=function(a){return a.getAttribute("data-sort")||a.textContent||a.innerText||""},e=function(a,b){return a=a.trim().toLowerCase(),b=b.trim().toLowerCase(),a===b?0:a<b?1:-1},f=function(a,b){return[].slice.call(a).find(function(a){return a.getAttribute("data-sort-column-key")===b})},g=function(a,b){return function(c,d){var e=a(c.td,d.td);return 0===e?b?d.index-c.index:c.index-d.index:e}};a.extend=function(a,c,d){if("function"!=typeof c||"function"!=typeof d)throw new Error("Pattern and sort must be a function");b.push({name:a,pattern:c,sort:d})},a.prototype={init:function(a,b){var c,d,e,f,g=this;if(g.table=a,g.thead=!1,g.options=b,a.rows&&a.rows.length>0)if(a.tHead&&a.tHead.rows.length>0){for(e=0;e<a.tHead.rows.length;e++)if("thead"===a.tHead.rows[e].getAttribute("data-sort-method")){c=a.tHead.rows[e];break}c||(c=a.tHead.rows[a.tHead.rows.length-1]),g.thead=!0}else c=a.rows[0];if(c){var h=function(){g.current&&g.current!==this&&g.current.removeAttribute("aria-sort"),g.current=this,g.sortTable(this)};for(e=0;e<c.cells.length;e++)f=c.cells[e],f.setAttribute("role","columnheader"),"none"!==f.getAttribute("data-sort-method")&&(f.tabindex=0,f.addEventListener("click",h,!1),null!==f.getAttribute("data-sort-default")&&(d=f));d&&(g.current=d,g.sortTable(d))}},sortTable:function(a,h){var i=this,j=a.getAttribute("data-sort-column-key"),k=a.cellIndex,l=e,m="",n=[],o=i.thead?0:1,p=a.getAttribute("data-sort-method"),q=a.getAttribute("aria-sort");if(i.table.dispatchEvent(c("beforeSort")),h||(q="ascending"===q?"descending":"descending"===q?"ascending":i.options.descending?"descending":"ascending",a.setAttribute("aria-sort",q)),!(i.table.rows.length<2)){if(!p){for(var r;n.length<3&&o<i.table.tBodies[0].rows.length;)r=j?f(i.table.tBodies[0].rows[o].cells,j):i.table.tBodies[0].rows[o].cells[k],m=r?d(r):"",m=m.trim(),m.length>0&&n.push(m),o++;if(!n)return}for(o=0;o<b.length;o++)if(m=b[o],p){if(m.name===p){l=m.sort;break}}else if(n.every(m.pattern)){l=m.sort;break}for(i.col=k,o=0;o<i.table.tBodies.length;o++){var s,t=[],u={},v=0,w=0;if(!(i.table.tBodies[o].rows.length<2)){for(s=0;s<i.table.tBodies[o].rows.length;s++){var r;m=i.table.tBodies[o].rows[s],"none"===m.getAttribute("data-sort-method")?u[v]=m:(r=j?f(m.cells,j):m.cells[i.col],t.push({tr:m,td:r?d(r):"",index:v})),v++}for("descending"===q?t.sort(g(l,!0)):(t.sort(g(l,!1)),t.reverse()),s=0;s<v;s++)u[s]?(m=u[s],w++):m=t[s-w].tr,i.table.tBodies[o].appendChild(m)}}i.table.dispatchEvent(c("afterSort"))}},refresh:function(){void 0!==this.current&&this.sortTable(this.current,!0)}},"undefined"!=typeof module&&module.exports?module.exports=a:window.Tablesort=a}();
\ No newline at end of file
diff --git a/user_config/mkdocs.local.yml b/user_config/mkdocs.local.yml
new file mode 100644
index 0000000000000000000000000000000000000000..222c0fd32fa76d7b02d2eff11b67b8c341e22e3d
--- /dev/null
+++ b/user_config/mkdocs.local.yml
@@ -0,0 +1,251 @@
+### BEGIN MKDOCS TEMPLATE ###
+# ---------------------------------------------------------------------------
+# Below content is automatically managed with repo mkdocs_template.
+# Do not edit manually
+# ---------------------------------------------------------------------------
+
+# Website Information
+# ---------------------------------------------------------------------------
+site_name: ""      # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+#site_description: # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+#site_url:         # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+#copyright:        # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+docs_dir: docs
+
+# Repository Information
+# ---------------------------------------------------------------------------
+#repo_name: # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+#repo_url:  # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+edit_uri: ""
+# This setting controls the style used for linking to pages within the
+# documentation.
+use_directory_urls: false
+
+# Theme Configuration
+# ---------------------------------------------------------------------------
+theme:
+  # Using mkdocs-material theme
+  # https://squidfunk.github.io/mkdocs-material/
+  name: material
+  # Overriding parent theme configuration
+  custom_dir: docs/theme
+  # Determines whether the search plugin expects the theme to provide a
+  # dedicated search page via a template located at search/search.html.
+  include_search_page: false
+  # Determines whether the search plugin should only generate a search
+  # index or a complete search solution.
+  search_index_only: true
+  # Language site
+  language: en
+  # Optional features like tabs and instant loading are now implemented
+  # as flags and can be enabled by listing them in mkdocs.yml under
+  # theme.features:
+  features:
+    - navigation.tabs
+    - navigation.instant
+    - navigation.top
+  # Setting colors palette (these are defined in docs/theme/css/{colors,theme}.css)
+  palette:
+    # Light mode
+    - media: "(prefers-color-scheme: light)"
+      scheme: pagoda-light
+      primary: pagoda-deep-purple-light
+      accent: pagoda-orange-light
+      toggle:
+        icon: material/weather-night
+        name: Switch to dark mode
+    # Dark mode
+    - media: "(prefers-color-scheme: dark)"
+      scheme: pagoda-dark
+      primary: pagoda-deep-purple-dark
+      accent: pagoda-orange-dark
+      toggle:
+        icon: material/weather-sunny
+        name: Switch to light mode
+  # Font configuration for the website (FurCode are provided in
+  # docs/theme/fonts)
+  font: false
+  #  text: FuraCode Nerd Font
+  #  code: FuraCode Nerd Font
+  # Path to logo and icons to use for the website
+  #logo:    # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+  #icon:
+  #  repo:  # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+  #favicon: # Automatically set by mkdocs_macros_plugin (see docs/_data/plugins.py)
+
+# External CSS
+# ---------------------------------------------------------------------------
+extra_css:
+  # Define personal extra css
+  - theme/css/extra.css
+  # Define colors (all materials colors RGB code)
+  - theme/css/colors.css
+  # Define themes
+  - theme/css/theme.css
+  # Define css of base markdown extension and pymdown extension
+  - theme/css/python_markdown_extension.css
+
+# External JS
+# ---------------------------------------------------------------------------
+extra_javascript:
+  # Define javascript to allow table sorting
+  # From: https://squidfunk.github.io/mkdocs-material/reference/data-tables/#sortable-tables
+  - theme/js/tablesort.min.js
+  # Define personal custom javascript
+  - theme/js/extra.js
+
+# Extensions
+# ---------------------------------------------------------------------------
+markdown_extensions:
+  # Allow to include markdown files
+  # https://github.com/sethen/markdown-include
+  - markdown_include.include:
+      base_path: ./
+  # Python Markdown Extensions
+  # https://python-markdown.github.io/extensions/
+  - markdown.extensions.toc:
+      slugify: !!python/name:pymdownx.slugs.uslugify
+      permalink: ""
+  - markdown.extensions.admonition:
+  - markdown.extensions.smarty:
+      smart_quotes: false
+  - markdown.extensions.attr_list:
+  - markdown.extensions.def_list:
+  - markdown.extensions.tables:
+  - markdown.extensions.abbr:
+  - markdown.extensions.footnotes:
+  - markdown.extensions.meta:
+  - markdown.extensions.md_in_html:
+  # Pymdown Extensions
+  - pymdownx.extra:
+  - pymdownx.betterem:
+  - pymdownx.details:
+  - pymdownx.caret:
+  - pymdownx.escapeall:
+      hardbreak: True
+      nbsp: True
+  - pymdownx.critic:
+  - pymdownx.emoji:
+      emoji_index: !!python/name:pymdownx.emoji.twemoji
+      emoji_generator: !!python/name:pymdownx.emoji.to_svg
+  - pymdownx.inlinehilite:
+  - pymdownx.highlight:
+      linenums: true
+      linenums_special: 2
+      linenums_style: pymdownx-inline
+      guess_lang: false
+      extend_pygments_lang:
+        - name: pycon3
+          lang: pycon
+          options:
+            python3: true
+  - pymdownx.keys:
+      separator: "\uff0b"
+  - pymdownx.mark:
+  - pymdownx.magiclink:
+      repo_url_shortener: true
+  - pymdownx.progressbar:
+  - pymdownx.pathconverter:
+  - pymdownx.smartsymbols:
+  - pymdownx.snippets:
+  - pymdownx.striphtml:
+  - pymdownx.superfences:
+      preserve_tabs: true
+  - pymdownx.tabbed:
+  - pymdownx.tasklist:
+      custom_checkbox: true
+  - pymdownx.tilde:
+  # Locally installed in docs/theme/plugins/ from original repo
+  # https://github.com/g-provost/lightgallery-markdown
+  - lightgallery:
+
+# Extra Data Information & Customization
+# ---------------------------------------------------------------------------
+# Dictionary storing social icon that will be shown on the bottom right.
+extra:
+  social:
+    - icon: fontawesome/solid/globe
+      link: https://projet.liris.cnrs.fr/pagoda
+      name: PAGoDA Website
+    - icon: fontawesome/brands/gitlab
+      link: https://gitlab.liris.cnrs.fr/pagoda/
+      name: "@pagoda on Gitlab LIRIS"
+  version:
+    provider: mike
+
+# Plugins
+# ---------------------------------------------------------------------------
+plugins:
+  - search:
+    # https://github.com/timvink/mkdocs-git-revision-date-localized-plugin
+    # MkDocs plugin that enables displaying the date of the last git
+    # modification of a page.
+  - git-revision-date-localized:
+      locale: en
+      fallback_to_build_date: true
+    # https://github.com/oprypin/mkdocs-section-index
+    # MkDocs plugin to allow clickable sections that lead to an index page
+  - section-index:
+    # https://github.com/apenwarr/mkdocs-exclude
+    # A mkdocs plugin that lets you exclude files or trees.
+  - exclude:
+      regex:
+        - .*theme.*.md
+    # https://github.com/fralau/mkdocs_macros_plugin
+    # Unleash the power of MkDocs with variables and macros
+  - macros:
+      module_name: docs/_data/plugins
+      include_dir: ./
+      include_yaml:
+        - docs/_data/vars.yaml
+        # Others yaml include are done automatically using
+        # mkdocs_macros_plugin (see docs/_data/plugins.py)
+    # https://spotify.github.io/mkdocs-monorepo-plugin/
+    # This plugin enables you to build multiple sets of documentation in a
+    # single Mkdocs.
+  - monorepo:
+    # https://pawamoy.github.io/mkdocstrings/
+    # Automatic documentation from sources, for MkDocs.
+  - mkdocstrings:
+      default_handler: python
+      handlers:
+        python:
+          rendering:
+            show_source: true
+            show_if_no_docstring: true
+            show_root_heading: false
+            show_root_toc_entry: false
+            show_root_full_path: true
+            show_object_full_path: true
+            show_root_members_full_path: true
+            show_category_heading: true
+            show_signature_annotations: false
+            group_by_category: true
+            heading_level: 2
+          setup_commands:
+            - import sys
+            # Others command such as sys.path.append("path") are
+            # Automatically added using mkdocs_macros_plugin
+            # (see docs/_data/plugins.py)
+# DO NOT FORGET TO ADD/UPDATE THE \`nav\` KEY BELOW.
+### END MKDOCS TEMPLATE ###
+#  - redirects:
+#      redirect_maps:
+#        index.md: index.fork.md
+
+# Navigation Pane
+# ---------------------------------------------------------------------------
+nav:
+  - Home: index.md
+  - About:
+    - about/index.md
+    - Code of Conduct: about/code_of_conduct.md
+    - Contributing: about/contributing.md
+    - Data Privacy: about/data_privacy.md
+    - License: about/license.md
+    - Release Notes: about/release_notes.md
+
+# *****************************************************************************
+# VIM MODELINE
+# vim: ft=yaml: fdm=indent
+# *****************************************************************************
diff --git a/user_config/post_setup.sh b/user_config/post_setup.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8f80876c3861da721bb0dc6a09787457a13807fd
--- /dev/null
+++ b/user_config/post_setup.sh
@@ -0,0 +1,398 @@
+#!/usr/bin/env bash
+# """Post setup script to handle the README.md file
+#
+# SYNOPSIS:
+#   NOT TO BE USED ALONE, MUST BE SOURCED
+#
+# DESCRIPTION:
+#   This script will define methods to  install/upgrade the file README.md base
+#   on the git remote origin if its exists else, will ask the user to provide
+#   information.
+#
+# """
+
+# Set constant variables
+BASE_ONLINE_DOC_URL="https://docs.romaindeville.fr/"
+REPO_URL=""
+REPO_NAME=""
+REPO_NAME_FIRST_UPPERCASE=""
+REPO_ONLINE_DOC_URL=""
+
+main_post_setup()
+{
+  # """User defined post-setup config which handle update of `README.md`
+  #
+  # Main post-setup method which handle the management of `README.md` file from
+  # `user_config` folder using git repo information. If current repo is not a
+  # git repository without `origin` remote defined, print an error and exit.
+  #
+  # Globals:
+  #   MKDOCS_ROOT
+  #   MKDOCS_CLONE_ROOT
+  #   UPGRADE
+  #
+  # Arguments:
+  #   None
+  #
+  # Output:
+  #   None
+  #
+  # Returns:
+  #   0, If everything went right
+  #   1, If something went wrong
+  #
+  # """
+
+  #   - SC2034: var appears unused, Verify use (or export if used externally)
+  # shellcheck disable=SC2034
+  mkdocs_log()
+  {
+    # """Print debug message in colors depending on message severity on stderr.
+    #
+    # Echo colored log depending on user provided message severity. Message
+    # severity are associated to following color output:
+    #
+    #   - `DEBUG` print in the fifth color of the terminal (usually magenta)
+    #   - `INFO` print in the second color of the terminal (usually green)
+    #   - `WARNING` print in the third color of the terminal (usually yellow)
+    #   - `ERROR` print in the third color of the terminal (usually red)
+    #
+    # If no message severity is provided, severity will automatically be set to
+    # INFO.
+    #
+    # Globals:
+    #   ZSH_VERSION
+    #   MKDOCS_DEBUG_LEVEL
+    #
+    # Arguments:
+    #   $1 : string, message severity or message content
+    #   $@ : string, message content
+    #
+    # Output:
+    #   Colored log informations
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    # Store color prefixes in variable to ease their use.
+    # Base on only 8 colors to ensure portability of color when in tty
+    local e_normal="\e[0m"     # Normal (usually white fg & transparent bg)
+    local e_bold="\e[1m"       # Bold
+    local e_underline="\e[4m"  # Underline
+    local e_debug="\e[0;35m"   # Fifth term color (usually magenta fg)
+    local e_info="\e[0;32m"    # Second term color (usually green fg)
+    local e_warning="\e[0;33m" # Third term color (usually yellow fg)
+    local e_error="\e[0;31m"   # First term color (usually red fg)
+
+    # Store preformated colored prefix for log message
+    local error="${e_bold}${e_error}[ERROR]${e_normal}${e_error}"
+    local warning="${e_bold}${e_warning}[WARNING]${e_normal}${e_warning}"
+    local info="${e_bold}${e_info}[INFO]${e_normal}${e_info}"
+    local debug="${e_bold}${e_debug}[DEBUG]${e_normal}${e_debug}"
+
+    local color_output="e_error"
+    local msg_severity
+    local msg
+
+    # Not using ${1^^} to ensure portability when using ZSH
+    msg_severity=$(echo "$1" | tr '[:upper:]' '[:lower:]')
+
+    if [[ "${msg_severity}" =~ ^(error|time|warning|info|debug)$ ]]
+    then
+      # Shift arguments by one such that $@ start from the second arguments
+      shift
+      # Place the content of variable which name is defined by ${msg_severity}
+      # For instance, if `msg_severity` is INFO, then `prefix` will have the same
+      # value as variable `info`.
+      if [[ -n "${ZSH_VERSION}" ]]
+      then
+        prefix="${(P)msg_severity}"
+      else
+        prefix="${!msg_severity}"
+      fi
+      color_output="e_${msg_severity}"
+    else
+      prefix="${info}"
+    fi
+
+    if [[ -n "${ZSH_VERSION}" ]]
+    then
+      color_output="${(P)color_output}"
+    else
+      color_output="${!color_output}"
+    fi
+
+    # Concat all remaining arguments in the message content and apply markdown
+    # like syntax.
+    msg_content=$(echo "$*" \
+      | sed -e "s/ \*\*/ \\${e_bold}/g" \
+            -e "s/\*\*\./\\${e_normal}\\${color_output}./g" \
+            -e "s/\*\* /\\${e_normal}\\${color_output} /g" \
+            -e "s/\*\*$/\\${e_normal}\\${color_output} /g" \
+            -e "s/ \_\_/ \\${e_underline}/g" \
+            -e "s/\_\_\./\\${e_normal}\\${color_output}./g" \
+            -e "s/\_\_ /\\${e_normal}\\${color_output} /g")
+    msg="${prefix} ${msg_content}${e_normal}"
+
+    # Print message or not depending on message severity and MKDOCS_DEBUG_LEVEL
+    if [[ -z "${MKDOCS_DEBUG_LEVEL}" ]] && [[ "${msg_severity}" == "error" ]]
+    then
+      echo -e "${msg}" 1>&2
+    elif [[ -n "${MKDOCS_DEBUG_LEVEL}" ]]
+    then
+      case ${MKDOCS_DEBUG_LEVEL} in
+        DEBUG)
+          echo "${msg_severity}" \
+            | grep -q -E "(debug|info|warning|error)" && echo -e "${msg}" 1>&2
+          ;;
+        INFO)
+          echo "${msg_severity}" \
+            | grep -q -E "(info|warning|error)" && echo -e "${msg}" 1>&2
+          ;;
+        WARNING)
+          echo "${msg_severity}" \
+            | grep -q -E "(warning|error)" && echo -e "${msg}" 1>&2
+          ;;
+        ERROR)
+          echo "${msg_severity}" \
+            | grep -q -E "error" && echo -e "${msg}" 1>&2
+          ;;
+      esac
+    fi
+  }
+
+  extract_repo_info()
+  {
+    # """Extract repository from the origin remote
+    #
+    # Parse output of command `git remote -v | grep origin` to setup repo
+    # information store in `REPO_*` variables
+    #
+    # Globals:
+    #   REPO_URL
+    #   REPO_NAME
+    #   REPO_NAME_FIRST_UPPERCASE
+    #   REPO_NAME_FIRST_UPPERCASE_ARRAY
+    #   REPO_ONLINE_DOC_URL
+    #
+    # Arguments:
+    #   None
+    #
+    # Output:
+    #   None
+    #
+    # Returns:
+    #   None
+    # """
+
+    local repo_remote
+    local repo_domain
+
+    repo_remote=$(git remote -v | \
+                    grep origin | \
+                    head -1 | \
+                    sed -e "s/origin\t//g" -e "s/ *([a-z]*)//g")
+
+    if [[ "${repo_remote}" =~ @ ]]
+    then
+      repo_remote=${repo_remote##*@}
+      repo_domain="https://${repo_remote%%:*}/"
+      repo_with_namespace="${repo_remote##*:}"
+    else
+      repo_domain=${repo_remote##https:\/\/}
+      repo_domain="https://${repo_domain%%/*}/"
+      repo_with_namespace="${repo_remote/${repo_domain}/}"
+    fi
+    REPO_URL="${repo_domain}${repo_with_namespace/.git/}"
+    REPO_NAME="${repo_with_namespace##*/}"
+    REPO_NAME="${REPO_NAME/.git/}"
+    REPO_NAME_FIRST_UPPERCASE="${REPO_NAME/_/ }"
+    REPO_NAME_FIRST_UPPERCASE="${REPO_NAME_FIRST_UPPERCASE/-/ }"
+    # shellcheck disable=SC2206
+    #   - SC2206: Quote to prevent word splitting/globbing
+    REPO_NAME_FIRST_UPPERCASE_ARRAY=( ${REPO_NAME_FIRST_UPPERCASE} )
+    # shellcheck disable=SC2178
+    #   - SC2178: Variabel was used as an array but is now assigned a string
+    REPO_NAME_FIRST_UPPERCASE="${REPO_NAME_FIRST_UPPERCASE_ARRAY[*]^}"
+    REPO_ONLINE_DOC_URL="${BASE_ONLINE_DOC_URL}${repo_with_namespace/.git/}"
+  }
+
+  ensure_remote_origin()
+  {
+    # """Ensure remote `origin` exists and parse remote info
+    #
+    # Ensure current folder is a git folder with an `origin` remote defined. If
+    # not, print an error else extract repository information from remote.
+    #
+    # Globals:
+    #   None
+    #
+    # Arguments:
+    #   None
+    #
+    # Output:
+    #   Error message if git remote `origin` does not exists
+    #
+    # Returns:
+    #   0, if everything went right
+    #   1, if remote `origin` does not exists or not in a git repository
+    # """
+
+    if ! git remote -v | grep origin &> /dev/null
+    then
+      mkdocs_log "WARNING" "Unable to fetch git remote **\`origin\`**!"
+      mkdocs_log "WARNING" "Are you sure you are in a git repository with an origin remote defined ?"
+      return 1
+    else
+      extract_repo_info
+    fi
+  }
+
+  upgrade_readme()
+  {
+    # """Upgrade latest version of README.md
+    #
+    # Check if latest version of README.md is different from the old version. If
+    # yes, then move the old version to ${MKDOCS_ROOT}/.old then upgrade to
+    # latest version.
+    #
+    # Globals:
+    #   MKDOCS_ROOT
+    #   REPO_URL
+    #   REPO_NAME
+    #   REPO_NAME_FIRST_UPPERCASE
+    #   REPO_NAME_FIRST_UPPERCASE_ARRAY
+    #   REPO_ONLINE_DOC_URL
+    #
+    # Arguments:
+    #   $1, string, absolute path to the latest file version to be installed
+    #   $2, string, absolute path to the location of the installation
+    #
+    # Output:
+    #   Log messages
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    local file_from="$1"
+    local file_to="$2"
+    local relative_file_to="${file_to##*${MKDOCS_ROOT}\/}"
+    local tmp_file_from="${MKDOCS_TMP}/${relative_file_to}.new"
+    local tmp_file_to="${MKDOCS_TMP}/${relative_file_to}.old"
+    local bak_file=${file_to//${MKDOCS_ROOT}/${MKDOCS_ROOT}\/.old}
+    local begin="<\!-- BEGIN MKDOCS TEMPLATE -->"
+    local end="<\!-- END MKDOCS TEMPLATE -->"
+    local bak_dir
+
+    bak_file=${bak_file}.$(date "+%Y-%m-%d-%H-%M")
+    bak_dir=$(dirname "${bak_file}")
+
+    sed -n -e "/${begin}/,/${end}/"p "${file_from}" > "${tmp_file_from}"
+    sed -i \
+      -e "s|<TPL:REPO_NAME>|${REPO_NAME}|g" \
+      -e "s|<TPL:REPO_URL>|${REPO_URL}|g" \
+      -e "s|<TPL:REPO_ONLINE_DOC_URL>|${REPO_ONLINE_DOC_URL}|g" \
+      -e "s|<TPL:REPO_NAME_FIRST_UPPERCASE>|${REPO_NAME_FIRST_UPPERCASE}|g" \
+      "${tmp_file_from}"
+
+    sed -n -e "/${begin}/,/${end}/"p "${file_to}" > "${tmp_file_to}"
+
+    if [[ "$(sha1sum "${tmp_file_from}" | cut -d " " -f 1 )" \
+       != "$(sha1sum "${tmp_file_to}"   | cut -d " " -f 1 )" ]]
+    then
+      mkdocs_log "INFO" "Backup file **${relative_file_to}** to **${bak_file##*${MKDOCS_ROOT}\/}.**"
+      if ! [[ -d "${bak_dir}" ]]
+      then
+        mkdir -p "${bak_dir}"
+      fi
+      cp "${file_to}" "${bak_file}"
+
+      grep -B 1000000 "${begin}" "${file_to}" | sed -e "s/${begin}//g" > "${tmp_file_to}"
+      cat "${tmp_file_from}" >> "${tmp_file_to}"
+      grep -A 1000000 "${end}" "${file_to}" | sed -e "s/${end}//g" >> "${tmp_file_to}"
+      cat "${tmp_file_to}" > "${file_to}"
+    fi
+  }
+
+  setup_readme()
+  {
+    # """Install latest version of README.md from user_config folder
+    #
+    # Simply install README.md file replacing <TPL:XXX> with previously computed
+    # value.
+    #
+    # Globals:
+    #   MKDOCS_ROOT
+    #   REPO_URL
+    #   REPO_NAME
+    #   REPO_NAME_FIRST_UPPERCASE
+    #   REPO_NAME_FIRST_UPPERCASE_ARRAY
+    #   REPO_ONLINE_DOC_URL
+    #
+    #
+    # Arguments:
+    #   $1, string, absolute path to the latest file version to be installed
+    #   $2, string, absolute path to the location of the installation
+    #
+    # Output:
+    #   Log messages
+    #
+    # Returns:
+    #   None
+    #
+    # """
+
+    local file_from="$1"
+    local file_to="$2"
+    local relative_file_to="${file_to##*${MKDOCS_ROOT}\/}"
+    local begin="<!-- BEGIN MKDOCS TEMPLATE -->"
+    local end="<!-- END MKDOCS TEMPLATE -->"
+
+    mkdocs_log "INFO" "Installing file **${relative_file_to}**."
+    content=""
+    if ! grep "${begin}" "${file_from}" &> /dev/null
+    then
+      content+="\
+${begin}
+<!--
+WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG !
+Modified content will be overwritten when updating
+-->
+
+$(cat "${file_from}")
+
+${end}"
+    else
+      content="$(cat "${file_from}")"
+    fi
+    echo -e "${content}" | \
+      sed -e "s|<TPL:REPO_NAME>|${REPO_NAME}|g" \
+          -e "s|<TPL:REPO_URL>|${REPO_URL}|g" \
+          -e "s|<TPL:REPO_ONLINE_DOC_URL>|${REPO_ONLINE_DOC_URL}|g" \
+          -e "s|<TPL:REPO_NAME_FIRST_UPPERCASE>|${REPO_NAME_FIRST_UPPERCASE}|g" \
+      > "${file_to}"
+  }
+
+  if ! ensure_remote_origin
+  then
+    return 1
+  fi
+
+  file_from="${MKDOCS_CLONE_ROOT}/user_config/README.md"
+  file_to="${MKDOCS_ROOT}/README.md"
+  if [[ "${UPGRADE}" == "true" ]]
+  then
+    upgrade_readme "${file_from}" "${file_to}"
+  else
+    setup_readme "${file_from}" "${file_to}"
+  fi
+}
+
+# *****************************************************************************
+# VIM MODELINE
+# vim: fdm=indent:fdi=
+# *****************************************************************************
diff --git a/user_config/pyproject.toml b/user_config/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..28d6eff85105a5616658835b02f3185fcc334ae2
--- /dev/null
+++ b/user_config/pyproject.toml
@@ -0,0 +1,1206 @@
+# No need for [build-system] as this pyproject.toml per PEP-518 as this file
+# serve to a centralized configuration file for development tools such as
+# black, flake8/flake9, pylint, pycodestyle, etc.
+[build-system]
+requires = [
+  "setuptools",
+  "wheel"
+]
+build-backend = "setuptools.build_meta"
+
+# -----------------------------------------------------------------------------
+# Tox (Test automation) configuration
+# https://tox.readthedocs.io/en/latest/#
+[tool.tox]
+legacy_tox_ini="""
+# Global configuration
+[tox]
+isolated_build=true
+skipsdist=true
+envlist=format_{python,shell},build_doc
+
+[testenv:format_python]
+# Allow external commands
+allowlist_externals=
+  /usr/bin/bash
+skip_install=true
+deps =
+  -r./requirements.prod.txt
+  -r./requirements.dev.txt
+commands =
+  # Automatically sort import in python files
+  isort .
+  # Automatically format code
+  black ./
+  # Lint python files using pylint
+  bash -c '\
+    pylint \
+      $(find . -type f \\( \
+        -name "*.py" \
+        -not -path "./.*" \
+        -not -path "./docs/theme/*" \
+        -not -path "./python_venv/*" \
+        -not -path "./tmp/*" \
+        -not -path "./site**/*"  \\) )'
+  # Lint python files using flake8
+  flake8
+  # Ensure docstring convention (google is mkdocs rendering documentation)
+  pydocstyle --count --convention=google
+
+[testenv:format_shell]
+# Allow external commands
+allowlist_externals=
+  /usr/bin/bash
+skip_install=true
+deps =
+  -r./requirements.prod.txt
+  -r./requirements.dev.txt
+commands =
+  # Linter bash script using shellcheck
+  bash -c '\
+    shellcheck \
+      -s bash \
+      -x \
+      $(find . -type f \\( \
+        -name "*.sh" \
+        -not -path "./.*" \
+        -not -path "./python_venv/*" \\) ) '
+  bash -c 'DIRENV_ROOT="$(pwd)" ./tools/generate_source_docs.sh --dry-run'
+
+
+[testenv:build_doc]
+# Allow external commands
+allowlist_externals=
+  /usr/bin/bash
+  /usr/bin/rm
+skip_install=true
+deps =
+  -r./requirements.docs.txt
+commands =
+  # Ensure build of documentation website is working
+  mkdocs build -d site_local
+  # If everything went right, remove build site
+  rm -rf site_local
+  bash -c '\
+    if [[ -f "mkdocs.local.yml" ]]; \
+    then \
+      mkdocs build -f mkdocs.local.yml -d site_monorepo; \
+      rm -rf site_monorepo; \
+    fi'
+"""
+
+
+### BEGIN MKDOCS TEMPLATE ###
+### WARNING, DO NOT UPDATE CONTENT BETWEEN MKDOCS TEMPLATE TAG ! ###
+### Modified content will be overwritten when updating. ###
+
+# -----------------------------------------------------------------------------
+# Pytest configuration
+# https://docs.pytest.org/en/latest/customize.html?highlight=pyproject#pyproject-toml
+[tool.pytest.ini_options]
+  # TODO: Find online documentation about this option.
+ignore=[".tox",".direnv", "python_venv"]
+
+  # Sets list of directories that should be searched for tests when no specific
+  # directories, files or test ids are given in the command line when executing
+  # pytest from the rootdir directory. Useful when all project tests are in a
+  # known location to speed up test collection and to avoid picking up undesired
+  # tests by accident.
+testpaths=[ "test" ]
+
+# -----------------------------------------------------------------------------
+# For sorting imports
+# https://timothycrosley.github.io/isort/
+[tool.isort]
+  # Tells isort to set the known standard library based on the specified Python
+  # version. Default is to assume any Python 3 version could be the target, and use
+  # a union of all stdlib modules across versions. If auto is specified, the
+  # version of the interpreter used to run isort (currently: 38) will be used.
+  # Default:`py3`
+#py_version="py3"
+
+  # Force specific imports to the top of their appropriate section.
+  # Default: `frozenset()`
+#force_to_top=[]
+
+  # Files that sort imports should skip over. If you want to skip multiple files
+  # you should specify twice: --skip file1 --skip file2.
+  # Default: `('.bzr', '.direnv', '.eggs', '.git', '.hg', '.mypy_cache', '.nox',
+  # '.pants.d', '.svn', '.tox', '.venv', '_build', 'buck-out', 'build', 'dist',
+  # 'node_modules', 'venv')`
+skip=['.bzr',
+      '.direnv',
+      '.eggs',
+      '.git',
+      '.hg',
+      '.mypy_cache',
+      '.nox',
+      '.pants.d',
+      '.svn',
+      '.tox',
+      '.venv',
+      '_build',
+      'buck-out',
+      'build',
+      'dist',
+      'node_modules',
+      'venv',
+      'python_venv']
+
+  # Files that sort imports should skip over.
+  # Default: frozenset()
+#skip_glob=[]
+
+  # Treat project as a git repository and ignore files listed in .gitignore
+  # Default: `False`
+skip_gitignore=true
+
+  # The max length of an import line (used for wrapping long imports).
+  # Default: `79`
+line_length=80
+
+  # Specifies how long lines that are wrapped should be, if not set line_length is
+  # used. NOTE: wrap_length must be LOWER than or equal to line_length.
+  # Default: `0`
+#wrap_length=0
+
+  # Forces line endings to the specified value. If not set, values will be guessed
+  # per-file.
+  # Default: ``
+#line_ending
+
+  # Order of import
+  # Default:`('FUTURE', 'STDLIB', 'THIRDPARTY', 'FIRSTPARTY', 'LOCALFOLDER')`
+#sections=
+
+  # Put all imports into the same section bucket
+  # Default: `False`
+#no_sections=false
+
+  # Force isort to recognize a module as part of Python's internal future
+  # compatibility libraries. WARNING: this overrides the behavior of __future__
+  # handling and therefore can result in code that can't execute. If you're looking
+  # to add dependencies such as six a better option is to create a another section
+  # below --future using custom sections. See:
+  # https://github.com/PyCQA/isort#custom-sections-and-ordering and the discussion
+  # here: https://github.com/PyCQA/isort/issues/1463.
+  # Default: `('__future__',)`
+#known_future_library=
+
+  # Force isort to recognize a module as being part of a third party library.
+  # Default: `frozenset()`
+#known_third_party=
+
+  # Force isort to recognize a module as being part of the current python project.
+  # Default: `frozenset()`
+#known_first_party=
+
+  # Force isort to recognize a module as being a local folder. Generally, this is
+  # reserved for relative imports (from . import module).
+  # Default: `frozenset()`
+#known_local_folder=
+
+  # Force isort to recognize a module as part of Python's standard library.
+  # Default: `('_dummy_thread', '_thread', 'abc', 'aifc', 'argparse', 'array',
+  # 'ast', 'asynchat', 'asyncio', 'asyncore', 'atexit', 'audioop', 'base64',
+  # 'bdb', 'binascii', 'binhex', 'bisect', 'builtins', 'bz2', 'cProfile',
+  # 'calendar', 'cgi', 'cgitb', 'chunk', 'cmath', 'cmd', 'code', 'codecs',
+  # 'codeop', 'collections', 'colorsys', 'compileall', 'concurrent',
+  # 'configparser', 'contextlib', 'contextvars', 'copy', 'copyreg', 'crypt',
+  # 'csv', 'ctypes', 'curses', 'dataclasses', 'datetime', 'dbm', 'decimal',
+  # 'difflib', 'dis', 'distutils', 'doctest', 'dummy_threading', 'email',
+  # 'encodings', 'ensurepip', 'enum', 'errno', 'faulthandler', 'fcntl', 'filecmp',
+  # 'fileinput', 'fnmatch', 'formatter', 'fpectl', 'fractions', 'ftplib',
+  # 'functools', 'gc', 'getopt', 'getpass', 'gettext', 'glob', 'graphlib', 'grp',
+  # 'gzip', 'hashlib', 'heapq', 'hmac', 'html', 'http', 'imaplib', 'imghdr',
+  # 'imp', 'importlib', 'inspect', 'io', 'ipaddress', 'itertools', 'json',
+  # 'keyword', 'lib2to3', 'linecache', 'locale', 'logging', 'lzma', 'macpath',
+  # 'mailbox', 'mailcap', 'marshal', 'math', 'mimetypes', 'mmap', 'modulefinder',
+  # 'msilib', 'msvcrt', 'multiprocessing', 'netrc', 'nis', 'nntplib', 'ntpath',
+  # 'numbers', 'operator', 'optparse', 'os', 'ossaudiodev', 'parser', 'pathlib',
+  # 'pdb', 'pickle', 'pickletools', 'pipes', 'pkgutil', 'platform', 'plistlib',
+  # 'poplib', 'posix', 'posixpath', 'pprint', 'profile', 'pstats', 'pty', 'pwd',
+  # 'py_compile', 'pyclbr', 'pydoc', 'queue', 'quopri', 'random', 're',
+  # 'readline', 'reprlib', 'resource', 'rlcompleter', 'runpy', 'sched', 'secrets',
+  # 'select', 'selectors', 'shelve', 'shlex', 'shutil', 'signal', 'site', 'smtpd',
+  # 'smtplib', 'sndhdr', 'socket', 'socketserver', 'spwd', 'sqlite3', 'sre',
+  # 'sre_compile', 'sre_constants', 'sre_parse', 'ssl', 'stat', 'statistics',
+  # 'string', 'stringprep', 'struct', 'subprocess', 'sunau', 'symbol', 'symtable',
+  # 'sys', 'sysconfig', 'syslog', 'tabnanny', 'tarfile', 'telnetlib', 'tempfile',
+  # 'termios', 'test', 'textwrap', 'threading', 'time', 'timeit', 'tkinter',
+  # 'token', 'tokenize', 'trace', 'traceback', 'tracemalloc', 'tty', 'turtle',
+  # 'turtledemo', 'types', 'typing', 'unicodedata', 'unittest', 'urllib', 'uu',
+  # 'uuid', 'venv', 'warnings', 'wave', 'weakref', 'webbrowser', 'winreg',
+  # 'winsound', 'wsgiref', 'xdrlib', 'xml', 'xmlrpc', 'zipapp', 'zipfile',
+  # 'zipimport', 'zlib', 'zoneinfo')`
+#known_standard_library=
+
+  # Extra modules to be included in the list of ones in Python's standard library.
+  # Default: `frozenset()`
+#extra_standard_library=
+
+  # No Description
+  # ----- Example `pyproject.toml`
+  # ```
+  # [tool.isort]
+  # sections=['FUTURE', 'STDLIB', 'THIRDPARTY', 'AIRFLOW', 'FIRSTPARTY', 'LOCALFOLDER']
+  # known_airflow=['airflow']
+  # ```
+  # Default: `{}`
+#known_other=
+
+  # Multi line output (0-grid, 1-vertical, 2-hanging, 3-vert-hanging, 4-vert-grid,
+  # 5-vert-grid-grouped, 6-vert-grid-grouped-no-comma, 7-noqa,
+  # 8-vertical-hanging-indent-bracket, 9-vertical-prefix-from-module-import,
+  # 10-hanging-indent-with-parentheses).
+  # Default: `WrapModes.GRID`
+multi_line_output=3
+
+  # No Description**
+  # Default: `()`
+#forced_separate=
+
+  # String to place for indents defaults to "    " (4 spaces).
+  # Default: `    `
+#indent=
+
+  # No Description
+  # Default: `  #`
+#comment_prefix=
+
+  # Sort imports by their string length.
+  # Default: `False`
+#length_sort=false
+
+  # Sort straight imports by their string length. Similar to `length_sort` but
+  # applies only to straight imports and doesn't affect from imports.
+  # Default: `False`
+#length_sort_straight=false
+
+  # No Description
+  # Default: `frozenset()`
+#length_sort_sections=[]
+
+  # Adds the specified import line to all files, automatically determining correct
+  # placement.
+  # Default: `frozenset()`
+#add_imports=[]
+
+  # Removes the specified import from all files.
+  # Default: `frozenset()`
+#remove_imports=[]
+
+  # Only adds the imports specified in --add-import if the file contains existing
+  # imports.
+  # Default: `False`
+#append_only=false
+
+  # Reverse order of relative imports.
+  # Default: `False`
+#reverse_relative=false
+
+  # Forces all from imports to appear on their own line
+  # Default: `False`
+#force_single_line=false
+
+  # One or more modules to exclude from the single line rule.
+  # Default: `()`
+#single_line_exclusions=[]
+
+  # Sets the default section for import options: ('FUTURE', 'STDLIB',
+  # 'THIRDPARTY', 'FIRSTPARTY', 'LOCALFOLDER')
+  # Default: `THIRDPARTY`
+#default_section="THIRDPARTY
+
+  # No Description
+  # Default: `{}`
+#import_headings=[]
+
+  # Balances wrapping to produce the most consistent line length possible
+  # Default: `False`
+#balanced_wrapping=false
+
+  # Use parentheses for line continuation on length limit instead of slashes.
+  # **NOTE**: This is separate from wrap modes, and only affects how individual
+  # lines that  are too long get continued, not sections of multiple imports.
+  # Default: `False`
+use_parentheses=true
+
+  # Order imports by type, which is determined by case, in addition to alphabetically.
+  # **NOTE**: type here refers to the implied type from the import name
+  # capitalization. isort does not do type introspection for the imports. These
+  # "types" are simply: CONSTANT_VARIABLE, CamelCaseClass, variable_or_function.
+  # If your project follows PEP8 or a related coding standard and has many imports
+  # this is a good default, otherwise you likely will want to turn it off. From
+  # the CLI the `--dont-order-by-type` option will turn this off.
+  # Default:*`True`
+#order_by_type=true
+
+  # Ensures the output doesn't save if the resulting file contains syntax errors.
+  # Default: `False`
+#atomic=false
+
+  # Lines after inmports
+  # Default: `-1`
+#lines_after_imports=-1
+
+  # Lines Between Sections
+  # Default: `1`
+#lines_between_sections=1
+
+  # Lines Between Types
+  # Default: `0`
+#lines_between_types=0
+
+  # Combines as imports on the same line.
+  # Default: `False`
+#combine_as_imports=false
+
+  # Ensures that if a star import is present, nothing else is imported from that
+  # namespace.
+  # Default: `False`
+#combine_star=false
+
+  # Includes a trailing comma on multi line imports that include parentheses.
+  # Default: `False`
+include_trailing_comma=true
+
+  # Switches the typical ordering preference, showing from imports first then
+  # straight ones.
+  # Default: `False`
+#from_first=false
+
+  # Shows verbose output, such as when files are skipped or when a check is
+  # successful.
+  # Default: `False`
+#verbose=false
+
+  # Shows extra quiet output, only errors are outputted.
+  # Default:`False`
+#quiet=false
+
+  # Forces import adds even if the original file is empty.
+  # Default: `False`
+#force_adds=false
+
+  # Force all imports to be sorted alphabetically within a section
+  # Default: `False`
+#force_alphabetical_sort_within_sections= false
+
+  # Force all imports to be sorted as a single section
+  # Default: `False`
+#force_alphabetical_sort=false
+
+  # Force number of from imports (defaults to 2 when passed as CLI flag without
+  # value)to be grid wrapped regardless of line length. If 0 is passed in (the
+  # global default) only line length is considered.
+  # Default: `0`
+force_grid_wrap=0
+
+  # Don't sort straight-style imports (like import sys) before from-style imports
+  # (like from itertools import groupby). Instead, sort the imports by module,
+  # independent of import style.
+  # Default: `False`
+#force_sort_within_sections=false
+
+  # Lexicographical
+  # Default: `False`
+#lexicographical=false
+
+  # Group By Package
+  # Default: `False`
+#group_by_package=false
+
+  # Tells isort to ignore whitespace differences when --check-only is being used.
+  # Default: `False`
+#ignore_whitespace+false
+
+  # Sections which should not be split with previous by empty lines
+  # Default: `frozenset()`
+#no_lines_before=[]
+
+  # Leaves `from` imports with multiple imports 'as-is' (e.g. `from foo import a,
+  # c ,b`).
+  # Default: `False`
+#no_inline_sort=false
+
+  # Ignore Comments
+  # Default: `False`
+#ignore_comments=false
+
+  # Tells isort to include casing when sorting module names
+  # Default: `False`
+#case_sensitive=false
+
+  # Sources
+  # Default: `()`
+#sources=[]
+
+  # Virtual environment to use for determining whether a package is third-party
+  # Default: ``
+#virtual_env=
+
+  # Conda environment to use for determining whether a package is third-party
+  # Default: ``
+#conda_env=
+
+  # Inserts a blank line before a comment following an import.
+  # Default: `False`
+#ensure_newline_before_comments=false
+
+  # Directory
+  # Default: ``
+#directory+
+
+  # Profile
+  # Base profile type to use for configuration. Profiles include: black, django,
+  # pycharm, google, open_stack, plone, attrs, hug. As well as any shared profiles.
+  # Default: ``
+profile="black"
+
+  # Tells isort to honor noqa comments to enforce skipping those comments.
+  # Default: `False`
+#honor_noqa=false
+
+  # Add an explicitly defined source path (modules within src paths have their
+  # imports automatically categorized as first_party).
+  # Default: `()`
+src_paths=["src"]
+
+  # Use the old deprecated finder logic that relies on environment introspection magic.
+  # Default: `False`
+#old_finders=false
+
+  # Tells isort to remove redundant aliases from imports, such as `import os as
+  # os`. This defaults to `False` simply because some projects use these seemingly
+  # useless  aliases to signify intent and change behaviour.
+  # Default: `False`
+#remove_redundant_aliases=false
+
+  # Causes all non-indented imports to float to the top of the file having its
+  # imports sorted (immediately below the top of file comment).
+  # This can be an excellent shortcut for collecting imports every once in a while
+  # when you place them in the middle of a file to avoid context switching.
+  # *NOTE*: It currently doesn't work with cimports and introduces some extra
+  # over-head and a performance penalty.
+  # Default: `False`
+#float_to_top=false
+
+  # Tells isort to filter files even when they are explicitly passed in as part of
+  # the CLI command.
+  # Default: `False`
+#filter_files=false
+
+  # Specifies the name of a formatting plugin to use when producing output.
+  # Default: ``
+#formatter
+
+  # Formatting Function
+  # Default: `None`
+#formatting_function=None
+
+  # Color Output
+  # Tells isort to use color in terminal output.
+  # Default: `False`
+color_output=true
+
+  # Tells isort to treat the specified single line comment(s) as if they are code.
+  # Default: `frozenset()`
+#treat_comments_as_code=[]
+
+  # Tells isort to treat all single line comments as if they are code.
+  # Default: `False`
+#treat_all_comments_as_code=false
+
+  # Specifies what extensions isort can be ran against.
+  # Default: `('pxd', 'py', 'pyi', 'pyx')`
+#supported_extensions=['pxd', 'py', 'pyi', 'pyx']
+
+  # Specifies what extensions isort can never be ran against.
+  # Default: `('pex',)`
+#blocked_extensions=["pex"]
+
+  # Constants
+  # Default: `frozenset()`
+#constants
+
+  # Classes
+  # Default: `frozenset()`
+#classes
+
+  # Variables
+  # Default: `frozenset()`
+#variables
+
+  # Tells isort to only show an identical custom import heading comment once, even
+  # if there are multiple sections with the comment set.
+  # Default: `False`
+#dedup_headings=false
+
+  # Causes imports to be sorted only based on their sections like
+  # STDLIB,THIRDPARTY etc. Imports are unaltered and keep their relative positions
+  # within the different sections.
+  # Default: `False`
+#only_sections=false
+
+  # Suppresses verbose output for non-modified files.
+  # Default: `False`
+#only_modified=false
+
+  # Combines all the bare straight imports of the same section in a single line.
+  # Won't work with sections which have 'as' imports
+  # Default: `False`
+#combine_straight_imports=false
+
+  # Auto Identify Namespace Packages
+  # Default: `True`
+#auto_identify_namespace_packages+true
+
+  # Namespace Packages
+  # Default: `frozenset()`
+#namespace_packages
+
+  # Follow Links
+  # Default: `True`
+#follow_links=
+
+# -----------------------------------------------------------------------------
+# Black (Optionless formatter) configuration
+# https://black.readthedocs.io/en/stable/index.html
+[tool.black]
+  # How many characters per line to allow.
+line-length=80
+
+  # Python versions that should be supported by Black's output
+target-version=['py38']
+
+  # A regular expression that matches files and directories that should be
+  # included on recursive searches. An empty value means all files are included
+  # regardless of the name.  Use forward slashes for directories on all platforms
+  # (Windows, too).  Exclusions are calculated first, inclusions later.
+include='\.pyi?$'
+
+  # A regular expression that matches files and directories that should be
+  # excluded on recursive searches. An empty value means no paths are excluded.
+  # Use forward slashes for directories on all platforms (Windows, too).
+  # Exclusions are calculated first, inclusions later.
+exclude='''
+(
+  /(
+      \.eggs         # exclude a few common directories in the
+    | \.eggs-info
+    | \.git          # root of the project
+    | \.tox
+    | \.venv
+    | \.sha1
+    | \.direnv/python_venv
+    | \.direnv/.sha1
+    | python_venv
+    | build
+    | dist
+    | site
+    | site.tox
+  )/
+)
+'''
+
+# -----------------------------------------------------------------------------
+# Pylint configuration
+# Automatically generated with 'pylint --generate-rcfile'
+# https://pylint.readthedocs.io/en/latest/index.html
+[tool.pylint.'MASTER']
+  # A comma-separated list of package or module names from where C extensions may
+  # be loaded. Extensions are loading into the active Python interpreter and may
+  # run arbitrary code.
+extension-pkg-whitelist=[]
+
+  # Specify a score threshold to be exceeded before program exits with error.
+fail-under=10
+
+  # Add files or directories to the blacklist. They should be base names, not
+  # paths.
+ignore=[".tox",".direnv", "python_venv"]
+
+  # Add files or directories matching the regex patterns to the blacklist. The
+  # regex matches against base names, not paths.
+ignore-patterns=[]
+
+  # Python code to execute, usually for sys.path manipulation such as
+  # pygtk.require().
+  # init-hook=
+  # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
+  # number of processors available to use.
+jobs=0
+
+  # Control the amount of potential inferred values when inferring a single
+  # object. This can help the performance when dealing with large functions or
+  # complex, nested conditions.
+limit-inference-results=100
+
+  # List of plugins (as comma separated values of python module names) to load,
+  # usually to register additional checkers.
+load-plugins=[]
+
+  # Pickle collected data for later comparisons.
+persistent=true
+
+  # When enabled, pylint would attempt to guess common misconfiguration and emit
+  # user-friendly hints instead of false-positive error messages.
+suggestion-mode=true
+
+  # Allow loading of arbitrary C extensions. Extensions are imported into the
+  # active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=false
+
+[tool.pylint.'MESSAGES CONTROL']
+  # Only show warnings with the listed confidence levels. Leave empty to show
+  # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
+confidence=[]
+
+  # Disable the message, report, category or checker with the given id(s). You
+  # can either give multiple identifiers separated by comma (,) or put this
+  # option multiple times (only on the command line, not in the configuration
+  # file where it should appear only once). You can also use "--disable=all" to
+  # disable everything first and then reenable specific checks. For example, if
+  # you want to run only the similarities checker, you can use "--disable=all
+  # --enable=similarities". If you want to run only the classes checker, but have
+  # no Warning level messages displayed, use "--disable=all --enable=classes
+  # --disable=W".
+disable=[]
+
+  # Enable the message, report, category or checker with the given id(s). You can
+  # either give multiple identifier separated by comma (,) or put this option
+  # multiple time (only on the command line, not in the configuration file where
+  # it should appear only once). See also the "--disable" option for examples.
+enable=["c-extension-no-member"]
+
+[tool.pylint.'REPORTS']
+  # Python expression which should return a score less than or equal to 10. You
+  # have access to the variables 'error', 'warning', 'refactor', and 'convention'
+  # which contain the number of messages in each category, as well as 'statement'
+  # which is the total number of statements analyzed. This score is used by the
+  # global evaluation report (RP0004).
+evaluation="10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)"
+
+  # Template used to display messages. This is a python new-style format string
+  # used to format the message information. See doc for all details.
+#msg-template=
+
+  # Set the output format. Available formats are text, parseable, colorized, json
+  # and msvs (visual studio). You can also give a reporter class, e.g.
+  # mypackage.mymodule.MyReporterClass.
+output-format="text"
+
+  # Tells whether to display a full report or only the messages.
+reports=false
+
+  # Activate the evaluation score.
+score=true
+
+
+[tool.pylint.'REFACTORING']
+  # Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+  # Complete name of functions that never returns. When checking for
+  # inconsistent-return-statements if a never returning function is called then
+  # it will be considered as an explicit return statement and no message will be
+  # printed.
+never-returning-functions=["sys.exit"]
+
+
+[tool.pylint.'TYPECHECK']
+  # List of decorators that produce context managers, such as
+  # contextlib.contextmanager. Add to this list to register other decorators that
+  # produce valid context managers.
+contextmanager-decorators=["contextlib.contextmanager"]
+
+  # List of members which are set dynamically and missed by pylint inference
+  # system, and so shouldn't trigger E1101 when accessed. Python regular
+  # expressions are accepted.
+generated-members=[]
+
+  # Tells whether missing members accessed in mixin class should be ignored. A
+  # mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=true
+
+  # Tells whether to warn about missing members when the owner of the attribute
+  # is inferred to be None.
+ignore-none=true
+
+  # This flag controls whether pylint should warn about no-member and similar
+  # checks whenever an opaque object is returned when inferring. The inference
+  # can return multiple potential results while evaluating a Python object, but
+  # some branches might not be evaluated, which results in partial inference. In
+  # that case, it might be useful to still emit no-member and other checks for
+  # the rest of the inferred objects.
+ignore-on-opaque-inference=true
+
+  # List of class names for which member attributes should not be checked (useful
+  # for classes with dynamically set attributes). This supports the use of
+  # qualified names.
+ignored-classes=["optparse.Values","thread._local","_thread._local"]
+
+  # List of module names for which member attributes should not be checked
+  # (useful for modules/projects where namespaces are manipulated during runtime
+  # and thus existing member attributes cannot be deduced by static analysis). It
+  # supports qualified module names, as well as Unix pattern matching.
+ignored-modules=[]
+
+  # Show a hint with possible names when a member name was not found. The aspect
+  # of finding the hint is based on edit distance.
+missing-member-hint=true
+
+  # The minimum edit distance a name should have in order to be considered a
+  # similar match for a missing member name.
+missing-member-hint-distance=1
+
+  # The total number of similar names that should be taken in consideration when
+  # showing a hint for a missing member.
+missing-member-max-choices=1
+
+  # List of decorators that change the signature of a decorated function.
+signature-mutators=[]
+
+
+[tool.pylint.'VARIABLES']
+  # List of additional names supposed to be defined in builtins. Remember that
+  # you should avoid defining new builtins when possible.
+additional-builtins=[]
+
+  # Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=true
+
+  # List of strings which can identify a callback function by name. A callback
+  # name must start or end with one of those strings.
+callbacks=["cb_","_cb"]
+
+  # A regular expression matching the name of dummy variables (i.e. expected to
+  # not be used).
+#dummy-variables-rgx="+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_"
+
+  # Argument names that match this expression will be ignored. Default to name
+  # with leading underscore.
+ignored-argument-names="_.*|^ignored_|^unused_"
+
+  # Tells whether we should check for unused import in __init__ files.
+init-import=false
+
+  # List of qualified module names which can have objects that can redefine
+  # builtins.
+redefining-builtins-modules=["six.moves","past.builtins","future.builtins","builtins","io"]
+
+
+[tool.pylint.'LOGGING']
+  # The type of string formatting that logging methods do. `old` means using %
+  # formatting, `new` is for `{}` formatting.
+logging-format-style="old"
+
+  # Logging modules to check that the string format arguments are in logging
+  # function parameter format.
+logging-modules="logging"
+
+
+[tool.pylint.'MISCELLANEOUS']
+  # List of note tags to take in consideration, separated by a comma.
+notes=["FIXME","XXX","TODO"]
+
+  # Regular expression of note tags to take in consideration.
+  # notes-rgx=
+
+
+[tool.pylint.'SIMILARITIES']
+  # Ignore comments when computing similarities.
+ignore-comments=true
+
+  # Ignore docstrings when computing similarities.
+ignore-docstrings=true
+
+  # Ignore imports when computing similarities.
+ignore-imports=false
+
+  # Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[tool.pylint.'SPELLING']
+  # Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
+
+  # Spelling dictionary name. Available dictionaries: none. To make it work,
+  # install the python-enchant package.
+spelling-dict=[]
+
+  # List of comma separated words that should not be checked.
+spelling-ignore-words=[]
+
+  # A path to a file that contains the private dictionary; one word per line.
+spelling-private-dict-file=[]
+
+  # Tells whether to store unknown words to the private dictionary (see the
+  # --spelling-private-dict-file option) instead of raising a message.
+spelling-store-unknown-words=false
+
+
+[tool.pylint.'STRING']
+  # This flag controls whether inconsistent-quotes generates a warning when the
+  # character used as a quote delimiter is used inconsistently within a module.
+check-quote-consistency=false
+
+  # This flag controls whether the implicit-str-concat should generate a warning
+  # on implicit string concatenation in sequences defined over several lines.
+check-str-concat-over-line-jumps=false
+
+
+[tool.pylint.'FORMAT']
+  # Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=[]
+
+  # Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines='^\s*(# )?<?https?://\S+>?$'
+
+  # Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+  # String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1
+  # tab).
+indent-string='    '
+
+  # Maximum number of characters on a single line.
+max-line-length=100
+
+  # Maximum number of lines in a module.
+max-module-lines=1000
+
+  # List of optional constructs for which whitespace checking is disabled. `dict-
+  # separator` is used to allow tabulation in dicts, etc.: {1  : 1,\n222: 2}.
+  # `trailing-comma` allows a space between comma and closing bracket: (a, ).
+  # `empty-line` allows space-only lines.
+no-space-check=["trailing-comma","dict-separator"]
+
+  # Allow the body of a class to be on the same line as the declaration if body
+  # contains single statement.
+single-line-class-stmt=false
+
+  # Allow the body of an if to be on the same line as the test if there is no
+  # else.
+single-line-if-stmt=false
+
+
+[tool.pylint.'BASIC']
+  # Naming style matching correct argument names.
+argument-naming-style="snake_case"
+
+  # Regular expression matching correct argument names. Overrides argument-
+  # naming-style.
+#argument-rgx=
+
+  # Naming style matching correct attribute names.
+attr-naming-style="snake_case"
+
+  # Regular expression matching correct attribute names. Overrides attr-naming-
+  # style.
+#attr-rgx=
+
+  # Bad variable names which should always be refused, separated by a comma.
+bad-names=["foo","bar","baz","toto","tutu","tata"]
+
+  # Bad variable names regexes, separated by a comma. If names match any regex,
+  # they will always be refused
+bad-names-rgxs=[]
+
+  # Naming style matching correct class attribute names.
+class-attribute-naming-style="any"
+
+  # Regular expression matching correct class attribute names. Overrides class-
+  # attribute-naming-style.
+#class-attribute-rgx=
+
+  # Naming style matching correct class names.
+class-naming-style="PascalCase"
+
+  # Regular expression matching correct class names. Overrides class-naming-
+  # style.
+#class-rgx=
+
+  # Naming style matching correct constant names.
+const-naming-style="UPPER_CASE"
+
+  # Regular expression matching correct constant names. Overrides const-naming-
+  # style.
+#const-rgx=
+
+  # Minimum line length for functions/classes that require docstrings, shorter
+  # ones are exempt.
+docstring-min-length=-1
+
+  # Naming style matching correct function names.
+function-naming-style="snake_case"
+
+  # Regular expression matching correct function names. Overrides function-
+  # naming-style.
+#function-rgx=
+
+  # Good variable names which should always be accepted, separated by a comma.
+#good-names= ["i","j","k","ex","Run","_"]
+
+  # Good variable names regexes, separated by a comma. If names match any regex,
+  # they will always be accepted
+good-names-rgxs=[]
+
+  # Include a hint for the correct naming format with invalid-name.
+include-naming-hint=true
+
+  # Naming style matching correct inline iteration names.
+inlinevar-naming-style="any"
+
+  # Regular expression matching correct inline iteration names. Overrides
+  # inlinevar-naming-style.
+#inlinevar-rgx=
+
+  # Naming style matching correct method names.
+method-naming-style="snake_case"
+
+  # Regular expression matching correct method names. Overrides method-naming-
+  # style.
+#method-rgx=
+
+  # Naming style matching correct module names.
+module-naming-style="snake_case"
+
+  # Regular expression matching correct module names. Overrides module-naming-
+  # style.
+#module-rgx=
+
+  # Colon-delimited sets of names that determine each other's naming style when
+  # the name regexes allow several styles.
+name-group=[]
+
+  # Regular expression which should only match function or class names that do
+  # not require a docstring.
+no-docstring-rgx="^_"
+
+  # List of decorators that produce properties, such as abc.abstractproperty. Add
+  # to this list to register other decorators that produce valid properties.
+  # These decorators are taken in consideration only for invalid-name.
+property-classes="abc.abstractproperty"
+
+  # Naming style matching correct variable names.
+variable-naming-style="snake_case"
+
+  # Regular expression matching correct variable names. Overrides variable-
+  # naming-style.
+  # variable-rgx=
+
+[tool.pylint.'IMPORTS']
+  # List of modules that can be imported at any level, not just the top level
+  # one.
+allow-any-import-level=[]
+
+  # Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=false
+
+  # Analyse import fallback blocks. This can be used to support both Python 2 and
+  # 3 compatible code, which means that the block might have code that exists
+  # only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=false
+
+  # Deprecated modules which should not be used, separated by a comma.
+deprecated-modules="optparse,tkinter.tix"
+
+  # Create a graph of external dependencies in the given file (report RP0402 must
+  # not be disabled).
+ext-import-graph=[]
+
+  # Create a graph of every (i.e. internal and external) dependencies in the
+  # given file (report RP0402 must not be disabled).
+import-graph=[]
+
+  # Create a graph of internal dependencies in the given file (report RP0402 must
+  # not be disabled).
+int-import-graph=[]
+
+  # Force import order to recognize a module as part of the standard
+  # compatibility libraries.
+known-standard-library=[]
+
+  # Force import order to recognize a module as part of a third party library.
+known-third-party="enchant"
+
+  # Couples of modules and preferred modules, separated by a comma.
+preferred-modules=[]
+
+
+[tool.pylint.'CLASSES']
+  # List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=["__init__","__new__","setUp","__post_init__"]
+
+  # List of member names, which should be excluded from the protected access
+  # warning.
+exclude-protected=["_asdict","_fields","_replace","_source","_make"]
+
+  # List of valid names for the first argument in a class method.
+valid-classmethod-first-arg="cls"
+
+  # List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg="cls"
+
+
+[tool.pylint.'DESIGN']
+  # Maximum number of arguments for function / method.
+max-args=5
+
+  # Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+  # Maximum number of boolean expressions in an if statement (see R0916).
+max-bool-expr=5
+
+  # Maximum number of branch for function / method body.
+max-branches=12
+
+  # Maximum number of locals for function / method body.
+max-locals=15
+
+  # Maximum number of parents for a class (see R0901).
+max-parents=7
+
+  # Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+  # Maximum number of return / yield for function / method body.
+max-returns=6
+
+  # Maximum number of statements in function / method body.
+max-statements=50
+
+  # Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+
+[tool.pylint.'EXCEPTIONS']
+  # Exceptions that will emit a warning when being caught. Defaults to
+  # "BaseException, Exception".
+overgeneral-exceptions=["BaseException","Exception"]
+
+
+# -----------------------------------------------------------------------------
+# Flake8/flake9
+# https://flake8.pycqa.org/en/latest/user/configuration.html
+[tool.flake8]
+  # Optionally inherit from remote config (or local if you want)
+#base=https://url.git.com/pyproject.toml
+
+  # Specify any flake8 options.
+  # Print the total number of errors.
+  # Default False
+count = true
+
+  # Provide a comma-separated list of glob patterns to exclude from checks.
+exclude = ".git,__pycache__,.eggs,.env,.venv,.direnv,.tox,.sha1,build,dist,docs,site"
+
+  # Provide a comma-separate list of glob patterns to include for checks.
+filename = "*.py"
+
+  # Select the formatter used to display errors to the user.
+  # This defaults to: default
+  #  - default
+  #  - pylint
+  #  - grouped
+  #  - colored
+  # The default formatter has a format string of:
+  # '%(path)s:%(row)d:%(col)d: %(code)s %(text)s'
+#format="colored
+
+  # Toggle whether pycodestyle should enforce matching the indentation of the
+  # opening bracket’s line. When you specify this, it will prefer that you hang
+  # the closing bracket rather than match the indentation.
+hang-closing = false
+
+  # Specify a list of codes to ignore. The list is expected to be comma-separated,
+  # and does not need to specify an error code exactly. Since Flake8 3.0, this can
+  # be combined with --select. See --select for more information.
+  # For example, if you wish to only ignore W234, then you can specify that. But
+  # if you want to ignore all codes that start with W23 you need only specify W23
+  # to ignore them. This also works for W2 and W (for example).
+  # This defaults to: E121,E123,E126,E226,E24,E704
+ignore = "E121,E123,E126,E226,E24,E704,W503,E501"
+  # W503 : line break before binary operator
+  # E501 : line to long (already handled by black)
+
+  # Set the maximum length that any line (with some exceptions) may be.
+  # Exceptions include lines that are either strings or comments which are
+  # entirely URLs. For example:
+  # ```
+  # # https://some-super-long-domain-name.com/with/some/very/long/path
+  # url=(
+  #   'http://...'
+  # )
+  # This defaults to: 79
+max-line-length = 80
+
+  # Report all errors, even if it is on the same line as a # NOQA comment. # NOQA
+  # can be used to silence messages on specific lines. Sometimes, users will want
+  # to see what errors are being silenced without editing the file. This option
+  # allows you to see all the warnings, errors, etc. reported.
+  # This default to : False
+disable-noqa = true
+
+  # Print the source code generating the error/warning in question.
+show-source = true
+
+  # Count the number of occurrences of each error/warning code and print a report.
+statistics = true
+
+  # Enable off-by-default extensions.
+  # Plugins to Flake8 have the option of registering themselves as off-by-default.
+  # These plugins effectively add themselves to the default ignore list.
+#enable-extensions =
+#  H111,
+#  G123
+
+  # Specify the number of subprocesses that Flake8 will use to run checks in parallel.
+  # Note
+  # This option is ignored on Windows because multiprocessing does not support
+  # Windows across all supported versions of Python.
+  # This defaults to: auto
+  # The default behaviour will use the number of CPUs on your machine as reported
+  # by multiprocessing.cpu_count().
+jobs = "auto"
+
+  # Also print output to stdout if output-file has been configured.
+tee = true
+
+  # Provide a custom list of builtin functions, objects, names, etc.
+  # This allows you to let pyflakes know about builtins that it may not
+  # immediately recognize so it does not report warnings for using an undefined
+  # name.
+  # This is registered by the default PyFlakes plugin.
+#builtins =
+#  _,
+#  _LE,
+#  _LW
+
+  # Enable PyFlakes syntax checking of doctests in docstrings.
+  # This is registered by the default PyFlakes plugin.
+#doctests = True
+
+  # Specify which files are checked by PyFlakes for doctest syntax.
+  # This is registered by the default PyFlakes plugin.
+#include-in-doctest =
+#  dir/subdir/file.py,
+#  dir/other/file.py
+
+  # Specify which files are not to be checked by PyFlakes for doctest syntax.
+  # This is registered by the default PyFlakes plugin.
+#exclude-in-doctest =
+  #  dir/subdir/file.py,
+  #  dir/other/file.py
+
+### END MKDOCS TEMPLATE ###
+
+
+# *****************************************************************************
+# VIM MODELINE
+# vim: ft=toml:fdm=indent:fdi=
+# *****************************************************************************
diff --git a/user_config/requirements.dev.in b/user_config/requirements.dev.in
new file mode 100644
index 0000000000000000000000000000000000000000..ea4c9de12c1d1842b583cadb32c071bf99507bed
--- /dev/null
+++ b/user_config/requirements.dev.in
@@ -0,0 +1,42 @@
+# DEVELOPER REQUIREMENTS
+# ============================================================
+# DESCRIPTION:
+#   Mainly testing suite tools to ensure and/or enfore code syntax
+
+# Testing tools
+# ------------------------------------------------------------
+# Tox is a generic virtualenv management and test command line tool
+# https://pypi.org/project/tox/
+tox
+
+# The uncompromising code formatter.
+# https://pypi.org/project/black/
+black
+
+# A Python utility / library to sort Python imports.
+# https://pypi.org/project/isort/
+isort
+
+# pytest: simple powerful testing with Python
+# https://pypi.org/project/pytest/
+pytest
+
+# Flake8 with pyproject support
+# https://pypi.org/project/flake9/
+flake9
+
+# python code static checker
+# https://pypi.org/project/pylint/
+pylint
+
+# Python docstring style checker
+# https://pypi.org/project/pydocstyle/
+pydocstyle
+
+# Python wrapper around invoking shellcheck (https://www.shellcheck.net/)
+# https://pypi.org/project/shellcheck-py/
+shellcheck-py
+
+# A linter for YAML files.
+# https://pypi.org/project/yamllint/
+yamllint
\ No newline at end of file
diff --git a/user_config/requirements.dev.txt b/user_config/requirements.dev.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fee5187d6f236a74f80fec913dbf509be604b00b
--- /dev/null
+++ b/user_config/requirements.dev.txt
@@ -0,0 +1,94 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+#    pip-compile requirements.dev.in
+#
+appdirs==1.4.4
+    # via
+    #   black
+    #   virtualenv
+astroid==2.5.6
+    # via pylint
+attrs==21.2.0
+    # via pytest
+black==21.5b0
+    # via -r requirements.dev.in
+click==7.1.2
+    # via black
+distlib==0.3.1
+    # via virtualenv
+filelock==3.0.12
+    # via
+    #   tox
+    #   virtualenv
+flake9==3.8.3.post2
+    # via -r requirements.dev.in
+iniconfig==1.1.1
+    # via pytest
+isort==5.8.0
+    # via
+    #   -r requirements.dev.in
+    #   pylint
+lazy-object-proxy==1.6.0
+    # via astroid
+mccabe==0.6.1
+    # via
+    #   flake9
+    #   pylint
+mypy-extensions==0.4.3
+    # via black
+packaging==20.9
+    # via
+    #   pytest
+    #   tox
+pathspec==0.8.1
+    # via
+    #   black
+    #   yamllint
+pluggy==0.13.1
+    # via
+    #   pytest
+    #   tox
+py==1.10.0
+    # via
+    #   pytest
+    #   tox
+pycodestyle==2.6.0
+    # via flake9
+pydocstyle==6.0.0
+    # via -r requirements.dev.in
+pyflakes==2.2.0
+    # via flake9
+pylint==2.8.2
+    # via -r requirements.dev.in
+pyparsing==2.4.7
+    # via packaging
+pytest==6.2.4
+    # via -r requirements.dev.in
+pyyaml==5.4.1
+    # via yamllint
+regex==2021.4.4
+    # via black
+shellcheck-py==0.7.2.1
+    # via -r requirements.dev.in
+six==1.16.0
+    # via
+    #   tox
+    #   virtualenv
+snowballstemmer==2.1.0
+    # via pydocstyle
+toml==0.10.2
+    # via
+    #   black
+    #   pylint
+    #   pytest
+    #   tox
+tox==3.23.1
+    # via -r requirements.dev.in
+virtualenv==20.4.6
+    # via tox
+wrapt==1.12.1
+    # via astroid
+yamllint==1.26.1
+    # via -r requirements.dev.in
diff --git a/user_config/requirements.docs.in b/user_config/requirements.docs.in
new file mode 100644
index 0000000000000000000000000000000000000000..a7a8e1a8541730d508766924f43f2e57e052cba7
--- /dev/null
+++ b/user_config/requirements.docs.in
@@ -0,0 +1,59 @@
+# DOCUMENTATION REQUIREMENTS
+# ============================================================
+# DESCRIPTION:
+#   Requirements to be able to render documentation locally
+
+# Documentation rendering dependencies
+# ------------------------------------------------------------
+# Project documentation with Markdown.
+# https://pypi.org/project/mkdocs/
+mkdocs
+
+# A Material Design theme for MkDocs
+# https://pypi.org/project/mkdocs-material/
+mkdocs-material>=7.1
+
+# Plugin for adding monorepository support in Mkdocs.
+# https://pypi.org/project/mkdocs-monorepo-plugin/
+mkdocs-monorepo-plugin
+
+# Mkdocs plugin that enables displaying the localized date of the last git
+# modification of a markdown file.
+# https://pypi.org/project/mkdocs-git-revision-date-localized-plugin/
+mkdocs-git-revision-date-localized-plugin
+
+# MkDocs plugin to allow clickable sections that lead to an index page
+# https://pypi.org/project/mkdocs-section-index/
+mkdocs-section-index
+
+# Automatic documentation from sources, for MkDocs.
+# https://pypi.org/project/mkdocstrings/
+mkdocstrings
+
+# This is an extension to Python-Markdown which provides an "include" function.
+# https://pypi.org/project/markdown-include/
+markdown-include
+
+# Unleash the power of MkDocs with macros and variables
+# https://pypi.org/project/mkdocs-macros-plugin/
+mkdocs-macros-plugin
+
+# A mkdocs plugin that lets you exclude files or trees.
+# https://github.com/apenwarr/mkdocs-exclude
+mkdocs-exclude
+
+# Python lib/cli for JSON/YAML schema validation
+# https://pypi.org/project/pykwalify/
+pykwalify
+
+# Markdown extension to wrap images in a lightbox.
+# https://github.com/g-provost/lightgallery-markdown
+git+https://github.com/g-provost/lightgallery-markdown
+
+# A Mermaid graphs plugin for mkdocs
+# https://github.com/fralau/mkdocs-mermaid2-plugin#declaring-the-superfences-extension
+mkdocs-mermaid2-plugin
+
+# A MkDocs plugin for dynamic page redirects to prevent broken links.
+# https://pypi.org/project/mkdocs-redirects/
+mkdocs-redirects
diff --git a/user_config/requirements.docs.txt b/user_config/requirements.docs.txt
new file mode 100644
index 0000000000000000000000000000000000000000..92670c6c350c5e835feea21fef36257917657643
--- /dev/null
+++ b/user_config/requirements.docs.txt
@@ -0,0 +1,160 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+#    pip-compile requirements.docs.in
+#
+astunparse==1.6.3
+    # via pytkdocs
+babel==2.9.1
+    # via mkdocs-git-revision-date-localized-plugin
+beautifulsoup4==4.9.3
+    # via mkdocs-mermaid2-plugin
+certifi==2020.12.5
+    # via requests
+chardet==4.0.0
+    # via requests
+click==7.1.2
+    # via
+    #   mkdocs
+    #   nltk
+docopt==0.6.2
+    # via pykwalify
+editorconfig==0.12.3
+    # via jsbeautifier
+future==0.18.2
+    # via lunr
+gitdb==4.0.7
+    # via gitpython
+gitpython==3.1.14
+    # via mkdocs-git-revision-date-localized-plugin
+idna==2.10
+    # via requests
+jinja2==2.11.3
+    # via
+    #   mkdocs
+    #   mkdocs-macros-plugin
+    #   mkdocstrings
+joblib==1.0.1
+    # via nltk
+jsbeautifier==1.13.13
+    # via mkdocs-mermaid2-plugin
+git+https://github.com/g-provost/lightgallery-markdown
+    # via -r requirements.docs.in
+livereload==2.6.3
+    # via mkdocs
+lunr[languages]==0.5.8
+    # via mkdocs
+markdown-include==0.6.0
+    # via -r requirements.docs.in
+markdown==3.3.4
+    # via
+    #   lightgallery
+    #   markdown-include
+    #   mkdocs
+    #   mkdocs-autorefs
+    #   mkdocs-material
+    #   mkdocstrings
+    #   pymdown-extensions
+markupsafe==1.1.1
+    # via
+    #   jinja2
+    #   mkdocstrings
+mkdocs-autorefs==0.1.1
+    # via mkdocstrings
+mkdocs-exclude==1.0.2
+    # via -r requirements.docs.in
+mkdocs-git-revision-date-localized-plugin==0.9.2
+    # via -r requirements.docs.in
+mkdocs-macros-plugin==0.5.5
+    # via -r requirements.docs.in
+mkdocs-material-extensions==1.0.1
+    # via mkdocs-material
+mkdocs-material==7.1.4
+    # via
+    #   -r requirements.docs.in
+    #   mkdocs-macros-plugin
+    #   mkdocs-material-extensions
+    #   mkdocs-mermaid2-plugin
+mkdocs-mermaid2-plugin==0.5.1
+    # via -r requirements.docs.in
+mkdocs-monorepo-plugin==0.4.14
+    # via -r requirements.docs.in
+mkdocs-redirects==1.0.3
+    # via -r requirements.docs.in
+mkdocs-section-index==0.3.0
+    # via -r requirements.docs.in
+mkdocs==1.1.2
+    # via
+    #   -r requirements.docs.in
+    #   mkdocs-autorefs
+    #   mkdocs-exclude
+    #   mkdocs-git-revision-date-localized-plugin
+    #   mkdocs-macros-plugin
+    #   mkdocs-material
+    #   mkdocs-mermaid2-plugin
+    #   mkdocs-monorepo-plugin
+    #   mkdocs-redirects
+    #   mkdocs-section-index
+    #   mkdocstrings
+mkdocstrings==0.15.0
+    # via -r requirements.docs.in
+nltk==3.6.2
+    # via lunr
+pygments==2.9.0
+    # via mkdocs-material
+pykwalify==1.8.0
+    # via -r requirements.docs.in
+pymdown-extensions==8.1.1
+    # via
+    #   mkdocs-material
+    #   mkdocs-mermaid2-plugin
+    #   mkdocstrings
+python-dateutil==2.8.1
+    # via
+    #   mkdocs-macros-plugin
+    #   pykwalify
+pytkdocs==0.11.1
+    # via mkdocstrings
+pytz==2021.1
+    # via babel
+pyyaml==5.4.1
+    # via
+    #   mkdocs
+    #   mkdocs-macros-plugin
+    #   mkdocs-mermaid2-plugin
+regex==2021.4.4
+    # via nltk
+requests==2.25.1
+    # via mkdocs-mermaid2-plugin
+ruamel.yaml.clib==0.2.2
+    # via ruamel.yaml
+ruamel.yaml==0.17.4
+    # via pykwalify
+six==1.16.0
+    # via
+    #   astunparse
+    #   jsbeautifier
+    #   livereload
+    #   lunr
+    #   mkdocs-redirects
+    #   python-dateutil
+smmap==4.0.0
+    # via gitdb
+soupsieve==2.2.1
+    # via beautifulsoup4
+termcolor==1.1.0
+    # via mkdocs-macros-plugin
+tornado==6.1
+    # via
+    #   livereload
+    #   mkdocs
+tqdm==4.60.0
+    # via nltk
+urllib3==1.26.4
+    # via requests
+wheel==0.36.2
+    # via astunparse
+
+# The following packages are considered to be unsafe in a requirements file:
+# setuptools