diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 0b11c26..0fa7195 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -17,7 +17,9 @@
"ms-toolsai.jupyter",
"pkief.material-icon-theme",
"redhat.vscode-yaml",
- "tamasfe.even-better-toml"
+ "tamasfe.even-better-toml",
+ "ms-vscode.vscode-websearchforcopilot",
+ "ms-vscode.vscode-commander"
],
"settings": {
"editor.linkedEditing": true,
@@ -57,6 +59,19 @@
"python.testing.cwd": "${containerWorkspaceFolder}/tests",
"python.testing.pytestPath": "${containerWorkspaceFolder}/.venv/bin/pytest",
"python.testing.autoTestDiscoverOnSaveEnabled": true,
+ // MkDocs schema for the YAML extension
+ "yaml.schemas": {
+ "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml"
+ },
+ "yaml.customTags": [
+ "!ENV scalar",
+ "!ENV sequence",
+ "!relative scalar",
+ "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg",
+ "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji",
+ "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format",
+ "tag:yaml.org,2002:python/object/apply:pymdownx.slugs.slugify mapping"
+ ],
// Settings per file type
"[toml]": {
"editor.defaultFormatter": "tamasfe.even-better-toml",
@@ -86,5 +101,8 @@
"ghcr.io/thecodecrate/devcontainer-features/uv:1": {}
},
"remoteUser": "vscode",
- "postCreateCommand": "zsh -i .devcontainer/scripts/post-create.sh"
+ "postCreateCommand": "zsh -i .devcontainer/scripts/post-create.sh",
+ "containerEnv": {
+ "PYTHONPATH": "${containerWorkspaceFolder}/src"
+ }
}
diff --git a/.github/workflows/format-ruff.yaml b/.github/workflows/format-ruff.yaml
index a9c1cd7..5dce6af 100644
--- a/.github/workflows/format-ruff.yaml
+++ b/.github/workflows/format-ruff.yaml
@@ -7,6 +7,8 @@ on:
branches:
- main
+permissions: {}
+
jobs:
format-ruff:
name: Ruff Check
diff --git a/.github/workflows/lint-ruff.yaml b/.github/workflows/lint-ruff.yaml
index 6794001..8020104 100644
--- a/.github/workflows/lint-ruff.yaml
+++ b/.github/workflows/lint-ruff.yaml
@@ -7,6 +7,8 @@ on:
branches:
- main
+permissions: {}
+
jobs:
lint-ruff:
name: Ruff Check
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index c1f605f..bbde8a7 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -6,6 +6,8 @@ on:
tags:
- '*'
+permissions: {}
+
jobs:
deploy:
runs-on: ubuntu-latest
diff --git a/.github/workflows/security-zizmor.yaml b/.github/workflows/security-zizmor.yaml
index 1125bfc..2c35426 100644
--- a/.github/workflows/security-zizmor.yaml
+++ b/.github/workflows/security-zizmor.yaml
@@ -7,6 +7,8 @@ on:
branches:
- main
+permissions: {}
+
jobs:
zizmor:
name: Zizmor CI files check
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index cda4d5d..71c1d0a 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -7,6 +7,8 @@ on:
branches:
- main
+permissions: {}
+
jobs:
test:
name: Python ${{ matrix.python-version }} - ${{ matrix.os }}
diff --git a/docs/api/core.md b/docs/api/core.md
new file mode 100644
index 0000000..44b38e8
--- /dev/null
+++ b/docs/api/core.md
@@ -0,0 +1,15 @@
+# API Reference
+
+::: thecodecrate_pipeline.core
+ options:
+ show_if_no_docstring: true
+ preload_modules:
+ - "_api"
+ - "thecodecrate_pipeline"
+ members:
+ - T_in
+ - T_out
+ - Pipeline
+ - PipelineFactory
+ - Stage
+ - Processor
diff --git a/docs/api/processors.md b/docs/api/processors.md
new file mode 100644
index 0000000..724338f
--- /dev/null
+++ b/docs/api/processors.md
@@ -0,0 +1,13 @@
+# API Reference
+
+::: thecodecrate_pipeline.processors
+ options:
+ show_if_no_docstring: true
+ preload_modules:
+ - "_api"
+ - "thecodecrate_pipeline"
+ members:
+ - ChainedProcessor
+ - InterruptibleProcessor
+ - ChainedProcessorInterface
+ - InterruptibleProcessorInterface
diff --git a/docs/assets/css/extra-pymdownx.css b/docs/assets/css/extra-pymdownx.css
new file mode 100644
index 0000000..800872c
--- /dev/null
+++ b/docs/assets/css/extra-pymdownx.css
@@ -0,0 +1,2 @@
+@charset "UTF-8";:root>*{--md-code-link-bg-color:hsla(0, 0%, 96%, 1);--md-code-link-accent-bg-color:var(--md-code-link-bg-color);--md-default-bg-color--trans:rgb(100%, 100%, 100%, 0);--md-code-title-bg-color:var(--md-code-bg-color);--md-code-inline-bg-color:var(--md-code-bg-color);--md-code-special-bg-color:hsl(0, 0%, 91%);--md-code-alternate-bg-color:var(--md-code-bg-color);--md-code-hl-punctuation-color:var(--md-code-fg-color);--md-code-hl-namespace-color:var(--md-code-fg-color);--md-code-hl-entity-color:var(--md-code-hl-keyword-color);--md-code-hl-tag-color:var(--md-code-hl-keyword-color);--md-code-hl-builtin-color:var(--md-code-hl-constant-color);--md-code-hl-class-color:var(--md-code-hl-function-color);--md-typeset-a-color:#00bcd4;--md-progress-stripe:var(--md-default-bg-color--lighter);--md-progress-100:#00e676;--md-progress-80:#00e676;--md-progress-60:#fbc02d;--md-progress-40:#ff9100;--md-progress-20:#ff5252;--md-progress-0:#ff1744;--md-typeset-kbd-color:rgb(234.6, 234.6, 234.6);--md-typeset-kbd-border-color:rgb(183.6, 183.6, 183.6);--md-typeset-kbd-accent-color:hsla(0, 100%, 100%, 1)}:root>[data-md-color-scheme=slate]{--md-code-link-bg-color:hsla(232, 15%, 15%, 1);--md-code-link-accent-bg-color:var(--md-code-link-bg-color);--md-code-special-bg-color:hsl(232, 15%, 20%);--md-default-bg-color--trans:hsla(232,15%,15%, 0);--md-typeset-kbd-color:var(--md-default-fg-color--lightest);--md-typeset-kbd-border-color:rgb(26.45, 27.6, 35.65);--md-typeset-kbd-accent-color:var(--md-default-fg-color--lighter)}:root>[data-md-color-scheme=dracula]{--md-default-fg-color:hsla(60, 30%, 96%, 0.87);--md-default-fg-color--light:hsla(60, 30%, 96%, 0.54);--md-default-fg-color--lighter:hsla(60, 30%, 96%, 0.16);--md-default-fg-color--lightest:hsla(60, 30%, 96%, 0.07);--md-default-autocomplete-fg-color:hsla(60, 30%, 96%, 0.4);--md-shadow-z2:0 0.2rem 0.5rem hsla(0, 0%, 0%, 0.3),0 0 0.05rem hsla(0, 0%, 0%, 0.2);--md-default-bg-color:var(--md-default-bg-color--darkest);--md-default-bg-color--light:hsla(231, 15%, 23%, 0.7);--md-default-bg-color--lighter:hsla(231, 15%, 23%, 0.3);--md-default-bg-color--lightest:hsla(231, 15%, 23%, 0.12);--md-default-bg-color--trans:hsla(231, 15%, 23%, 0);--md-default-bg-color--dark:hsl(231, 15%, 20%);--md-default-bg-color--darker:hsl(231, 15%, 17%);--md-default-bg-color--darkest:hsl(231, 15%, 14%);--md-default-bg-color--ultra-dark:hsl(231, 15%, 8%);--md-text-color:var(--md-default-fg-color);--md-typeset-color:var(--md-default-fg-color);--md-admonition-fg-color:var(--md-default-fg-color);--md-code-fg-color:hsl(60, 30%, 96%);--md-code-bg-color:hsl(231, 15%, 18%);--md-code-title-bg-color:var(--md-default-bg-color--ultra-dark);--md-code-inline-bg-color:hsl(231, 15%, 23%);--md-code-hl-operator-color:hsl(326, 100%, 74%);--md-code-hl-punctuation-color:hsl(60, 30%, 96%);--md-code-hl-string-color:hsl(65, 92%, 76%);--md-code-hl-special-color:hsl(265, 89%, 78%);--md-code-hl-number-color:hsl(265, 89%, 78%);--md-code-hl-keyword-color:hsl(326, 100%, 74%);--md-code-hl-name-color:hsl(60, 30%, 96%);--md-code-hl-constant-color:hsl(265, 89%, 78%);--md-code-hl-function-color:hsl(135, 94%, 65%);--md-code-hl-comment-color:hsl(225, 27%, 51%);--md-code-hl-variable-color:hsl(31, 100%, 71%);--md-code-hl-generic-color:hsl(225, 27%, 51%);--md-code-hl-color:hsl(231, 25%, 25%);--md-code-hl-entity-color:hsl(135, 94%, 65%);--md-code-hl-tag-color:hsl(326, 100%, 74%);--md-code-hl-namespace-color:hsl(60, 30%, 96%);--md-code-hl-builtin-color:hsl(191, 97%, 77%);--md-code-hl-class-color:hsl(191, 97%, 77%);--md-code-special-bg-color:hsl(231, 15%, 13%);--md-code-alternate-bg-color:rgb(60.6135, 62.47245, 73.0065);--md-code-link-bg-color:rgb(54.081675, 69.7755225, 82.853325);--md-typeset-a-color:hsl(191, 97%, 77%);--md-typeset-mark-color:rgb(109.61175, 114.238725, 82.43385);--md-typeset-del-color:rgb(114.60975, 69.542325, 103.44925);--md-typeset-ins-color:rgb(54.009, 114.078075, 77.641125);--md-progress-stripe:var(--md-default-bg-color--lightest);--md-progress-100:hsl(135, 94%, 65%);--md-progress-80:hsl(135, 92%, 79%);--md-progress-60:hsl(65, 92%, 76%);--md-progress-40:hsl(31, 100%, 71%);--md-progress-20:hsl(326, 100%, 74%);--md-progress-0:hsl(0, 100%, 67%);--md-typeset-kbd-color:var(--md-default-fg-color--lightest);--md-typeset-kbd-border-color:var(--md-default-bg-color--ultra-dark);--md-typeset-kbd-accent-color:var(--md-default-fg-color--lighter)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=red],[data-md-color-scheme=dracula][data-md-color-primary=red]{--md-primary-code-bg-color:rgb(71.41275, 47.923425, 57.87225);--md-primary-fg-color:hsla(0deg, 100%, 67%, 1);--md-primary-fg-color--transparent:hsla(0deg, 100%, 67%, 0.1);--md-primary-fg-color--light:hsla(0deg, 100%, 72%, 1);--md-primary-fg-color--dark:hsla(0deg, 100%, 62%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=pink],[data-md-color-scheme=dracula][data-md-color-primary=pink]{--md-primary-code-bg-color:rgb(71.41275, 53.278425, 74.49825);--md-primary-fg-color:hsla(326deg, 100%, 74%, 1);--md-primary-fg-color--transparent:hsla(326deg, 100%, 74%, 0.1);--md-primary-fg-color--light:hsla(326deg, 100%, 79%, 1);--md-primary-fg-color--dark:hsla(326deg, 100%, 69%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=purple],[data-md-color-scheme=dracula][data-md-color-primary=purple]{--md-primary-code-bg-color:rgb(61.749525, 57.264075, 82.1916);--md-primary-fg-color:hsla(265deg, 89%, 78%, 1);--md-primary-fg-color--transparent:hsla(265deg, 89%, 78%, 0.1);--md-primary-fg-color--light:hsla(265deg, 89%, 83%, 1);--md-primary-fg-color--dark:hsla(265deg, 89%, 73%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-purple],[data-md-color-scheme=dracula][data-md-color-primary=deep-purple]{--md-primary-code-bg-color:rgb(61.749525, 57.264075, 82.1916);--md-primary-fg-color:hsla(265deg, 89%, 78%, 1);--md-primary-fg-color--transparent:hsla(265deg, 89%, 78%, 0.1);--md-primary-fg-color--light:hsla(265deg, 89%, 83%, 1);--md-primary-fg-color--dark:hsla(265deg, 89%, 73%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=blue],[data-md-color-scheme=dracula][data-md-color-primary=blue]{--md-primary-code-bg-color:rgb(47.609775, 51.8956875, 69.435225);--md-primary-fg-color:hsla(225deg, 27%, 51%, 1);--md-primary-fg-color--transparent:hsla(225deg, 27%, 51%, 0.1);--md-primary-fg-color--light:hsla(225deg, 27%, 56%, 1);--md-primary-fg-color--dark:hsla(225deg, 27%, 46%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=indigo],[data-md-color-scheme=dracula][data-md-color-primary=indigo]{--md-primary-code-bg-color:rgb(47.609775, 51.8956875, 69.435225);--md-primary-fg-color:hsla(225deg, 27%, 51%, 1);--md-primary-fg-color--transparent:hsla(225deg, 27%, 51%, 0.1);--md-primary-fg-color--light:hsla(225deg, 27%, 56%, 1);--md-primary-fg-color--dark:hsla(225deg, 27%, 46%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-blue],[data-md-color-scheme=dracula][data-md-color-primary=light-blue]{--md-primary-code-bg-color:rgb(47.609775, 51.8956875, 69.435225);--md-primary-fg-color:hsla(225deg, 27%, 51%, 1);--md-primary-fg-color--transparent:hsla(225deg, 27%, 51%, 0.1);--md-primary-fg-color--light:hsla(225deg, 27%, 56%, 1);--md-primary-fg-color--dark:hsla(225deg, 27%, 46%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=cyan],[data-md-color-scheme=dracula][data-md-color-primary=cyan]{--md-primary-code-bg-color:rgb(54.081675, 69.7755225, 82.853325);--md-primary-fg-color:hsla(191deg, 97%, 77%, 1);--md-primary-fg-color--transparent:hsla(191deg, 97%, 77%, 0.1);--md-primary-fg-color--light:hsla(191deg, 97%, 82%, 1);--md-primary-fg-color--dark:hsla(191deg, 97%, 72%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=teal],[data-md-color-scheme=dracula][data-md-color-primary=teal]{--md-primary-code-bg-color:rgb(54.081675, 69.7755225, 82.853325);--md-primary-fg-color:hsla(191deg, 97%, 77%, 1);--md-primary-fg-color--transparent:hsla(191deg, 97%, 77%, 0.1);--md-primary-fg-color--light:hsla(191deg, 97%, 82%, 1);--md-primary-fg-color--dark:hsla(191deg, 97%, 72%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=green],[data-md-color-scheme=dracula][data-md-color-primary=green]{--md-primary-code-bg-color:rgb(45.441, 72.365175, 63.437625);--md-primary-fg-color:hsla(135deg, 94%, 65%, 1);--md-primary-fg-color--transparent:hsla(135deg, 94%, 65%, 0.1);--md-primary-fg-color--light:hsla(135deg, 94%, 70%, 1);--md-primary-fg-color--dark:hsla(135deg, 94%, 60%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-green],[data-md-color-scheme=dracula][data-md-color-primary=light-green]{--md-primary-code-bg-color:rgb(45.441, 72.365175, 63.437625);--md-primary-fg-color:hsla(135deg, 94%, 65%, 1);--md-primary-fg-color--transparent:hsla(135deg, 94%, 65%, 0.1);--md-primary-fg-color--light:hsla(135deg, 94%, 70%, 1);--md-primary-fg-color--dark:hsla(135deg, 94%, 60%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=lime],[data-md-color-scheme=dracula][data-md-color-primary=lime]{--md-primary-code-bg-color:rgb(45.441, 72.365175, 63.437625);--md-primary-fg-color:hsla(135deg, 94%, 65%, 1);--md-primary-fg-color--transparent:hsla(135deg, 94%, 65%, 0.1);--md-primary-fg-color--light:hsla(135deg, 94%, 70%, 1);--md-primary-fg-color--dark:hsla(135deg, 94%, 60%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=yellow],[data-md-color-scheme=dracula][data-md-color-primary=yellow]{--md-primary-code-bg-color:rgb(69.27075, 72.434025, 65.49165);--md-primary-fg-color:hsla(65deg, 92%, 76%, 1);--md-primary-fg-color--transparent:hsla(65deg, 92%, 76%, 0.1);--md-primary-fg-color--light:hsla(65deg, 92%, 81%, 1);--md-primary-fg-color--dark:hsla(65deg, 92%, 71%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=amber],[data-md-color-scheme=dracula][data-md-color-primary=amber]{--md-primary-code-bg-color:rgb(69.27075, 72.434025, 65.49165);--md-primary-fg-color:hsla(65deg, 92%, 76%, 1);--md-primary-fg-color--transparent:hsla(65deg, 92%, 76%, 0.1);--md-primary-fg-color--light:hsla(65deg, 92%, 81%, 1);--md-primary-fg-color--dark:hsla(65deg, 92%, 71%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=orange],[data-md-color-scheme=dracula][data-md-color-primary=orange]{--md-primary-code-bg-color:rgb(71.41275, 62.445675, 60.93225);--md-primary-fg-color:hsla(31deg, 100%, 71%, 1);--md-primary-fg-color--transparent:hsla(31deg, 100%, 71%, 0.1);--md-primary-fg-color--light:hsla(31deg, 100%, 76%, 1);--md-primary-fg-color--dark:hsla(31deg, 100%, 66%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-orange],[data-md-color-scheme=dracula][data-md-color-primary=deep-orange]{--md-primary-code-bg-color:rgb(71.41275, 62.445675, 60.93225);--md-primary-fg-color:hsla(31deg, 100%, 71%, 1);--md-primary-fg-color--transparent:hsla(31deg, 100%, 71%, 0.1);--md-primary-fg-color--light:hsla(31deg, 100%, 76%, 1);--md-primary-fg-color--dark:hsla(31deg, 100%, 66%, 1);--md-primary-bg-color:var(--md-default-bg-color);--md-primary-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=red],[data-md-color-scheme=dracula][data-md-color-accent=red]{--md-code-link-accent-bg-color:rgb(71.41275, 44.098425, 54.04725);--md-accent-fg-color:hsla(0deg, 100%, 62%, 1);--md-accent-fg-color--transparent:hsla(0deg, 100%, 62%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=pink],[data-md-color-scheme=dracula][data-md-color-accent=pink]{--md-code-link-accent-bg-color:rgb(71.41275, 49.453425, 72.84075);--md-accent-fg-color:hsla(326deg, 100%, 69%, 1);--md-accent-fg-color--transparent:hsla(326deg, 100%, 69%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=purple],[data-md-color-scheme=dracula][data-md-color-accent=purple]{--md-code-link-accent-bg-color:rgb(59.5533375, 53.64945, 81.981225);--md-accent-fg-color:hsla(265deg, 89%, 73%, 1);--md-accent-fg-color--transparent:hsla(265deg, 89%, 73%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-purple],[data-md-color-scheme=dracula][data-md-color-accent=deep-purple]{--md-code-link-accent-bg-color:rgb(59.5533375, 53.64945, 81.981225);--md-accent-fg-color:hsla(265deg, 89%, 73%, 1);--md-accent-fg-color--transparent:hsla(265deg, 89%, 73%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=blue],[data-md-color-scheme=dracula][data-md-color-accent=blue]{--md-code-link-accent-bg-color:rgb(46.0071, 50.1381, 67.2129);--md-accent-fg-color:hsla(225deg, 27%, 46%, 1);--md-accent-fg-color--transparent:hsla(225deg, 27%, 46%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=indigo],[data-md-color-scheme=dracula][data-md-color-accent=indigo]{--md-code-link-accent-bg-color:rgb(46.0071, 50.1381, 67.2129);--md-accent-fg-color:hsla(225deg, 27%, 46%, 1);--md-accent-fg-color--transparent:hsla(225deg, 27%, 46%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-blue],[data-md-color-scheme=dracula][data-md-color-accent=light-blue]{--md-code-link-accent-bg-color:rgb(46.0071, 50.1381, 67.2129);--md-accent-fg-color:hsla(225deg, 27%, 46%, 1);--md-accent-fg-color--transparent:hsla(225deg, 27%, 46%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=cyan],[data-md-color-scheme=dracula][data-md-color-accent=cyan]{--md-code-link-accent-bg-color:rgb(50.31405, 69.037935, 82.79595);--md-accent-fg-color:hsla(191deg, 97%, 72%, 1);--md-accent-fg-color--transparent:hsla(191deg, 97%, 72%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=teal],[data-md-color-scheme=dracula][data-md-color-accent=teal]{--md-code-link-accent-bg-color:rgb(50.31405, 69.037935, 82.79595);--md-accent-fg-color:hsla(191deg, 97%, 72%, 1);--md-accent-fg-color--transparent:hsla(191deg, 97%, 72%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=green],[data-md-color-scheme=dracula][data-md-color-accent=green]{--md-code-link-accent-bg-color:rgb(41.73075, 72.250425, 60.62625);--md-accent-fg-color:hsla(135deg, 94%, 60%, 1);--md-accent-fg-color--transparent:hsla(135deg, 94%, 60%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-green],[data-md-color-scheme=dracula][data-md-color-accent=light-green]{--md-code-link-accent-bg-color:rgb(41.73075, 72.250425, 60.62625);--md-accent-fg-color:hsla(135deg, 94%, 60%, 1);--md-accent-fg-color--transparent:hsla(135deg, 94%, 60%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=lime],[data-md-color-scheme=dracula][data-md-color-accent=lime]{--md-code-link-accent-bg-color:rgb(41.73075, 72.250425, 60.62625);--md-accent-fg-color:hsla(135deg, 94%, 60%, 1);--md-accent-fg-color--transparent:hsla(135deg, 94%, 60%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=yellow],[data-md-color-scheme=dracula][data-md-color-accent=yellow]{--md-code-link-accent-bg-color:rgb(68.8245, 72.281025, 61.81965);--md-accent-fg-color:hsla(65deg, 92%, 71%, 1);--md-accent-fg-color--transparent:hsla(65deg, 92%, 71%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=amber],[data-md-color-scheme=dracula][data-md-color-accent=amber]{--md-code-link-accent-bg-color:rgb(68.8245, 72.281025, 61.81965);--md-accent-fg-color:hsla(65deg, 92%, 71%, 1);--md-accent-fg-color--transparent:hsla(65deg, 92%, 71%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=orange],[data-md-color-scheme=dracula][data-md-color-accent=orange]{--md-code-link-accent-bg-color:rgb(71.41275, 60.596925, 57.10725);--md-accent-fg-color:hsla(31deg, 100%, 66%, 1);--md-accent-fg-color--transparent:hsla(31deg, 100%, 66%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-orange],[data-md-color-scheme=dracula][data-md-color-accent=deep-orange]{--md-code-link-accent-bg-color:rgb(71.41275, 60.596925, 57.10725);--md-accent-fg-color:hsla(31deg, 100%, 66%, 1);--md-accent-fg-color--transparent:hsla(31deg, 100%, 66%, 0.1);--md-accent-bg-color:var(--md-default-bg-color);--md-accent-bg-color--light:var(--md-default-bg-color--light)}:root{--md-heart:#ff5252;--md-heart-big:#ff1744}:root :focus-visible{outline-style:solid}:root [data-md-color-scheme=dracula]{--md-heart:hsl(326, 100%, 74%);--md-heart-big:hsl(0, 100%, 67%)}.md-typeset h4{margin:2em 0 1em}.md-typeset a.source-link{position:relative;top:-.6rem;float:right;color:var(--md-default-fg-color--lighter);transition:color 125ms}.md-typeset a.source-link:hover{color:var(--md-accent-fg-color)}.md-typeset a.source-link .twemoji{height:1.2rem}.md-typeset a.source-link .twemoji svg{width:1.2rem;height:1.2rem}.md-typeset div.highlight.md-max-height pre>code{max-height:15rem}.twemoji.heart-throb svg,.twemoji.heart-throb-hover svg{position:relative;color:var(--md-heart);animation:pulse 1.5s ease infinite}@keyframes pulse{0%{transform:scale(1)}40%{color:var(--md-heart-big);transform:scale(1.3)}50%{transform:scale(1.2)}60%{color:var(--md-heart-big);transform:scale(1.3)}100%{transform:scale(1)}}footer.sponsorship{text-align:center}footer.sponsorship hr{display:inline-block;width:1.6rem;margin:0 .7rem;vertical-align:middle;border-bottom:2px solid var(--md-default-fg-color--lighter)}footer.sponsorship:hover hr{border-color:var(--md-accent-fg-color)}footer.sponsorship:not(:hover) .twemoji.heart-throb-hover svg{color:var(--md-default-fg-color--lighter)!important}body:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=dracula] .md-icon .light-mode,body:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=dracula] .md-icon .system-mode,body:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=dracula] .md-icon .unknown-mode{display:none}body:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=default] .md-icon .dark-mode,body:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=default] .md-icon .system-mode,body:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=default] .md-icon .unknown-mode{display:none}body:not([data-md-prefers-color-scheme=true]):not([data-md-color-scheme=default]):not([data-md-color-scheme=dracula]) .md-icon .dark-mode,body:not([data-md-prefers-color-scheme=true]):not([data-md-color-scheme=default]):not([data-md-color-scheme=dracula]) .md-icon .light-mode,body:not([data-md-prefers-color-scheme=true]):not([data-md-color-scheme=default]):not([data-md-color-scheme=dracula]) .md-icon .system-mode{display:none}body[data-md-prefers-color-scheme=true] .md-icon .dark-mode,body[data-md-prefers-color-scheme=true] .md-icon .light-mode,body[data-md-prefers-color-scheme=true] .md-icon .unknown-mode{display:none}.md-header-nav__scheme{z-index:0}[data-md-toggle=search]:checked~.md-header .md-header-nav__scheme{display:none}.md-typeset .admonition,.md-typeset details{border-width:0;border-left-width:4px}:root>*{--md-admonition-bg-color:transparent}:root>[data-md-color-scheme=dracula]{--md-admonition-icon-color:dracula.$drac-dark-yellow}:root>*{--md-admonition-icon--settings:url('data:image/svg+xml;charset=utf-8,');--md-admonition-bg-color--settings:rgba(170, 0, 255, 0.1);--md-admonition-icon-color--settings:#aa00ff;--md-admonition-shadow-color--settings:rgba(170, 0, 255, 0.1)}:root>[data-md-color-scheme=dracula]{--md-admonition-bg-color--settings:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--settings:hsl(326, 100%, 74%);--md-admonition-shadow-color--settings:hsla(326, 100%, 74%, 0.1)}:root>*{--md-admonition-bg-color--note:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--note:hsl(51, 94%, 73%);--md-admonition-shadow-color--note:hsl(51, 94%, 73%)}:root>*{--md-admonition-bg-color--abstract:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--abstract:hsl(191, 97%, 77%);--md-admonition-shadow-color--abstract:hsl(191, 97%, 77%)}:root>*{--md-admonition-bg-color--info:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--info:hsl(190, 94%, 87%);--md-admonition-shadow-color--info:hsl(190, 94%, 87%)}:root>*{--md-admonition-bg-color--tip:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--tip:hsl(161, 97%, 77%);--md-admonition-shadow-color--tip:hsl(161, 97%, 77%)}:root>*{--md-admonition-bg-color--success:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--success:hsl(135, 94%, 65%);--md-admonition-shadow-color--success:hsl(135, 94%, 65%)}:root>*{--md-admonition-bg-color--question:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--question:hsl(135, 92%, 79%);--md-admonition-shadow-color--question:hsl(135, 92%, 79%)}:root>*{--md-admonition-bg-color--warning:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--warning:hsl(31, 100%, 71%);--md-admonition-shadow-color--warning:hsl(31, 100%, 71%)}:root>*{--md-admonition-bg-color--failure:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--failure:hsl(0, 100%, 59%);--md-admonition-shadow-color--failure:hsl(0, 100%, 59%)}:root>*{--md-admonition-bg-color--danger:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--danger:hsl(0, 100%, 67%);--md-admonition-shadow-color--danger:hsl(0, 100%, 67%)}:root>*{--md-admonition-bg-color--bug:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--bug:hsl(325, 100%, 64%);--md-admonition-shadow-color--bug:hsl(325, 100%, 64%)}:root>*{--md-admonition-bg-color--example:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--example:hsl(265, 89%, 78%);--md-admonition-shadow-color--example:hsl(265, 89%, 78%)}:root>*{--md-admonition-bg-color--quote:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--quote:hsl(225, 8%, 51%);--md-admonition-shadow-color--quote:hsl(225, 8%, 51%)}:root>*{--md-admonition-icon--new:url('data:image/svg+xml;charset=utf-8,');--md-admonition-bg-color--new:rgba(255, 214, 0, 0.1);--md-admonition-icon-color--new:#ffd600;--md-admonition-shadow-color--new:rgba(255, 214, 0, 0.1)}:root>[data-md-color-scheme=dracula]{--md-admonition-bg-color--new:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--new:hsl(65, 92%, 76%);--md-admonition-shadow-color--new:hsla(65, 92%, 76%, 0.1)}:root>*{--md-admonition-bg-color--note:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--note:hsl(51, 94%, 73%);--md-admonition-shadow-color--note:hsl(51, 94%, 73%)}:root>*{--md-admonition-bg-color--abstract:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--abstract:hsl(191, 97%, 77%);--md-admonition-shadow-color--abstract:hsl(191, 97%, 77%)}:root>*{--md-admonition-bg-color--info:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--info:hsl(190, 94%, 87%);--md-admonition-shadow-color--info:hsl(190, 94%, 87%)}:root>*{--md-admonition-bg-color--tip:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--tip:hsl(161, 97%, 77%);--md-admonition-shadow-color--tip:hsl(161, 97%, 77%)}:root>*{--md-admonition-bg-color--success:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--success:hsl(135, 94%, 65%);--md-admonition-shadow-color--success:hsl(135, 94%, 65%)}:root>*{--md-admonition-bg-color--question:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--question:hsl(135, 92%, 79%);--md-admonition-shadow-color--question:hsl(135, 92%, 79%)}:root>*{--md-admonition-bg-color--warning:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--warning:hsl(31, 100%, 71%);--md-admonition-shadow-color--warning:hsl(31, 100%, 71%)}:root>*{--md-admonition-bg-color--failure:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--failure:hsl(0, 100%, 59%);--md-admonition-shadow-color--failure:hsl(0, 100%, 59%)}:root>*{--md-admonition-bg-color--danger:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--danger:hsl(0, 100%, 67%);--md-admonition-shadow-color--danger:hsl(0, 100%, 67%)}:root>*{--md-admonition-bg-color--bug:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--bug:hsl(325, 100%, 64%);--md-admonition-shadow-color--bug:hsl(325, 100%, 64%)}:root>*{--md-admonition-bg-color--example:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--example:hsl(265, 89%, 78%);--md-admonition-shadow-color--example:hsl(265, 89%, 78%)}:root>*{--md-admonition-bg-color--quote:var(--md-default-bg-color--ultra-dark);--md-admonition-icon-color--quote:hsl(225, 8%, 51%);--md-admonition-shadow-color--quote:hsl(225, 8%, 51%)}[data-md-color-scheme=dracula] .md-typeset .admonition,[data-md-color-scheme=dracula] .md-typeset details{border-color:var(--md-admonition-icon-color--note);box-shadow:var(--md-shadow-z2)}[data-md-color-scheme=dracula] .md-typeset .admonition:focus-within,[data-md-color-scheme=dracula] .md-typeset details:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details>summary{background-color:var(--md-admonition-bg-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details>summary::before{background-color:var(--md-admonition-icon-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details>summary::after{color:var(--md-admonition-icon-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition.note,[data-md-color-scheme=dracula] .md-typeset details.note{border-color:var(--md-admonition-icon-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition.note:focus-within,[data-md-color-scheme=dracula] .md-typeset details.note:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition.note>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.note>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.note>summary{background-color:var(--md-admonition-bg-color--note);border-color:var(--md-admonition-icon-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition.note>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.note>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.note>summary::before{background-color:var(--md-admonition-icon-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition.note>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.note>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.note>summary::after{color:var(--md-admonition-icon-color--note)}[data-md-color-scheme=dracula] .md-typeset .admonition.abstract,[data-md-color-scheme=dracula] .md-typeset details.abstract{border-color:var(--md-admonition-icon-color--abstract)}[data-md-color-scheme=dracula] .md-typeset .admonition.abstract:focus-within,[data-md-color-scheme=dracula] .md-typeset details.abstract:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--abstract)}[data-md-color-scheme=dracula] .md-typeset .admonition.abstract>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.abstract>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.abstract>summary{background-color:var(--md-admonition-bg-color--abstract);border-color:var(--md-admonition-icon-color--abstract)}[data-md-color-scheme=dracula] .md-typeset .admonition.abstract>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.abstract>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.abstract>summary::before{background-color:var(--md-admonition-icon-color--abstract)}[data-md-color-scheme=dracula] .md-typeset .admonition.abstract>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.abstract>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.abstract>summary::after{color:var(--md-admonition-icon-color--abstract)}[data-md-color-scheme=dracula] .md-typeset .admonition.info,[data-md-color-scheme=dracula] .md-typeset details.info{border-color:var(--md-admonition-icon-color--info)}[data-md-color-scheme=dracula] .md-typeset .admonition.info:focus-within,[data-md-color-scheme=dracula] .md-typeset details.info:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--info)}[data-md-color-scheme=dracula] .md-typeset .admonition.info>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.info>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.info>summary{background-color:var(--md-admonition-bg-color--info);border-color:var(--md-admonition-icon-color--info)}[data-md-color-scheme=dracula] .md-typeset .admonition.info>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.info>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.info>summary::before{background-color:var(--md-admonition-icon-color--info)}[data-md-color-scheme=dracula] .md-typeset .admonition.info>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.info>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.info>summary::after{color:var(--md-admonition-icon-color--info)}[data-md-color-scheme=dracula] .md-typeset .admonition.tip,[data-md-color-scheme=dracula] .md-typeset details.tip{border-color:var(--md-admonition-icon-color--tip)}[data-md-color-scheme=dracula] .md-typeset .admonition.tip:focus-within,[data-md-color-scheme=dracula] .md-typeset details.tip:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--tip)}[data-md-color-scheme=dracula] .md-typeset .admonition.tip>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.tip>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.tip>summary{background-color:var(--md-admonition-bg-color--tip);border-color:var(--md-admonition-icon-color--tip)}[data-md-color-scheme=dracula] .md-typeset .admonition.tip>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.tip>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.tip>summary::before{background-color:var(--md-admonition-icon-color--tip)}[data-md-color-scheme=dracula] .md-typeset .admonition.tip>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.tip>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.tip>summary::after{color:var(--md-admonition-icon-color--tip)}[data-md-color-scheme=dracula] .md-typeset .admonition.success,[data-md-color-scheme=dracula] .md-typeset details.success{border-color:var(--md-admonition-icon-color--success)}[data-md-color-scheme=dracula] .md-typeset .admonition.success:focus-within,[data-md-color-scheme=dracula] .md-typeset details.success:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--success)}[data-md-color-scheme=dracula] .md-typeset .admonition.success>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.success>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.success>summary{background-color:var(--md-admonition-bg-color--success);border-color:var(--md-admonition-icon-color--success)}[data-md-color-scheme=dracula] .md-typeset .admonition.success>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.success>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.success>summary::before{background-color:var(--md-admonition-icon-color--success)}[data-md-color-scheme=dracula] .md-typeset .admonition.success>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.success>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.success>summary::after{color:var(--md-admonition-icon-color--success)}[data-md-color-scheme=dracula] .md-typeset .admonition.question,[data-md-color-scheme=dracula] .md-typeset details.question{border-color:var(--md-admonition-icon-color--question)}[data-md-color-scheme=dracula] .md-typeset .admonition.question:focus-within,[data-md-color-scheme=dracula] .md-typeset details.question:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--question)}[data-md-color-scheme=dracula] .md-typeset .admonition.question>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.question>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.question>summary{background-color:var(--md-admonition-bg-color--question);border-color:var(--md-admonition-icon-color--question)}[data-md-color-scheme=dracula] .md-typeset .admonition.question>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.question>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.question>summary::before{background-color:var(--md-admonition-icon-color--question)}[data-md-color-scheme=dracula] .md-typeset .admonition.question>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.question>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.question>summary::after{color:var(--md-admonition-icon-color--question)}[data-md-color-scheme=dracula] .md-typeset .admonition.warning,[data-md-color-scheme=dracula] .md-typeset details.warning{border-color:var(--md-admonition-icon-color--warning)}[data-md-color-scheme=dracula] .md-typeset .admonition.warning:focus-within,[data-md-color-scheme=dracula] .md-typeset details.warning:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--warning)}[data-md-color-scheme=dracula] .md-typeset .admonition.warning>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.warning>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.warning>summary{background-color:var(--md-admonition-bg-color--warning);border-color:var(--md-admonition-icon-color--warning)}[data-md-color-scheme=dracula] .md-typeset .admonition.warning>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.warning>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.warning>summary::before{background-color:var(--md-admonition-icon-color--warning)}[data-md-color-scheme=dracula] .md-typeset .admonition.warning>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.warning>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.warning>summary::after{color:var(--md-admonition-icon-color--warning)}[data-md-color-scheme=dracula] .md-typeset .admonition.failure,[data-md-color-scheme=dracula] .md-typeset details.failure{border-color:var(--md-admonition-icon-color--failure)}[data-md-color-scheme=dracula] .md-typeset .admonition.failure:focus-within,[data-md-color-scheme=dracula] .md-typeset details.failure:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--failure)}[data-md-color-scheme=dracula] .md-typeset .admonition.failure>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.failure>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.failure>summary{background-color:var(--md-admonition-bg-color--failure);border-color:var(--md-admonition-icon-color--failure)}[data-md-color-scheme=dracula] .md-typeset .admonition.failure>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.failure>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.failure>summary::before{background-color:var(--md-admonition-icon-color--failure)}[data-md-color-scheme=dracula] .md-typeset .admonition.failure>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.failure>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.failure>summary::after{color:var(--md-admonition-icon-color--failure)}[data-md-color-scheme=dracula] .md-typeset .admonition.danger,[data-md-color-scheme=dracula] .md-typeset details.danger{border-color:var(--md-admonition-icon-color--danger)}[data-md-color-scheme=dracula] .md-typeset .admonition.danger:focus-within,[data-md-color-scheme=dracula] .md-typeset details.danger:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--danger)}[data-md-color-scheme=dracula] .md-typeset .admonition.danger>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.danger>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.danger>summary{background-color:var(--md-admonition-bg-color--danger);border-color:var(--md-admonition-icon-color--danger)}[data-md-color-scheme=dracula] .md-typeset .admonition.danger>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.danger>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.danger>summary::before{background-color:var(--md-admonition-icon-color--danger)}[data-md-color-scheme=dracula] .md-typeset .admonition.danger>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.danger>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.danger>summary::after{color:var(--md-admonition-icon-color--danger)}[data-md-color-scheme=dracula] .md-typeset .admonition.bug,[data-md-color-scheme=dracula] .md-typeset details.bug{border-color:var(--md-admonition-icon-color--bug)}[data-md-color-scheme=dracula] .md-typeset .admonition.bug:focus-within,[data-md-color-scheme=dracula] .md-typeset details.bug:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--bug)}[data-md-color-scheme=dracula] .md-typeset .admonition.bug>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.bug>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.bug>summary{background-color:var(--md-admonition-bg-color--bug);border-color:var(--md-admonition-icon-color--bug)}[data-md-color-scheme=dracula] .md-typeset .admonition.bug>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.bug>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.bug>summary::before{background-color:var(--md-admonition-icon-color--bug)}[data-md-color-scheme=dracula] .md-typeset .admonition.bug>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.bug>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.bug>summary::after{color:var(--md-admonition-icon-color--bug)}[data-md-color-scheme=dracula] .md-typeset .admonition.example,[data-md-color-scheme=dracula] .md-typeset details.example{border-color:var(--md-admonition-icon-color--example)}[data-md-color-scheme=dracula] .md-typeset .admonition.example:focus-within,[data-md-color-scheme=dracula] .md-typeset details.example:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--example)}[data-md-color-scheme=dracula] .md-typeset .admonition.example>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.example>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.example>summary{background-color:var(--md-admonition-bg-color--example);border-color:var(--md-admonition-icon-color--example)}[data-md-color-scheme=dracula] .md-typeset .admonition.example>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.example>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.example>summary::before{background-color:var(--md-admonition-icon-color--example)}[data-md-color-scheme=dracula] .md-typeset .admonition.example>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.example>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.example>summary::after{color:var(--md-admonition-icon-color--example)}[data-md-color-scheme=dracula] .md-typeset .admonition.quote,[data-md-color-scheme=dracula] .md-typeset details.quote{border-color:var(--md-admonition-icon-color--quote)}[data-md-color-scheme=dracula] .md-typeset .admonition.quote:focus-within,[data-md-color-scheme=dracula] .md-typeset details.quote:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--quote)}[data-md-color-scheme=dracula] .md-typeset .admonition.quote>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.quote>.admonition-title,[data-md-color-scheme=dracula] .md-typeset details.quote>summary{background-color:var(--md-admonition-bg-color--quote);border-color:var(--md-admonition-icon-color--quote)}[data-md-color-scheme=dracula] .md-typeset .admonition.quote>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.quote>.admonition-title::before,[data-md-color-scheme=dracula] .md-typeset details.quote>summary::before{background-color:var(--md-admonition-icon-color--quote)}[data-md-color-scheme=dracula] .md-typeset .admonition.quote>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.quote>.admonition-title::after,[data-md-color-scheme=dracula] .md-typeset details.quote>summary::after{color:var(--md-admonition-icon-color--quote)}.md-typeset .admonition.config,.md-typeset .admonition.settings,.md-typeset details.config,.md-typeset details.settings{border-color:var(--md-admonition-icon-color--settings)}.md-typeset .admonition.config:focus-within,.md-typeset .admonition.settings:focus-within,.md-typeset details.config:focus-within,.md-typeset details.settings:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--settings)}.md-typeset .admonition.config>.admonition-title,.md-typeset .admonition.settings>.admonition-title,.md-typeset details.config>.admonition-title,.md-typeset details.config>summary,.md-typeset details.settings>.admonition-title,.md-typeset details.settings>summary{background-color:var(--md-admonition-bg-color--settings);border-color:var(--md-admonition-icon-color--settings)}.md-typeset .admonition.config>.admonition-title::before,.md-typeset .admonition.settings>.admonition-title::before,.md-typeset details.config>.admonition-title::before,.md-typeset details.config>summary::before,.md-typeset details.settings>.admonition-title::before,.md-typeset details.settings>summary::before{width:1rem;height:1rem;background-color:var(--md-admonition-icon-color--settings);background-size:1rem;-webkit-mask-image:var(--md-admonition-icon--settings);mask-image:var(--md-admonition-icon--settings);content:" "}.md-typeset .admonition.config>.admonition-title::after,.md-typeset .admonition.settings>.admonition-title::after,.md-typeset details.config>.admonition-title::after,.md-typeset details.config>summary::after,.md-typeset details.settings>.admonition-title::after,.md-typeset details.settings>summary::after{color:var(--md-admonition-icon-color--settings)}.md-typeset .admonition.new,.md-typeset details.new{border-color:var(--md-admonition-icon-color--new)}.md-typeset .admonition.new:focus-within,.md-typeset details.new:focus-within{box-shadow:0 0 0 .2rem var(--md-admonition-shadow-color--new)}.md-typeset .admonition.new>.admonition-title,.md-typeset details.new>.admonition-title,.md-typeset details.new>summary{background-color:var(--md-admonition-bg-color--new);border-color:var(--md-admonition-icon-color--new)}.md-typeset .admonition.new>.admonition-title::before,.md-typeset details.new>.admonition-title::before,.md-typeset details.new>summary::before{width:1rem;height:1rem;background-color:var(--md-admonition-icon-color--new);background-size:1rem;-webkit-mask-image:var(--md-admonition-icon--new);mask-image:var(--md-admonition-icon--new);content:" "}.md-typeset .admonition.new>.admonition-title::after,.md-typeset details.new>.admonition-title::after,.md-typeset details.new>summary::after{color:var(--md-admonition-icon-color--new)}mjx-container[display=true]{font-size:120%!important}mjx-container:not([display]){font-size:100%!important}[data-md-color-scheme=dracula] .CtxtMenu_InfoContent pre,[data-md-color-scheme=dracula] .CtxtMenu_InfoSignature input,[data-md-color-scheme=slate] .CtxtMenu_InfoContent pre,[data-md-color-scheme=slate] .CtxtMenu_InfoSignature input{color:#000}[data-md-color-scheme=dracula] .CtxtMenu_Info,[data-md-color-scheme=dracula] .CtxtMenu_Menu,[data-md-color-scheme=slate] .CtxtMenu_Info,[data-md-color-scheme=slate] .CtxtMenu_Menu{box-shadow:0 10px 20px rgba(0,0,0,.5)}.md-typeset .arithmatex{overflow-x:auto!important;overflow-y:hidden!important}.katex-display .katex-html{display:flex!important;flex-direction:row;flex-wrap:nowrap;align-items:baseline;justify-content:space-between}.katex-display .katex-html .base{display:inline!important}.katex-display .katex-html .tag{position:relative!important;display:inline!important;margin-left:var(--margin-small)}.md-typeset del.critic,.md-typeset ins.critic,.md-typeset mark.critic{padding:0 .25em;color:unset;box-shadow:none}.md-typeset .critic.break{margin:0}.md-typeset details{overflow:hidden}.md-typeset details>summary:focus{outline-style:none}.highlight .kc{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne{color:var(--md-code-hl-class-color)}.highlight .mb{color:var(--md-code-hl-number-color)}.highlight .bp,.highlight .nb{color:var(--md-code-hl-builtin-color)}.highlight .nn{color:var(--md-code-hl-namespace-color)}.highlight .na,.highlight .nd,.highlight .ni{color:var(--md-code-hl-entity-color)}.highlight .nl,.highlight .nt{color:var(--md-code-hl-tag-color)}.md-typeset :not(pre)>code{margin:0;padding:0 .2941176471em;color:var(--md-code-fg-color);background-color:var(--md-code-inline-bg-color);border-radius:px2rem(2px);box-shadow:none}.md-typeset a>code{color:inherit!important;background-color:var(--md-code-link-bg-color)!important;transition:color 125ms;transition:background-color 125ms}.md-typeset a>code *{color:var(--md-typeset-a-color)!important}.md-typeset a>code:hover{background-color:var(--md-code-link-accent-bg-color)!important}.md-typeset a>code:hover *{color:var(--md-accent-fg-color)!important}.md-typeset pre>code{outline:0}.md-typeset td code{word-break:normal}.md-typeset .highlight{-moz-tab-size:8;-o-tab-size:8;tab-size:8}.md-typeset .highlight+.result{border-width:px2rem(2px)}.md-typeset .highlight [data-linenos].special::before{background-color:var(--md-code-special-bg-color)}.md-typeset .highlighttable .linenodiv .special{margin-right:-.5882352941em;margin-left:-1.1764705882em;padding-right:.5882352941em;padding-left:1.1764705882em;background-color:var(--md-code-special-bg-color)}.md-typeset .highlight span.filename{position:relative;display:block;margin-top:1em;padding:.5em 1.1764705882em .5em 2.9411764706em;font-weight:700;font-size:px2rem(13.6px);background-color:var(--md-code-title-bg-color);border-top-left-radius:px2rem(2px);border-top-right-radius:px2rem(2px)}.md-typeset .highlight span.filename+pre{margin-top:0}.md-typeset .highlight span.filename+pre code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .highlight span.filename::before{position:absolute;left:.8823529412em;width:1.4705882353em;height:1.4705882353em;background-color:var(--md-default-fg-color);-webkit-mask-image:url('data:image/svg+xml;charset=utf-8,');mask-image:url('data:image/svg+xml;charset=utf-8,');-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-typeset .collapse-code{position:relative;margin-top:1em;margin-bottom:1em}.md-typeset .collapse-code pre{margin-top:0;margin-bottom:0}.md-typeset .collapse-code input{display:none}.md-typeset .collapse-code input~.code-footer{width:100%;margin:0;padding:.25em .5em .25em 0}.md-typeset .collapse-code input~.code-footer label{position:relative;margin:.05em;padding:.15em .8em;color:var(--md-primary-bg-color);font-size:90%;background-color:var(--md-primary-fg-color);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;border-radius:px2rem(2px);cursor:pointer;content:""}.md-typeset .collapse-code input~.code-footer label:hover{background-color:var(--md-accent-fg-color)}.md-typeset .collapse-code input~.code-footer label::before{position:absolute;top:.15em;left:.15em;display:block;box-sizing:border-box;width:1.25em;height:1.25em;background-color:var(--md-primary-bg-color);background-size:1.25em;content:""}.md-typeset .collapse-code input~.code-footer label.expand{display:none}.md-typeset .collapse-code input~.code-footer label.expand::before{-webkit-mask-image:url('data:image/svg+xml;charset=utf-8,');mask-image:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .collapse-code input~.code-footer label.collapse::before{-webkit-mask-image:url('data:image/svg+xml;charset=utf-8,');mask-image:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .collapse-code input:checked~.code-footer label.expand{display:inline}.md-typeset .collapse-code input:checked~.code-footer label.collapse{display:none}.md-typeset .collapse-code input:checked+div.highlight code{max-height:9.375em;overflow:hidden}.md-typeset .collapse-code input:checked~.code-footer{position:absolute;bottom:0;left:0;padding:2em .5em .5em px2rem(16px);background-image:linear-gradient(to bottom,transparent,var(--md-default-bg-color) 80% 100%)}.md-typeset .keys .key-power::before{padding-right:.4em;content:"⏻"}.md-typeset .keys .key-fingerprint::before{padding-right:.4em;content:"☝"}:root>*{--magiclink-email-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-github-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-bitbucket-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-gitlab-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-commit-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-compare-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-pull-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-issue-icon:url('data:image/svg+xml;charset=utf-8,');--magiclink-discussion-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset a[href^="mailto:"]:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-email-icon);mask-image:var(--magiclink-email-icon)}.md-typeset .magiclink-commit:not(.magiclink-ignore),.md-typeset .magiclink-compare:not(.magiclink-ignore),.md-typeset .magiclink-discussion:not(.magiclink-ignore),.md-typeset .magiclink-issue:not(.magiclink-ignore),.md-typeset .magiclink-pull:not(.magiclink-ignore),.md-typeset .magiclink-repository:not(.magiclink-ignore),.md-typeset a[href^="mailto:"]:not(.magiclink-ignore){position:relative;padding-left:1.375em}.md-typeset .magiclink-commit:not(.magiclink-ignore)::before,.md-typeset .magiclink-compare:not(.magiclink-ignore)::before,.md-typeset .magiclink-discussion:not(.magiclink-ignore)::before,.md-typeset .magiclink-issue:not(.magiclink-ignore)::before,.md-typeset .magiclink-pull:not(.magiclink-ignore)::before,.md-typeset .magiclink-repository:not(.magiclink-ignore)::before,.md-typeset a[href^="mailto:"]:not(.magiclink-ignore)::before{position:absolute;top:0;left:0;display:block;box-sizing:border-box;width:1.25em;height:1.25em;background-color:var(--md-typeset-a-color);background-size:1.25em;transition:background-color 125ms;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-typeset .magiclink-commit:not(.magiclink-ignore):hover::before,.md-typeset .magiclink-compare:not(.magiclink-ignore):hover::before,.md-typeset .magiclink-discussion:not(.magiclink-ignore):hover::before,.md-typeset .magiclink-issue:not(.magiclink-ignore):hover::before,.md-typeset .magiclink-pull:not(.magiclink-ignore):hover::before,.md-typeset .magiclink-repository:not(.magiclink-ignore):hover::before,.md-typeset a[href^="mailto:"]:not(.magiclink-ignore):hover::before{background-color:var(--md-accent-fg-color)}.md-typeset .magiclink-commit:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-commit-icon);mask-image:var(--magiclink-commit-icon)}.md-typeset .magiclink-compare:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-compare-icon);mask-image:var(--magiclink-compare-icon)}.md-typeset .magiclink-pull:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-pull-icon);mask-image:var(--magiclink-pull-icon)}.md-typeset .magiclink-issue:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-issue-icon);mask-image:var(--magiclink-issue-icon)}.md-typeset .magiclink-discussion:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-discussion-icon);mask-image:var(--magiclink-discussion-icon)}.md-typeset .magiclink-repository.magiclink-github:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-github-icon);mask-image:var(--magiclink-github-icon)}.md-typeset .magiclink-repository.magiclink-gitlab:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-gitlab-icon);mask-image:var(--magiclink-gitlab-icon)}.md-typeset .magiclink-repository.magiclink-bitbucket:not(.magiclink-ignore)::before{-webkit-mask-image:var(--magiclink-bitbucket-icon);mask-image:var(--magiclink-bitbucket-icon)}.md-typeset mark:not(.critic){box-shadow:none}.md-typeset .progress-label{position:absolute;width:100%;margin:0;color:var(--md-text-color);font-weight:700;line-height:1.4rem;white-space:nowrap;text-align:center;text-shadow:-.0625em -.0625em .375em var(--md-default-bg-color--light),.0625em -.0625em .375em var(--md-default-bg-color--light),-.0625em .0625em .375em var(--md-default-bg-color--light),.0625em .0625em .375em var(--md-default-bg-color--light)}.md-typeset .progress-bar{float:left;height:1.2rem;background-color:#2979ff}.md-typeset .candystripe-animate .progress-bar{animation:animate-stripes 3s linear infinite}.md-typeset .progress{position:relative;display:block;width:100%;height:1.2rem;margin:.5rem 0;background-color:var(--md-default-fg-color--lightest)}.md-typeset .progress.thin{height:.4rem;margin-top:.9rem}.md-typeset .progress.thin .progress-label{margin-top:-.4rem}.md-typeset .progress.thin .progress-bar{height:.4rem}.md-typeset .progress.candystripe .progress-bar{background-image:linear-gradient(135deg,var(--md-progress-stripe) 27%,transparent 27%,transparent 52%,var(--md-progress-stripe) 52%,var(--md-progress-stripe) 77%,transparent 77%,transparent);background-size:2rem 2rem}.md-typeset .progress-100plus .progress-bar{background-color:var(--md-progress-100)}.md-typeset .progress-80plus .progress-bar{background-color:var(--md-progress-80)}.md-typeset .progress-60plus .progress-bar{background-color:var(--md-progress-60)}.md-typeset .progress-40plus .progress-bar{background-color:var(--md-progress-40)}.md-typeset .progress-20plus .progress-bar{background-color:var(--md-progress-20)}.md-typeset .progress-0plus .progress-bar{background-color:var(--md-progress-0)}@keyframes animate-stripes{0%{background-position:0 0}100%{background-position:6rem 0}}[data-md-color-scheme=dracula] .md-typeset .tabbed-set>.tabbed-labels{box-shadow:0 -.05rem var(--md-default-fg-color--lighter) inset}.md-typeset .tabbed-alternate.tabbed-set .tabbed-control{width:2rem}.md-typeset .tabbed-alternate.tabbed-set .tabbed-control[hidden]{width:1.2rem;opacity:0}.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block{padding:0 .6rem}.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.codehilite:only-child,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.codehilitetable:only-child,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.highlight:only-child,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.highlighttable:only-child,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>pre:only-child{margin-right:-1.2rem;margin-left:-1.2rem;padding-right:.6rem;padding-left:.6rem}.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.codehilite:only-child span.filename,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.codehilitetable:only-child span.filename,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.highlight:only-child span.filename,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.highlighttable:only-child span.filename,.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>pre:only-child span.filename{margin-top:0}.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.collapse-code:only-child{margin-top:0;margin-right:-1.2rem;margin-left:-1.2rem;padding-right:.6rem;padding-left:.6rem}.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>.collapse-code:only-child>.code-footer{left:.6rem}.md-typeset .tabbed-alternate.tabbed-set>.tabbed-content>.tabbed-block>diagram-div:only-child{margin-right:-1.2rem;margin-left:-1.2rem;padding-right:.6rem;padding-left:.6rem}.js .md-typeset .tabbed-labels::before{background-color:var(--md-accent-fg-color)}[data-md-color-scheme=dracula] .md-typeset table:not([class]){box-shadow:var(--md-shadow-z2)}[data-md-color-scheme=dracula] .md-typeset table:not([class]) tr:hover{background-color:rgba(0,0,0,.08)}[data-md-color-scheme=dracula] .md-typeset table:not([class]) th{color:var(--md-text-color);background-color:var(--md-default-bg-color--ultra-dark);border-bottom:.05rem solid var(--md-primary-fg-color)}[data-md-color-scheme=dracula] .md-typeset table:not([class]) td{border-top:.05rem solid var(--md-default-fg-color--lighter)}[data-md-color-scheme=dracula] .md-typeset .task-list-control .task-list-indicator::before{background-color:var(--md-default-fg-color--lighter)}[data-md-color-scheme=dracula] .md-typeset .task-list-control [type=checkbox]:checked+.task-list-indicator::before{background-color:#51f97b}.md-typeset .headerlink{width:1em;height:1em;vertical-align:middle;background-color:var(--md-default-fg-color--lighter);background-size:1em;-webkit-mask-size:1em;mask-size:1em;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;visibility:visible;-webkit-mask-image:url('data:image/svg+xml;charset=utf-8,');mask-image:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .headerlink:hover,.md-typeset [id]:target .headerlink{background-color:var(--md-accent-fg-color)}diagram-div{overflow:auto}html{background-color:transparent}[data-md-component=announce] .twemoji{color:var(--md-primary-fg-color)}[data-md-color-scheme=dracula]{--md-text-color:var(--md-default-fg-color);background-color:var(--md-default-bg-color);--md-footer-bg-color:transparent;--md-footer-bg-color--dark:var(--md-default-bg-color--darkest);--md-header-fg-color:var(--md-text-color);--md-header-bg-color:var(--md-default-bg-color--darkest)}[data-md-color-scheme=dracula] .md-header{color:var(--md-text-color);background-color:var(--md-header-bg-color);border-bottom:.05rem solid var(--md-primary-fg-color)}[data-md-color-scheme=dracula] .md-header[data-md-state=shadow]{box-shadow:0 0 .2rem rgba(0,0,0,.15),0 0 .2rem .4rem rgba(0,0,0,.2)}[data-md-color-scheme=dracula] .md-top{background-color:var(--md-default-bg-color--dark)}[data-md-color-scheme=dracula] .md-top:hover{background-color:var(--md-primary-fg-color)}[data-md-color-scheme=dracula] .md-tabs{color:var(--md-text-color);background-color:var(--md-primary-fg-color--transparent)}[data-md-color-scheme=dracula] .md-tabs__link--active{color:var(--md-primary-fg-color)}[data-md-color-scheme=dracula] .md-tabs__link:hover{color:var(--md-accent-fg-color)}[data-md-color-scheme=dracula] .md-hero{color:var(--md-text-color);background-color:var(--md-primary-fg-color--transparent)}[data-md-color-scheme=dracula] .md-nav__source{color:var(--md-text-color)}[data-md-color-scheme=dracula] .md-nav__link[data-md-state=blur]{color:var(--md-default-fg-color--light)}[data-md-color-scheme=dracula] .md-nav__item .md-nav__link--active{color:var(--md-primary-fg-color)}[data-md-color-scheme=dracula] .md-nav__link:focus,[data-md-color-scheme=dracula] .md-nav__link:hover{color:var(--md-accent-fg-color)}[data-md-color-scheme=dracula] .md-search__input{color:var(--md-text-color);background-color:var(--md-accent-bg-color--light)}[data-md-color-scheme=dracula] .md-search__input:hover{background-color:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] .md-search__input~.md-search__icon{color:var(--md-text-color)}[data-md-color-scheme=dracula] .md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}[data-md-color-scheme=dracula] .md-search__input::placeholder{color:var(--md-default-fg-color--light)}[data-md-color-scheme=dracula] [data-md-toggle=search]:checked~.md-header .md-search__input{background-color:transparent}[data-md-color-scheme=dracula] .md-search__suggest{color:var(--md-default-autocomplete-fg-color)}[data-md-color-scheme=dracula] .md-overlay,[data-md-color-scheme=dracula] .md-search__overlay{background-color:var(--md-default-bg-color--light)}[data-md-color-scheme=dracula] .md-footer-nav__direction{color:var(--md-primary-fg-color)}[data-md-color-scheme=dracula] .md-footer-meta{border-top:.05rem solid var(--md-primary-fg-color)}[data-md-color-scheme=dracula] [data-md-component=announce]{background-color:var(--md-default-bg-color--ultra-dark)}.md-typeset h5{color:var(--md-text-color);text-transform:none}.md-search__scrollwrap,.md-sidebar__scrollwrap,.md-typeset diagram-div,.md-typeset div.arithmatex,.md-typeset div.diagram,.md-typeset div.mermaid,.md-typeset mermaid-div,.md-typeset pre.arithmatex,.md-typeset pre>code,.md-typeset__scrollwrap{scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin}.md-search__scrollwrap:hover,.md-sidebar__scrollwrap:hover,.md-typeset diagram-div:hover,.md-typeset div.arithmatex:hover,.md-typeset div.diagram:hover,.md-typeset div.mermaid:hover,.md-typeset mermaid-div:hover,.md-typeset pre.arithmatex:hover,.md-typeset pre>code:hover,.md-typeset__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar,.md-sidebar__scrollwrap::-webkit-scrollbar,.md-typeset diagram-div::-webkit-scrollbar,.md-typeset div.arithmatex::-webkit-scrollbar,.md-typeset div.diagram::-webkit-scrollbar,.md-typeset div.mermaid::-webkit-scrollbar,.md-typeset mermaid-div::-webkit-scrollbar,.md-typeset pre.arithmatex::-webkit-scrollbar,.md-typeset pre>code::-webkit-scrollbar,.md-typeset__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-search__scrollwrap::-webkit-scrollbar-corner,.md-sidebar__scrollwrap::-webkit-scrollbar-corner,.md-typeset diagram-div::-webkit-scrollbar-corner,.md-typeset div.arithmatex::-webkit-scrollbar-corner,.md-typeset div.diagram::-webkit-scrollbar-corner,.md-typeset div.mermaid::-webkit-scrollbar-corner,.md-typeset mermaid-div::-webkit-scrollbar-corner,.md-typeset pre.arithmatex::-webkit-scrollbar-corner,.md-typeset pre>code::-webkit-scrollbar-corner,.md-typeset__scrollwrap::-webkit-scrollbar-corner{background-color:transparent}.md-search__scrollwrap::-webkit-scrollbar-thumb,.md-sidebar__scrollwrap::-webkit-scrollbar-thumb,.md-typeset diagram-div::-webkit-scrollbar-thumb,.md-typeset div.arithmatex::-webkit-scrollbar-thumb,.md-typeset div.diagram::-webkit-scrollbar-thumb,.md-typeset div.mermaid::-webkit-scrollbar-thumb,.md-typeset mermaid-div::-webkit-scrollbar-thumb,.md-typeset pre.arithmatex::-webkit-scrollbar-thumb,.md-typeset pre>code::-webkit-scrollbar-thumb,.md-typeset__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover,.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover,.md-typeset diagram-div::-webkit-scrollbar-thumb:hover,.md-typeset div.arithmatex::-webkit-scrollbar-thumb:hover,.md-typeset div.diagram::-webkit-scrollbar-thumb:hover,.md-typeset div.mermaid::-webkit-scrollbar-thumb:hover,.md-typeset mermaid-div::-webkit-scrollbar-thumb:hover,.md-typeset pre.arithmatex::-webkit-scrollbar-thumb:hover,.md-typeset pre>code::-webkit-scrollbar-thumb:hover,.md-typeset__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width:59.9375em){.md-header-nav__scheme{padding-right:0}label[for=__search]{padding-left:0}[data-md-color-scheme=dracula] .md-nav__source{color:var(--md-text-color);background-color:var(--md-primary-fg-color--transparent)}[data-md-color-scheme=dracula] .md-nav .md-nav__title{color:var(--md-text-color);background-color:var(--md-header-bg-color);border-bottom:.05rem solid var(--md-primary-fg-color)}}@media screen and (max-width:44.9375em){.md-typeset>diagram-div{margin-right:px2rem(-16px);margin-left:px2rem(-16px)}.md-typeset>.collapse-code{margin-right:px2rem(-16px);margin-left:px2rem(-16px)}.md-typeset>.collapse-code label.collapse{left:px2rem(16px)}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:0}.md-content__inner>.tabbed-set .tabbed-labels{max-width:100%;margin:0;padding-inline-start:0;scroll-padding-inline-start:0}.md-content__inner>.tabbed-set .tabbed-labels::after{padding-inline-end:0;content:none}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-inline-start:0;padding-inline-start:0}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-inline-end:0;padding-inline-end:0}}@media screen and (max-width:76.1875em){[data-md-color-scheme=dracula] .md-nav--primary .md-nav__item--active>.md-nav__link:not(:hover){color:var(--md-primary-fg-color)}[data-md-color-scheme=dracula] .md-nav--primary .md-nav__title{color:var(--md-text-color);background-color:var(--md-header-bg-color);border-bottom:.05rem solid var(--md-primary-fg-color)}}
+/*# sourceMappingURL=extra-pymdownx.css.map */
diff --git a/docs/assets/css/extra-pymdownx.css.map b/docs/assets/css/extra-pymdownx.css.map
new file mode 100644
index 0000000..4c61497
--- /dev/null
+++ b/docs/assets/css/extra-pymdownx.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["palette/_colors.scss","extra.css","_general.scss","extensions/_admonition.scss","extensions/_arithmatex.scss","extensions/_critic.scss","extensions/_details.scss","extensions/_highlight.scss","extensions/_keys.scss","extensions/_magiclink.scss","extensions/_mark.scss","extensions/_progressbar.scss","extensions/_tabbed.scss","extensions/_tables.scss","extensions/_tasklist.scss","extensions/_toc.scss","extensions/_superfences.scss","_material.scss","utilities/_break.scss"],"names":[],"mappings":"iBAOA,QAEE,wBAAA,oBACA,+BAAA,6BACA,6BAAA,yBACA,yBAAA,wBACA,0BAAA,wBAEA,2BAAA,gBACA,6BAAA,wBAEA,+BAAA,wBACA,6BAAA,wBAEA,0BAAA,gCACA,uBAAA,gCACA,2BAAA,iCACA,yBAAA,iCAGA,qBAAA,QAGA,qBAAA,oCACA,kBAAA,QACA,iBAAA,QACA,iBAAA,QACA,iBAAA,QACA,iBAAA,QACA,gBAAA,QAGA,uBAAA,yBACA,8BAAA,yBACA,8BAAA,uBAEA,mCAEE,wBAAA,uBACA,+BAAA,6BACA,2BAAA,mBACA,6BAAA,qBAGA,uBAAA,qCACA,8BAAA,wBACA,8BAAA,oCAIF,qCAEE,sBAAA,yBACA,6BAAA,yBACA,+BAAA,yBACA,gCAAA,yBACA,mCAAA,wBACA,eAAA,EAAA,OAAA,OAAA,oBAAA,CCrBmC,EAAE,EAAE,QAAQ,qBDwB/C,sBAAA,oCACA,6BAAA,yBACA,+BAAA,yBACA,gCAAA,0BACA,6BAAA,uBAGA,4BAAA,mBACA,8BAAA,mBACA,+BAAA,mBACA,kCAAA,kBAGA,gBAAA,2BACA,mBAAA,2BAGA,yBAAA,2BAGA,mBAAA,kBACA,mBAAA,mBACA,yBAAA,uCACA,0BAAA,mBACA,4BAAA,oBACA,+BAAA,kBACA,0BAAA,kBACA,2BAAA,mBACA,0BAAA,mBACA,2BAAA,oBACA,wBAAA,kBACA,4BAAA,mBACA,4BAAA,mBACA,2BAAA,mBACA,4BAAA,mBACA,2BAAA,mBACA,mBAAA,mBAGA,0BAAA,mBACA,uBAAA,oBACA,6BAAA,kBACA,2BAAA,mBACA,yBAAA,mBAEA,2BAAA,mBACA,6BAAA,gCACA,wBAAA,sCAGA,qBAAA,mBACA,wBAAA,qCACA,uBAAA,qCACA,uBAAA,mCAGA,qBAAA,qCACA,kBAAA,mBACA,iBAAA,mBACA,iBAAA,kBACA,iBAAA,mBACA,iBAAA,oBACA,gBAAA,kBAGA,uBAAA,qCACA,8BAAA,uCACA,8BAAA,oCCpCJ,uFDgEE,0DAIE,2BAAA,mCACA,sBAAA,yBACA,mCAAA,2BACA,6BAAA,yBACA,4BAAA,yBACA,sBAAA,2BACA,6BAAA,kCC/DJ,wFDqDE,2DAIE,2BAAA,mCACA,sBAAA,2BACA,mCAAA,6BACA,6BAAA,2BACA,4BAAA,2BACA,sBAAA,2BACA,6BAAA,kCCpDJ,0FD0CE,6DAIE,2BAAA,mCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCzCJ,+FD+BE,kEAIE,2BAAA,mCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCC9BJ,wFDoBE,2DAIE,2BAAA,sCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCnBJ,0FDSE,6DAIE,2BAAA,sCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCRJ,8FDFE,iEAIE,2BAAA,sCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCGJ,wFDbE,2DAIE,2BAAA,sCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCcJ,wFDxBE,2DAIE,2BAAA,sCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCyBJ,yFDnCE,4DAIE,2BAAA,kCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCoCJ,+FD9CE,kEAIE,2BAAA,kCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCC+CJ,wFDzDE,2DAIE,2BAAA,kCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCC0DJ,0FDpEE,6DAIE,2BAAA,mCACA,sBAAA,yBACA,mCAAA,2BACA,6BAAA,yBACA,4BAAA,yBACA,sBAAA,2BACA,6BAAA,kCCqEJ,yFD/EE,4DAIE,2BAAA,mCACA,sBAAA,yBACA,mCAAA,2BACA,6BAAA,yBACA,4BAAA,yBACA,sBAAA,2BACA,6BAAA,kCCgFJ,0FD1FE,6DAIE,2BAAA,mCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCC2FJ,+FDrGE,kEAIE,2BAAA,mCACA,sBAAA,0BACA,mCAAA,4BACA,6BAAA,0BACA,4BAAA,0BACA,sBAAA,2BACA,6BAAA,kCCsGJ,uFD1EE,yDAEE,+BAAA,mCACA,qBAAA,yBACA,kCAAA,2BACA,qBAAA,2BACA,4BAAA,kCC6EJ,wFDnFE,0DAEE,+BAAA,mCACA,qBAAA,2BACA,kCAAA,6BACA,qBAAA,2BACA,4BAAA,kCCsFJ,0FD5FE,4DAEE,+BAAA,qCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCC+FJ,+FDrGE,iEAEE,+BAAA,qCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCCwGJ,wFD9GE,0DAEE,+BAAA,+BACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCCiHJ,0FDvHE,4DAEE,+BAAA,+BACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCC0HJ,8FDhIE,gEAEE,+BAAA,+BACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCCmIJ,wFDzIE,0DAEE,+BAAA,mCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCC4IJ,wFDlJE,0DAEE,+BAAA,mCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCCqJJ,yFD3JE,2DAEE,+BAAA,mCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCC8JJ,+FDpKE,iEAEE,+BAAA,mCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCCuKJ,wFD7KE,0DAEE,+BAAA,mCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCCgLJ,0FDtLE,4DAEE,+BAAA,kCACA,qBAAA,yBACA,kCAAA,2BACA,qBAAA,2BACA,4BAAA,kCCyLJ,yFD/LE,2DAEE,+BAAA,kCACA,qBAAA,yBACA,kCAAA,2BACA,qBAAA,2BACA,4BAAA,kCCkMJ,0FDxME,4DAEE,+BAAA,mCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCC2MJ,+FDjNE,iEAEE,+BAAA,mCACA,qBAAA,0BACA,kCAAA,4BACA,qBAAA,2BACA,4BAAA,kCExMJ,MACE,WAAA,QACA,eAAA,QAEA,qBACE,cAAA,MAIF,qCACE,WAAA,oBACA,eAAA,kBAMA,eACE,OAAA,IAAA,EAAA,IAGF,0BACI,SAAA,SACA,IAAA,OACA,MAAA,MACA,MAAA,oCACA,WAAA,MAAA,MAEA,gCACE,MAAA,0BAGF,mCACI,OAAA,OAEA,uCACI,MAAA,OACA,OAAA,OAKZ,iDACE,WAAA,MAMF,yBAAA,+BACE,SAAA,SACA,MAAA,gBACA,UAAA,MAAA,KAAA,KAAA,SAKN,iBACE,GAAK,UAAA,SACL,IAAM,MAAA,oBAA4B,UAAA,WAClC,IAAM,UAAA,WACN,IAAM,MAAA,oBAA4B,UAAA,WAClC,KAAO,UAAA,UAGT,mBACE,WAAA,OAEA,sBACE,QAAA,aACA,MAAA,OACA,OAAA,EAAA,MACA,eAAA,OACA,cAAA,IAAA,MAAA,oCAIA,4BACI,aAAA,0BAKJ,8DACI,MAAA,8CAQJ,iGDgZJ,kGACA,mGC9YM,QAAA,KAMF,gGD4YJ,kGACA,mGC1YM,QAAA,KAKF,0IDyYJ,2IACA,4ICvYM,QAAA,KAKF,4DDsYJ,6DACA,+DCpYM,QAAA,KAKN,uBACE,QAAA,EAaF,kEACE,QAAA,KC5IF,wBAAA,oBACE,aAAA,EACA,kBAAA,IAwBF,QACE,yBAAA,YAEA,qCACE,2BAAA,0BAQA,QACE,+BAAA,+wBACA,mCAAA,uBACA,qCAAA,QACA,uCAAA,uBAGF,qCACE,mCAAA,uCACA,qCAAA,oBACA,uCAAA,0BAMA,QACE,+BAAA,uCACA,iCAAA,kBACA,mCAAA,kBAHF,QACE,mCAAA,uCACA,qCAAA,mBACA,uCAAA,mBAHF,QACE,+BAAA,uCACA,iCAAA,mBACA,mCAAA,mBAHF,QACE,8BAAA,uCACA,gCAAA,mBACA,kCAAA,mBAHF,QACE,kCAAA,uCACA,oCAAA,mBACA,sCAAA,mBAHF,QACE,mCAAA,uCACA,qCAAA,mBACA,uCAAA,mBAHF,QACE,kCAAA,uCACA,oCAAA,mBACA,sCAAA,mBAHF,QACE,kCAAA,uCACA,oCAAA,kBACA,sCAAA,kBAHF,QACE,iCAAA,uCACA,mCAAA,kBACA,qCAAA,kBAHF,QACE,8BAAA,uCACA,gCAAA,oBACA,kCAAA,oBAHF,QACE,kCAAA,uCACA,oCAAA,mBACA,sCAAA,mBAHF,QACE,gCAAA,uCACA,kCAAA,kBACA,oCAAA,kBAnBJ,QACE,0BAAA,4TACA,8BAAA,uBACA,gCAAA,QACA,kCAAA,uBAGF,qCACE,8BAAA,uCACA,gCAAA,kBACA,kCAAA,wBAMA,QACE,+BAAA,uCACA,iCAAA,kBACA,mCAAA,kBAHF,QACE,mCAAA,uCACA,qCAAA,mBACA,uCAAA,mBAHF,QACE,+BAAA,uCACA,iCAAA,mBACA,mCAAA,mBAHF,QACE,8BAAA,uCACA,gCAAA,mBACA,kCAAA,mBAHF,QACE,kCAAA,uCACA,oCAAA,mBACA,sCAAA,mBAHF,QACE,mCAAA,uCACA,qCAAA,mBACA,uCAAA,mBAHF,QACE,kCAAA,uCACA,oCAAA,mBACA,sCAAA,mBAHF,QACE,kCAAA,uCACA,oCAAA,kBACA,sCAAA,kBAHF,QACE,iCAAA,uCACA,mCAAA,kBACA,qCAAA,kBAHF,QACE,8BAAA,uCACA,gCAAA,oBACA,kCAAA,oBAHF,QACE,kCAAA,uCACA,oCAAA,mBACA,sCAAA,mBAHF,QACE,gCAAA,uCACA,kCAAA,kBACA,oCAAA,kBAOR,uDAAA,mDACE,aAAA,sCACA,WAAA,oBAEA,oEAAA,gEACE,WAAA,EAAA,EAAA,EAAA,MAAA,wCAGF,yEAAA,qEAAA,2DACE,iBAAA,oCACA,iFAAA,6EAAA,mEACE,iBAAA,sCAEF,gFAAA,4EAAA,kEACE,MAAA,sCAaF,4DAAA,wDACE,aAAA,sCAEA,yEAAA,qEACE,WAAA,EAAA,EAAA,EAAA,MAAA,wCAIF,8EAAA,0EAAA,gEACE,iBAAA,oCACA,aAAA,sCAGA,sFAAA,kFAAA,wEACE,iBAAA,sCAEF,qFAAA,iFAAA,uEACE,MAAA,sCAjBN,gEAAA,4DACE,aAAA,0CAEA,6EAAA,yEACE,WAAA,EAAA,EAAA,EAAA,MAAA,4CAIF,kFAAA,8EAAA,oEACE,iBAAA,wCACA,aAAA,0CAGA,0FAAA,sFAAA,4EACE,iBAAA,0CAEF,yFAAA,qFAAA,2EACE,MAAA,0CAjBN,4DAAA,wDACE,aAAA,sCAEA,yEAAA,qEACE,WAAA,EAAA,EAAA,EAAA,MAAA,wCAIF,8EAAA,0EAAA,gEACE,iBAAA,oCACA,aAAA,sCAGA,sFAAA,kFAAA,wEACE,iBAAA,sCAEF,qFAAA,iFAAA,uEACE,MAAA,sCAjBN,2DAAA,uDACE,aAAA,qCAEA,wEAAA,oEACE,WAAA,EAAA,EAAA,EAAA,MAAA,uCAIF,6EAAA,yEAAA,+DACE,iBAAA,mCACA,aAAA,qCAGA,qFAAA,iFAAA,uEACE,iBAAA,qCAEF,oFAAA,gFAAA,sEACE,MAAA,qCAjBN,+DAAA,2DACE,aAAA,yCAEA,4EAAA,wEACE,WAAA,EAAA,EAAA,EAAA,MAAA,2CAIF,iFAAA,6EAAA,mEACE,iBAAA,uCACA,aAAA,yCAGA,yFAAA,qFAAA,2EACE,iBAAA,yCAEF,wFAAA,oFAAA,0EACE,MAAA,yCAjBN,gEAAA,4DACE,aAAA,0CAEA,6EAAA,yEACE,WAAA,EAAA,EAAA,EAAA,MAAA,4CAIF,kFAAA,8EAAA,oEACE,iBAAA,wCACA,aAAA,0CAGA,0FAAA,sFAAA,4EACE,iBAAA,0CAEF,yFAAA,qFAAA,2EACE,MAAA,0CAjBN,+DAAA,2DACE,aAAA,yCAEA,4EAAA,wEACE,WAAA,EAAA,EAAA,EAAA,MAAA,2CAIF,iFAAA,6EAAA,mEACE,iBAAA,uCACA,aAAA,yCAGA,yFAAA,qFAAA,2EACE,iBAAA,yCAEF,wFAAA,oFAAA,0EACE,MAAA,yCAjBN,+DAAA,2DACE,aAAA,yCAEA,4EAAA,wEACE,WAAA,EAAA,EAAA,EAAA,MAAA,2CAIF,iFAAA,6EAAA,mEACE,iBAAA,uCACA,aAAA,yCAGA,yFAAA,qFAAA,2EACE,iBAAA,yCAEF,wFAAA,oFAAA,0EACE,MAAA,yCAjBN,8DAAA,0DACE,aAAA,wCAEA,2EAAA,uEACE,WAAA,EAAA,EAAA,EAAA,MAAA,0CAIF,gFAAA,4EAAA,kEACE,iBAAA,sCACA,aAAA,wCAGA,wFAAA,oFAAA,0EACE,iBAAA,wCAEF,uFAAA,mFAAA,yEACE,MAAA,wCAjBN,2DAAA,uDACE,aAAA,qCAEA,wEAAA,oEACE,WAAA,EAAA,EAAA,EAAA,MAAA,uCAIF,6EAAA,yEAAA,+DACE,iBAAA,mCACA,aAAA,qCAGA,qFAAA,iFAAA,uEACE,iBAAA,qCAEF,oFAAA,gFAAA,sEACE,MAAA,qCAjBN,+DAAA,2DACE,aAAA,yCAEA,4EAAA,wEACE,WAAA,EAAA,EAAA,EAAA,MAAA,2CAIF,iFAAA,6EAAA,mEACE,iBAAA,uCACA,aAAA,yCAGA,yFAAA,qFAAA,2EACE,iBAAA,yCAEF,wFAAA,oFAAA,0EACE,MAAA,yCAjBN,6DAAA,yDACE,aAAA,uCAEA,0EAAA,sEACE,WAAA,EAAA,EAAA,EAAA,MAAA,yCAIF,+EAAA,2EAAA,iEACE,iBAAA,qCACA,aAAA,uCAGA,uFAAA,mFAAA,yEACE,iBAAA,uCAEF,sFAAA,kFAAA,wEACE,MAAA,uCAoBR,+BAAA,iCAAA,2BAAA,6BACE,aAAA,0CAEA,4CAAA,8CAAA,wCAAA,0CACE,WAAA,EAAA,EAAA,EAAA,MAAA,4CAGF,iDAAA,mDAAA,6CAAA,mCAAA,+CAAA,qCACE,iBAAA,wCACA,aAAA,0CAGA,yDAAA,2DAAA,qDAAA,2CAAA,uDAAA,6CACE,MAAA,KACA,OAAA,KACA,iBAAA,0CACA,gBAAA,KACA,mBAAA,oCAAA,WAAA,oCACA,QAAA,IAEF,wDAAA,0DAAA,oDAAA,0CAAA,sDAAA,4CACE,MAAA,0CArBN,4BAAA,wBACE,aAAA,qCAEA,yCAAA,qCACE,WAAA,EAAA,EAAA,EAAA,MAAA,uCAGF,8CAAA,0CAAA,gCACE,iBAAA,mCACA,aAAA,qCAGA,sDAAA,kDAAA,wCACE,MAAA,KACA,OAAA,KACA,iBAAA,qCACA,gBAAA,KACA,mBAAA,+BAAA,WAAA,+BACA,QAAA,IAEF,qDAAA,iDAAA,uCACE,MAAA,qCC3JR,4BACE,UAAA,eAGF,6BACE,UAAA,eHq7BF,yDADA,6DADA,uDG76BE,2DAEE,MAAA,KHk7BJ,8CACA,8CGj7BE,4CH+6BF,4CG76BI,WAAA,EAAA,KAAA,KAAA,eAKJ,wBACE,WAAA,eACA,WAAA,iBAKA,2BACE,QAAA,eACA,eAAA,IACA,UAAA,OACA,YAAA,SACA,gBAAA,cAGA,iCACE,QAAA,iBAGF,gCACE,SAAA,mBACA,QAAA,iBACA,YAAA,oBCrCF,uBJo9BJ,uBACA,wBIp9BM,QAAA,EAAA,MACA,MAAA,MACA,WAAA,KAIJ,0BACE,OAAA,ECXF,oBAGE,SAAA,OAOE,kCACE,cAAA,KCXN,eACE,MAAA,iCAGF,eNy+BF,eMt+BI,MAAA,8BAGF,eACE,MAAA,+BNy+BJ,eMt+BE,eAEE,MAAA,gCAGF,eACE,MAAA,kCAGF,eNo+BF,eACA,eMl+BI,MAAA,+BAEF,eNo+BF,eMl+BI,MAAA,4BAOF,2BACI,OAAA,EACA,QAAA,EAAA,cACA,MAAA,wBACA,iBAAA,+BACA,cAAA,YACA,WAAA,KAKF,mBACE,MAAA,kBACA,iBAAA,uCACA,WAAA,MAAA,MACA,WAAA,iBAAA,MAGA,qBACE,MAAA,oCAGF,yBACE,iBAAA,8CAEA,2BACE,MAAA,oCAMR,qBACE,QAAA,EAIF,oBACE,WAAA,OAGF,uBAGE,cAAA,EAAA,YAAA,EAAA,SAAA,EAEA,+BACE,aAAA,YAOA,sDACE,iBAAA,gCAQF,gDACE,aAAA,eACA,YAAA,gBACA,cAAA,cACA,aAAA,eACA,iBAAA,gCAMN,qCAGE,SAAA,SACA,QAAA,MACA,WAAA,IACA,QAAA,KAAA,eAAA,KAAA,eACA,YAAA,IACA,UAAA,eACA,iBAAA,8BACA,uBAAA,YACA,wBAAA,YAGA,yCACE,WAAA,EAEA,8CACE,uBAAA,EACA,wBAAA,EAKJ,6CACE,SAAA,SACA,KAAA,cACA,MAAA,eACA,OAAA,eACA,iBAAA,2BACA,mBAAA,uRAAA,WAAA,uRACA,oBAAA,UAAA,YAAA,UACA,kBAAA,QAAA,UAAA,QACA,QAAA,GAIJ,2BACE,SAAA,SACA,WAAA,IACA,cAAA,IAEA,+BACE,WAAA,EACA,cAAA,EAGF,iCACE,QAAA,KAEA,8CACE,MAAA,KACA,OAAA,EACA,QAAA,MAAA,KAAA,MAAA,EAEA,oDACE,SAAA,SACA,OAAA,MACA,QAAA,MAAA,KACA,MAAA,2BACA,UAAA,IACA,iBAAA,2BACA,oBAAA,UAAA,YAAA,UACA,kBAAA,QAAA,UAAA,QACA,cAAA,YACA,OAAA,QACA,QAAA,GAEA,0DACE,iBAAA,0BAGF,4DACE,SAAA,SACA,IAAA,MACA,KAAA,MACA,QAAA,MACA,WAAA,WACA,MAAA,OACA,OAAA,OACA,iBAAA,2BACA,gBAAA,OACA,QAAA,GAGF,2DACE,QAAA,KAEA,mEACE,mBAAA,oNAAA,WAAA,oNAGJ,qEACE,mBAAA,mNAAA,WAAA,mNAMJ,mEACE,QAAA,OAGF,qEACE,QAAA,KAGF,4DACE,WAAA,QACA,SAAA,OAGF,sDACE,SAAA,SACA,OAAA,EACA,KAAA,EACA,QAAA,IAAA,KAAA,KAAA,aACA,iBAAA,2EC3NJ,qCACE,cAAA,KACA,QAAA,IAFF,2CACE,cAAA,KACA,QAAA,ICZR,QACE,uBAAA,uOACA,wBAAA,0pBACA,2BAAA,qSACA,wBAAA,4pBACA,wBAAA,iSACA,yBAAA,mhBACA,sBAAA,yvBACA,uBAAA,sUACA,4BAAA,8xBAIA,8DACE,mBAAA,4BAAA,WAAA,4BRyrCJ,qDADA,sDAIA,yDADA,oDADA,mDQhrCI,yDRmrCJ,sDQlrCM,SAAA,SACA,aAAA,QRurCN,6DADA,8DAIA,iEADA,4DADA,2DQtrCM,iERyrCN,8DQxrCQ,SAAA,SACA,IAAA,EACA,KAAA,EACA,QAAA,MACA,WAAA,WACA,MAAA,OACA,OAAA,OACA,iBAAA,0BACA,gBAAA,OACA,WAAA,iBAAA,MACA,oBAAA,UAAA,YAAA,UACA,kBAAA,QAAA,UAAA,QACA,QAAA,GR+rCR,mEADA,oEAIA,uEADA,kEADA,iEQ7rCM,uERgsCN,oEQ/rCQ,iBAAA,0BAgBF,6DACE,mBAAA,6BAAA,WAAA,6BADF,8DACE,mBAAA,8BAAA,WAAA,8BADF,2DACE,mBAAA,2BAAA,WAAA,2BADF,4DACE,mBAAA,4BAAA,WAAA,4BADF,iEACE,mBAAA,iCAAA,WAAA,iCAcF,kFACE,mBAAA,6BAAA,WAAA,6BADF,kFACE,mBAAA,6BAAA,WAAA,6BADF,qFACE,mBAAA,gCAAA,WAAA,gCC/ER,8BACE,WAAA,KCIA,4BACE,SAAA,SACA,MAAA,KACA,OAAA,EACA,MAAA,qBACA,YAAA,IACA,YAAA,OACA,YAAA,OACA,WAAA,OACA,YAAA,SAAA,SAAA,OAAA,iCAAA,CAAA,QAAA,SAAA,OAAA,iCAAA,CAAA,SAAA,QAAA,OAAA,iCAAA,CAAA,QAAA,QAAA,OAAA,kCAOF,0BACE,MAAA,KACA,OAAA,OACA,iBAAA,QAKA,+CACE,UAAA,gBAAA,GAAA,OAAA,SAIJ,sBACE,SAAA,SACA,QAAA,MACA,MAAA,KACA,OAAA,OACA,OAAA,MAAA,EACA,iBAAA,qCAEA,2BACE,OAAA,MACA,WAAA,MAEA,2CACE,WAAA,OAGF,yCACE,OAAA,MAIJ,gDACE,iBAAA,8KAWA,gBAAA,KAAA,KAaA,4CACE,iBAAA,uBADF,2CACE,iBAAA,sBADF,2CACE,iBAAA,sBADF,2CACE,iBAAA,sBADF,2CACE,iBAAA,sBADF,0CACE,iBAAA,qBAKN,2BACE,GACE,oBAAA,EAAA,EAGF,KACE,oBAAA,KAAA,GCvFF,sEACE,WAAA,EAAA,QAAA,oCAAA,MASF,yDACE,MAAA,KAEA,iEACE,MAAA,OACA,QAAA,EAIJ,uEACE,QAAA,EAAA,MXg2CN,8FACA,mGACA,6FACA,kGW11CU,sFACE,aAAA,QACA,YAAA,QACA,cAAA,MACA,aAAA,MX61CZ,4GACA,iHACA,2GACA,gHW91CY,oGACE,WAAA,EAKN,iGACE,WAAA,EAEA,aAAA,QACA,YAAA,QACA,cAAA,MACA,aAAA,MAEA,8GACE,KAAA,MAIJ,8FACE,aAAA,QACA,YAAA,QACA,cAAA,MACA,aAAA,MAOV,uCACE,iBAAA,0BCpEA,8DACE,WAAA,oBAEA,uEACE,iBAAA,gBAGF,iEACE,MAAA,qBACA,iBAAA,uCACA,cAAA,OAAA,MAAA,2BAGF,iEACE,WAAA,OAAA,MAAA,oCCbF,2FACC,iBAAA,oCAGD,mHACC,iBAAA,QCNH,wBACE,MAAA,IACA,OAAA,IACA,eAAA,OACA,iBAAA,oCACA,gBAAA,IACA,kBAAA,IAAA,UAAA,IACA,oBAAA,UAAA,YAAA,UACA,WAAA,QACA,mBAAA,kUAAA,WAAA,kUAGF,8Bdu7CF,oCcr7CI,iBAAA,0BCjBJ,YACE,SAAA,KCCF,KACE,iBAAA,YAGF,sCACE,MAAA,2BAIF,+BAEE,gBAAA,2BACA,iBAAA,2BAGA,qBAAA,YACA,2BAAA,oCAGA,qBAAA,qBACA,qBAAA,oCAGA,0CACE,MAAA,qBACA,iBAAA,0BACA,cAAA,OAAA,MAAA,2BAEA,gEACI,WAAA,EAAA,EAAA,MAAA,eAAA,CAAA,EAAA,EAAA,MAAA,MAAA,eAKN,uCACE,iBAAA,iCAEA,6CACE,iBAAA,2BAKJ,wCACE,MAAA,qBACA,iBAAA,wCAEA,sDACI,MAAA,2BAGJ,oDACI,MAAA,0BAKN,wCACE,MAAA,qBACA,iBAAA,wCAIF,+CACE,MAAA,qBAGF,iEACE,MAAA,kCAGF,mEACE,MAAA,2BAIA,mDAAA,mDAEE,MAAA,0BAkCJ,iDACE,MAAA,qBACA,iBAAA,iCAEA,uDACE,iBAAA,kCAGF,kEACE,MAAA,qBAEF,mEACE,MAAA,kCADF,8DACE,MAAA,kCAIJ,4FACE,iBAAA,YAGF,mDACE,MAAA,wCAGF,2CAAA,mDACE,iBAAA,kCAKA,yDACE,MAAA,2BAGF,+CACE,WAAA,OAAA,MAAA,2BAKJ,4DACE,iBAAA,uCAOF,eACE,MAAA,qBACA,eAAA,KhBi5CJ,uBADA,wBAMA,wBAEA,2BAJA,wBADA,wBAEA,wBAEA,2BALA,qBgB94CA,wBAWE,gBAAA,oCAAA,YACA,gBAAA,KhB84CF,6BADA,8BAMA,8BAEA,iCAJA,8BADA,8BAEA,8BAEA,iCALA,2BgB54CE,8BACE,gBAAA,0BAAA,YhBs5CJ,0CADA,2CAMA,2CAEA,8CAJA,2CADA,2CAEA,2CAEA,8CALA,wCgBn5CE,2CACE,MAAA,MACA,OAAA,MhB65CJ,iDADA,kDAMA,kDAEA,qDAJA,kDADA,kDAEA,kDAEA,qDALA,+CgB35CE,kDACE,iBAAA,YhBq6CJ,gDADA,iDAMA,iDAEA,oDAJA,iDADA,iDAEA,iDAEA,oDALA,8CgBl6CE,iDACE,iBAAA,oChB46CJ,sDADA,uDAMA,uDAEA,0DAJA,uDADA,uDAEA,uDAEA,0DALA,oDgB16CI,uDACE,iBAAA,0BCoBF,wChBxFF,uBACE,cAAA,EAGF,oBACE,aAAA,EevCA,+CACE,MAAA,qBACA,iBAAA,wCAGF,sDACE,MAAA,qBACA,iBAAA,0BACA,cAAA,OAAA,MAAA,4BCkHF,wCXoBE,wBACE,aAAA,cACA,YAAA,cAEF,2BACE,aAAA,cACA,YAAA,cAEA,0CACE,KAAA,aKhLR,wDACE,aAAA,EAGF,8CACE,UAAA,KACA,OAAA,EACA,qBAAA,EACA,4BAAA,EAEA,qDACE,mBAAA,EACA,QAAA,KAIF,oEACE,oBAAA,EACA,qBAAA,EAIF,oEACE,kBAAA,EACA,mBAAA,GM2HF,wCDzIA,gGACE,MAAA,2BAIF,+DACE,MAAA,qBACA,iBAAA,0BACA,cAAA,OAAA,MAAA","file":"extra-add764b01e.css","sourcesContent":["@use \"sass:color\";\n@use \"../utilities/convert\";\n@use \"../utilities/color_tools\";\n@use \"./material_color\";\n@use \"./dracula\";\n@use \"sass:list\";\n\n:root > * {\n // Custom code colors\n --md-code-link-bg-color: hsla(0, 0%, 96%, 1);\n --md-code-link-accent-bg-color: var(--md-code-link-bg-color);\n --md-default-bg-color--trans: rgb(100%, 100%, 100%, 0);\n --md-code-title-bg-color: var(--md-code-bg-color);\n --md-code-inline-bg-color: var(--md-code-bg-color);\n\n --md-code-special-bg-color: #{color.adjust(hsl(0, 0%, 96%), $lightness: -5%)};\n --md-code-alternate-bg-color: var(--md-code-bg-color);\n\n --md-code-hl-punctuation-color: var(--md-code-fg-color);\n --md-code-hl-namespace-color: var(--md-code-fg-color);\n\n --md-code-hl-entity-color: var(--md-code-hl-keyword-color);\n --md-code-hl-tag-color: var(--md-code-hl-keyword-color);\n --md-code-hl-builtin-color: var(--md-code-hl-constant-color);\n --md-code-hl-class-color: var(--md-code-hl-function-color);\n\n // Various Material related color variables\n --md-typeset-a-color: #{material_color.$clr-cyan-500};\n\n // Progressbar colors\n --md-progress-stripe: var(--md-default-bg-color--lighter);\n --md-progress-100: #{material_color.$clr-green-a400};\n --md-progress-80: #{material_color.$clr-green-a400};\n --md-progress-60: #{material_color.$clr-yellow-700};\n --md-progress-40: #{material_color.$clr-orange-a400};\n --md-progress-20: #{material_color.$clr-red-a200};\n --md-progress-0: #{material_color.$clr-red-a400};\n\n // Keys colors\n --md-typeset-kbd-color: #{color_tools.shade(hsla(0, 100%, 100%, 1), 8%)};\n --md-typeset-kbd-border-color: #{color_tools.shade(hsla(0, 100%, 100%, 1), 28%)};\n --md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);\n\n &[data-md-color-scheme=\"slate\"] {\n // Custom code colors\n --md-code-link-bg-color: hsla(232, 15%, 15%, 1);\n --md-code-link-accent-bg-color: var(--md-code-link-bg-color);\n --md-code-special-bg-color: #{color.adjust(hsl(232, 15%, 15%), $lightness: 5%)};\n --md-default-bg-color--trans: hsla(232,15%,15%, 0);\n\n // Keys colors\n --md-typeset-kbd-color: var(--md-default-fg-color--lightest);\n --md-typeset-kbd-border-color: #{color.adjust(rgb(46, 48, 62), $lightness: -9%)};\n --md-typeset-kbd-accent-color: var(--md-default-fg-color--lighter);\n }\n\n // Dark mode color changes\n &[data-md-color-scheme=\"dracula\"] {\n // Default color shades\n --md-default-fg-color: #{color.adjust(dracula.$drac-fg, $alpha: -0.13)};\n --md-default-fg-color--light: #{color.adjust(dracula.$drac-fg, $alpha: -0.46)};\n --md-default-fg-color--lighter: #{color.adjust(dracula.$drac-fg, $alpha: -0.84)};\n --md-default-fg-color--lightest: #{color.adjust(dracula.$drac-fg, $alpha: -0.93)};\n --md-default-autocomplete-fg-color: #{color.adjust(dracula.$drac-fg, $alpha: -0.60)};\n --md-shadow-z2: 0 #{convert.px2rem(4px)} #{convert.px2rem(10px)} hsla(0, 0%, 0%, 0.3),\n 0 0 #{convert.px2rem(1px)} hsla(0, 0%, 0%, 0.2);\n\n --md-default-bg-color: var(--md-default-bg-color--darkest);\n --md-default-bg-color--light: #{color.adjust(dracula.$drac-default-bg, $alpha: -0.3)};\n --md-default-bg-color--lighter: #{color.adjust(dracula.$drac-default-bg, $alpha: -0.7)};\n --md-default-bg-color--lightest: #{color.adjust(dracula.$drac-default-bg, $alpha: -0.88)};\n --md-default-bg-color--trans: #{color.adjust(dracula.$drac-default-bg, $alpha: -1)};\n\n // Dark specific colors\n --md-default-bg-color--dark: #{color.adjust(dracula.$drac-default-bg, $lightness: -3%)};\n --md-default-bg-color--darker: #{color.adjust(dracula.$drac-default-bg, $lightness: -6%)};\n --md-default-bg-color--darkest: #{color.adjust(dracula.$drac-default-bg, $lightness: -9%)};\n --md-default-bg-color--ultra-dark: #{color.adjust(dracula.$drac-default-bg, $lightness: -15%)};\n\n // General text\n --md-text-color: var(--md-default-fg-color);\n --md-typeset-color: var(--md-default-fg-color);\n\n // Admonition colors\n --md-admonition-fg-color: var(--md-default-fg-color);\n\n // Code colors\n --md-code-fg-color: #{dracula.$drac-fg};\n --md-code-bg-color: #{dracula.$drac-bg};\n --md-code-title-bg-color: var(--md-default-bg-color--ultra-dark);\n --md-code-inline-bg-color: #{color.adjust(dracula.$drac-bg, $lightness: 5%)};\n --md-code-hl-operator-color: #{dracula.$drac-pink};\n --md-code-hl-punctuation-color: #{dracula.$drac-fg};\n --md-code-hl-string-color: #{dracula.$drac-yellow};\n --md-code-hl-special-color: #{dracula.$drac-purple};\n --md-code-hl-number-color: #{dracula.$drac-purple};\n --md-code-hl-keyword-color: #{dracula.$drac-pink};\n --md-code-hl-name-color: #{dracula.$drac-fg};\n --md-code-hl-constant-color: #{dracula.$drac-purple};\n --md-code-hl-function-color: #{dracula.$drac-green};\n --md-code-hl-comment-color: #{dracula.$drac-blue};\n --md-code-hl-variable-color: #{dracula.$drac-orange};\n --md-code-hl-generic-color: #{dracula.$drac-blue};\n --md-code-hl-color: #{dracula.$drac-selection};\n\n // Custom code colors\n --md-code-hl-entity-color: #{dracula.$drac-green};\n --md-code-hl-tag-color: #{dracula.$drac-pink};\n --md-code-hl-namespace-color: #{dracula.$drac-fg};\n --md-code-hl-builtin-color: #{dracula.$drac-cyan};\n --md-code-hl-class-color: #{dracula.$drac-cyan};\n\n --md-code-special-bg-color: #{color.adjust(dracula.$drac-bg, $lightness: -5%)};\n --md-code-alternate-bg-color: #{color_tools.tint(dracula.$drac-bg, 10%)};\n --md-code-link-bg-color: #{color.mix(dracula.$drac-cyan, dracula.$drac-bg, 15%)};\n\n // Various Material related color variables\n --md-typeset-a-color: #{dracula.$drac-cyan};\n --md-typeset-mark-color: #{color.mix(dracula.$drac-yellow, dracula.$drac-bg, 35%)};\n --md-typeset-del-color: #{color.mix(dracula.$drac-pink, dracula.$drac-bg, 35%)};\n --md-typeset-ins-color: #{color.mix(dracula.$drac-green, dracula.$drac-bg, 35%)};\n\n // Progressbar colors\n --md-progress-stripe: var(--md-default-bg-color--lightest);\n --md-progress-100: #{dracula.$drac-green};\n --md-progress-80: #{dracula.$drac-light-green};\n --md-progress-60: #{dracula.$drac-yellow};\n --md-progress-40: #{dracula.$drac-orange};\n --md-progress-20: #{dracula.$drac-pink};\n --md-progress-0: #{dracula.$drac-red};\n\n // Keys colors\n --md-typeset-kbd-color: var(--md-default-fg-color--lightest);\n --md-typeset-kbd-border-color: var(--md-default-bg-color--ultra-dark);\n --md-typeset-kbd-accent-color: var(--md-default-fg-color--lighter);\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: primary colors\n// ----------------------------------------------------------------------------\n\n@each $name, $colors in (\n \"red\": dracula.$drac-red color.adjust(dracula.$drac-red, $lightness: 5%) color.adjust(dracula.$drac-red, $lightness: -5%),\n \"pink\": dracula.$drac-pink color.adjust(dracula.$drac-pink, $lightness: 5%) color.adjust(dracula.$drac-pink, $lightness: -5%),\n \"purple\": dracula.$drac-purple color.adjust(dracula.$drac-purple, $lightness: 5%) color.adjust(dracula.$drac-purple, $lightness: -5%),\n \"deep-purple\": dracula.$drac-purple color.adjust(dracula.$drac-purple, $lightness: 5%) color.adjust(dracula.$drac-purple, $lightness: -5%),\n \"blue\": dracula.$drac-blue color.adjust(dracula.$drac-blue, $lightness: 5%) color.adjust(dracula.$drac-blue, $lightness: -5%),\n \"indigo\": dracula.$drac-blue color.adjust(dracula.$drac-blue, $lightness: 5%) color.adjust(dracula.$drac-blue, $lightness: -5%),\n \"light-blue\": dracula.$drac-blue color.adjust(dracula.$drac-blue, $lightness: 5%) color.adjust(dracula.$drac-blue, $lightness: -5%),\n \"cyan\": dracula.$drac-cyan color.adjust(dracula.$drac-cyan, $lightness: 5%) color.adjust(dracula.$drac-cyan, $lightness: -5%),\n \"teal\": dracula.$drac-cyan color.adjust(dracula.$drac-cyan, $lightness: 5%) color.adjust(dracula.$drac-cyan, $lightness: -5%),\n \"green\": dracula.$drac-green color.adjust(dracula.$drac-green, $lightness: 5%) color.adjust(dracula.$drac-green, $lightness: -5%),\n \"light-green\": dracula.$drac-green color.adjust(dracula.$drac-green, $lightness: 5%) color.adjust(dracula.$drac-green, $lightness: -5%),\n \"lime\": dracula.$drac-green color.adjust(dracula.$drac-green, $lightness: 5%) color.adjust(dracula.$drac-green, $lightness: -5%),\n \"yellow\": dracula.$drac-yellow color.adjust(dracula.$drac-yellow, $lightness: 5%) color.adjust(dracula.$drac-yellow, $lightness: -5%),\n \"amber\": dracula.$drac-yellow color.adjust(dracula.$drac-yellow, $lightness: 5%) color.adjust(dracula.$drac-yellow, $lightness: -5%),\n \"orange\": dracula.$drac-orange color.adjust(dracula.$drac-orange, $lightness: 5%) color.adjust(dracula.$drac-orange, $lightness: -5%),\n \"deep-orange\": dracula.$drac-orange color.adjust(dracula.$drac-orange, $lightness: 5%) color.adjust(dracula.$drac-orange, $lightness: -5%)\n) {\n\n // Color palette\n [data-md-color-scheme=\"dracula\"][data-md-color-primary=\"#{$name}\"],\n [data-md-color-scheme=\"dracula\"] :not([data-md-color-scheme])[data-md-color-primary=\"#{$name}\"]\n {\n\n --md-primary-code-bg-color: #{color.mix(dracula.$drac-bg, list.nth($colors, 1), 85%)};\n --md-primary-fg-color: hsla(#{convert.hex2hsl(list.nth($colors, 1))}, 1);\n --md-primary-fg-color--transparent: hsla(#{convert.hex2hsl(list.nth($colors, 1))}, 0.1);\n --md-primary-fg-color--light: hsla(#{convert.hex2hsl(list.nth($colors, 2))}, 1);\n --md-primary-fg-color--dark: hsla(#{convert.hex2hsl(list.nth($colors, 3))}, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: accent colors\n// ----------------------------------------------------------------------------\n\n@each $name, $color in (\n \"red\": color.adjust(dracula.$drac-red, $lightness: -5%),\n \"pink\": color.adjust(dracula.$drac-pink, $lightness: -5%),\n \"purple\": color.adjust(dracula.$drac-purple, $lightness: -5%),\n \"deep-purple\": color.adjust(dracula.$drac-purple, $lightness: -5%),\n \"blue\": color.adjust(dracula.$drac-blue, $lightness: -5%),\n \"indigo\": color.adjust(dracula.$drac-blue, $lightness: -5%),\n \"light-blue\": color.adjust(dracula.$drac-blue, $lightness: -5%),\n \"cyan\": color.adjust(dracula.$drac-cyan, $lightness: -5%),\n \"teal\": color.adjust(dracula.$drac-cyan, $lightness: -5%),\n \"green\": color.adjust(dracula.$drac-green, $lightness: -5%),\n \"light-green\": color.adjust(dracula.$drac-green, $lightness: -5%),\n \"lime\": color.adjust(dracula.$drac-green, $lightness: -5%),\n \"yellow\": color.adjust(dracula.$drac-yellow, $lightness: -5%),\n \"amber\": color.adjust(dracula.$drac-yellow, $lightness: -5%),\n \"orange\": color.adjust(dracula.$drac-orange, $lightness: -5%),\n \"deep-orange\": color.adjust(dracula.$drac-orange, $lightness: -5%)\n) {\n\n // Color palette\n [data-md-color-scheme=\"dracula\"][data-md-color-accent=\"#{$name}\"],\n [data-md-color-scheme=\"dracula\"] :not([data-md-color-scheme])[data-md-color-primary=\"#{$name}\"] {\n --md-code-link-accent-bg-color: #{color.mix($color, dracula.$drac-bg, 15%)};\n --md-accent-fg-color: hsla(#{convert.hex2hsl($color)}, 1);\n --md-accent-fg-color--transparent: hsla(#{convert.hex2hsl($color)}, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n }\n}\n","@charset \"UTF-8\";\n:root > * {\n --md-code-link-bg-color: hsla(0, 0%, 96%, 1);\n --md-code-link-accent-bg-color: var(--md-code-link-bg-color);\n --md-default-bg-color--trans: rgb(100%, 100%, 100%, 0);\n --md-code-title-bg-color: var(--md-code-bg-color);\n --md-code-inline-bg-color: var(--md-code-bg-color);\n --md-code-special-bg-color: hsl(0, 0%, 91%);\n --md-code-alternate-bg-color: var(--md-code-bg-color);\n --md-code-hl-punctuation-color: var(--md-code-fg-color);\n --md-code-hl-namespace-color: var(--md-code-fg-color);\n --md-code-hl-entity-color: var(--md-code-hl-keyword-color);\n --md-code-hl-tag-color: var(--md-code-hl-keyword-color);\n --md-code-hl-builtin-color: var(--md-code-hl-constant-color);\n --md-code-hl-class-color: var(--md-code-hl-function-color);\n --md-typeset-a-color: #00bcd4;\n --md-progress-stripe: var(--md-default-bg-color--lighter);\n --md-progress-100: #00e676;\n --md-progress-80: #00e676;\n --md-progress-60: #fbc02d;\n --md-progress-40: #ff9100;\n --md-progress-20: #ff5252;\n --md-progress-0: #ff1744;\n --md-typeset-kbd-color: rgb(234.6, 234.6, 234.6);\n --md-typeset-kbd-border-color: rgb(183.6, 183.6, 183.6);\n --md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);\n}\n:root > *[data-md-color-scheme=slate] {\n --md-code-link-bg-color: hsla(232, 15%, 15%, 1);\n --md-code-link-accent-bg-color: var(--md-code-link-bg-color);\n --md-code-special-bg-color: hsl(232, 15%, 20%);\n --md-default-bg-color--trans: hsla(232,15%,15%, 0);\n --md-typeset-kbd-color: var(--md-default-fg-color--lightest);\n --md-typeset-kbd-border-color: rgb(26.45, 27.6, 35.65);\n --md-typeset-kbd-accent-color: var(--md-default-fg-color--lighter);\n}\n:root > *[data-md-color-scheme=dracula] {\n --md-default-fg-color: hsla(60, 30%, 96%, 0.87);\n --md-default-fg-color--light: hsla(60, 30%, 96%, 0.54);\n --md-default-fg-color--lighter: hsla(60, 30%, 96%, 0.16);\n --md-default-fg-color--lightest: hsla(60, 30%, 96%, 0.07);\n --md-default-autocomplete-fg-color: hsla(60, 30%, 96%, 0.4);\n --md-shadow-z2: 0 0.2rem 0.5rem hsla(0, 0%, 0%, 0.3),\n 0 0 0.05rem hsla(0, 0%, 0%, 0.2);\n --md-default-bg-color: var(--md-default-bg-color--darkest);\n --md-default-bg-color--light: hsla(231, 15%, 23%, 0.7);\n --md-default-bg-color--lighter: hsla(231, 15%, 23%, 0.3);\n --md-default-bg-color--lightest: hsla(231, 15%, 23%, 0.12);\n --md-default-bg-color--trans: hsla(231, 15%, 23%, 0);\n --md-default-bg-color--dark: hsl(231, 15%, 20%);\n --md-default-bg-color--darker: hsl(231, 15%, 17%);\n --md-default-bg-color--darkest: hsl(231, 15%, 14%);\n --md-default-bg-color--ultra-dark: hsl(231, 15%, 8%);\n --md-text-color: var(--md-default-fg-color);\n --md-typeset-color: var(--md-default-fg-color);\n --md-admonition-fg-color: var(--md-default-fg-color);\n --md-code-fg-color: hsl(60, 30%, 96%);\n --md-code-bg-color: hsl(231, 15%, 18%);\n --md-code-title-bg-color: var(--md-default-bg-color--ultra-dark);\n --md-code-inline-bg-color: hsl(231, 15%, 23%);\n --md-code-hl-operator-color: hsl(326, 100%, 74%);\n --md-code-hl-punctuation-color: hsl(60, 30%, 96%);\n --md-code-hl-string-color: hsl(65, 92%, 76%);\n --md-code-hl-special-color: hsl(265, 89%, 78%);\n --md-code-hl-number-color: hsl(265, 89%, 78%);\n --md-code-hl-keyword-color: hsl(326, 100%, 74%);\n --md-code-hl-name-color: hsl(60, 30%, 96%);\n --md-code-hl-constant-color: hsl(265, 89%, 78%);\n --md-code-hl-function-color: hsl(135, 94%, 65%);\n --md-code-hl-comment-color: hsl(225, 27%, 51%);\n --md-code-hl-variable-color: hsl(31, 100%, 71%);\n --md-code-hl-generic-color: hsl(225, 27%, 51%);\n --md-code-hl-color: hsl(231, 25%, 25%);\n --md-code-hl-entity-color: hsl(135, 94%, 65%);\n --md-code-hl-tag-color: hsl(326, 100%, 74%);\n --md-code-hl-namespace-color: hsl(60, 30%, 96%);\n --md-code-hl-builtin-color: hsl(191, 97%, 77%);\n --md-code-hl-class-color: hsl(191, 97%, 77%);\n --md-code-special-bg-color: hsl(231, 15%, 13%);\n --md-code-alternate-bg-color: rgb(60.6135, 62.47245, 73.0065);\n --md-code-link-bg-color: rgb(54.081675, 69.7755225, 82.853325);\n --md-typeset-a-color: hsl(191, 97%, 77%);\n --md-typeset-mark-color: rgb(109.61175, 114.238725, 82.43385);\n --md-typeset-del-color: rgb(114.60975, 69.542325, 103.44925);\n --md-typeset-ins-color: rgb(54.009, 114.078075, 77.641125);\n --md-progress-stripe: var(--md-default-bg-color--lightest);\n --md-progress-100: hsl(135, 94%, 65%);\n --md-progress-80: hsl(135, 92%, 79%);\n --md-progress-60: hsl(65, 92%, 76%);\n --md-progress-40: hsl(31, 100%, 71%);\n --md-progress-20: hsl(326, 100%, 74%);\n --md-progress-0: hsl(0, 100%, 67%);\n --md-typeset-kbd-color: var(--md-default-fg-color--lightest);\n --md-typeset-kbd-border-color: var(--md-default-bg-color--ultra-dark);\n --md-typeset-kbd-accent-color: var(--md-default-fg-color--lighter);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=red],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=red] {\n --md-primary-code-bg-color: rgb(71.41275, 47.923425, 57.87225);\n --md-primary-fg-color: hsla(0deg, 100%, 67%, 1);\n --md-primary-fg-color--transparent: hsla(0deg, 100%, 67%, 0.1);\n --md-primary-fg-color--light: hsla(0deg, 100%, 72%, 1);\n --md-primary-fg-color--dark: hsla(0deg, 100%, 62%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=pink],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=pink] {\n --md-primary-code-bg-color: rgb(71.41275, 53.278425, 74.49825);\n --md-primary-fg-color: hsla(326deg, 100%, 74%, 1);\n --md-primary-fg-color--transparent: hsla(326deg, 100%, 74%, 0.1);\n --md-primary-fg-color--light: hsla(326deg, 100%, 79%, 1);\n --md-primary-fg-color--dark: hsla(326deg, 100%, 69%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=purple],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=purple] {\n --md-primary-code-bg-color: rgb(61.749525, 57.264075, 82.1916);\n --md-primary-fg-color: hsla(265deg, 89%, 78%, 1);\n --md-primary-fg-color--transparent: hsla(265deg, 89%, 78%, 0.1);\n --md-primary-fg-color--light: hsla(265deg, 89%, 83%, 1);\n --md-primary-fg-color--dark: hsla(265deg, 89%, 73%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=deep-purple],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-purple] {\n --md-primary-code-bg-color: rgb(61.749525, 57.264075, 82.1916);\n --md-primary-fg-color: hsla(265deg, 89%, 78%, 1);\n --md-primary-fg-color--transparent: hsla(265deg, 89%, 78%, 0.1);\n --md-primary-fg-color--light: hsla(265deg, 89%, 83%, 1);\n --md-primary-fg-color--dark: hsla(265deg, 89%, 73%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=blue],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=blue] {\n --md-primary-code-bg-color: rgb(47.609775, 51.8956875, 69.435225);\n --md-primary-fg-color: hsla(225deg, 27%, 51%, 1);\n --md-primary-fg-color--transparent: hsla(225deg, 27%, 51%, 0.1);\n --md-primary-fg-color--light: hsla(225deg, 27%, 56%, 1);\n --md-primary-fg-color--dark: hsla(225deg, 27%, 46%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=indigo],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=indigo] {\n --md-primary-code-bg-color: rgb(47.609775, 51.8956875, 69.435225);\n --md-primary-fg-color: hsla(225deg, 27%, 51%, 1);\n --md-primary-fg-color--transparent: hsla(225deg, 27%, 51%, 0.1);\n --md-primary-fg-color--light: hsla(225deg, 27%, 56%, 1);\n --md-primary-fg-color--dark: hsla(225deg, 27%, 46%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=light-blue],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-blue] {\n --md-primary-code-bg-color: rgb(47.609775, 51.8956875, 69.435225);\n --md-primary-fg-color: hsla(225deg, 27%, 51%, 1);\n --md-primary-fg-color--transparent: hsla(225deg, 27%, 51%, 0.1);\n --md-primary-fg-color--light: hsla(225deg, 27%, 56%, 1);\n --md-primary-fg-color--dark: hsla(225deg, 27%, 46%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=cyan],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=cyan] {\n --md-primary-code-bg-color: rgb(54.081675, 69.7755225, 82.853325);\n --md-primary-fg-color: hsla(191deg, 97%, 77%, 1);\n --md-primary-fg-color--transparent: hsla(191deg, 97%, 77%, 0.1);\n --md-primary-fg-color--light: hsla(191deg, 97%, 82%, 1);\n --md-primary-fg-color--dark: hsla(191deg, 97%, 72%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=teal],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=teal] {\n --md-primary-code-bg-color: rgb(54.081675, 69.7755225, 82.853325);\n --md-primary-fg-color: hsla(191deg, 97%, 77%, 1);\n --md-primary-fg-color--transparent: hsla(191deg, 97%, 77%, 0.1);\n --md-primary-fg-color--light: hsla(191deg, 97%, 82%, 1);\n --md-primary-fg-color--dark: hsla(191deg, 97%, 72%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=green],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=green] {\n --md-primary-code-bg-color: rgb(45.441, 72.365175, 63.437625);\n --md-primary-fg-color: hsla(135deg, 94%, 65%, 1);\n --md-primary-fg-color--transparent: hsla(135deg, 94%, 65%, 0.1);\n --md-primary-fg-color--light: hsla(135deg, 94%, 70%, 1);\n --md-primary-fg-color--dark: hsla(135deg, 94%, 60%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=light-green],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-green] {\n --md-primary-code-bg-color: rgb(45.441, 72.365175, 63.437625);\n --md-primary-fg-color: hsla(135deg, 94%, 65%, 1);\n --md-primary-fg-color--transparent: hsla(135deg, 94%, 65%, 0.1);\n --md-primary-fg-color--light: hsla(135deg, 94%, 70%, 1);\n --md-primary-fg-color--dark: hsla(135deg, 94%, 60%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=lime],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=lime] {\n --md-primary-code-bg-color: rgb(45.441, 72.365175, 63.437625);\n --md-primary-fg-color: hsla(135deg, 94%, 65%, 1);\n --md-primary-fg-color--transparent: hsla(135deg, 94%, 65%, 0.1);\n --md-primary-fg-color--light: hsla(135deg, 94%, 70%, 1);\n --md-primary-fg-color--dark: hsla(135deg, 94%, 60%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=yellow],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=yellow] {\n --md-primary-code-bg-color: rgb(69.27075, 72.434025, 65.49165);\n --md-primary-fg-color: hsla(65deg, 92%, 76%, 1);\n --md-primary-fg-color--transparent: hsla(65deg, 92%, 76%, 0.1);\n --md-primary-fg-color--light: hsla(65deg, 92%, 81%, 1);\n --md-primary-fg-color--dark: hsla(65deg, 92%, 71%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=amber],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=amber] {\n --md-primary-code-bg-color: rgb(69.27075, 72.434025, 65.49165);\n --md-primary-fg-color: hsla(65deg, 92%, 76%, 1);\n --md-primary-fg-color--transparent: hsla(65deg, 92%, 76%, 0.1);\n --md-primary-fg-color--light: hsla(65deg, 92%, 81%, 1);\n --md-primary-fg-color--dark: hsla(65deg, 92%, 71%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=orange],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=orange] {\n --md-primary-code-bg-color: rgb(71.41275, 62.445675, 60.93225);\n --md-primary-fg-color: hsla(31deg, 100%, 71%, 1);\n --md-primary-fg-color--transparent: hsla(31deg, 100%, 71%, 0.1);\n --md-primary-fg-color--light: hsla(31deg, 100%, 76%, 1);\n --md-primary-fg-color--dark: hsla(31deg, 100%, 66%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-primary=deep-orange],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-orange] {\n --md-primary-code-bg-color: rgb(71.41275, 62.445675, 60.93225);\n --md-primary-fg-color: hsla(31deg, 100%, 71%, 1);\n --md-primary-fg-color--transparent: hsla(31deg, 100%, 71%, 0.1);\n --md-primary-fg-color--light: hsla(31deg, 100%, 76%, 1);\n --md-primary-fg-color--dark: hsla(31deg, 100%, 66%, 1);\n --md-primary-bg-color: var(--md-default-bg-color);\n --md-primary-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=red],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=red] {\n --md-code-link-accent-bg-color: rgb(71.41275, 44.098425, 54.04725);\n --md-accent-fg-color: hsla(0deg, 100%, 62%, 1);\n --md-accent-fg-color--transparent: hsla(0deg, 100%, 62%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=pink],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=pink] {\n --md-code-link-accent-bg-color: rgb(71.41275, 49.453425, 72.84075);\n --md-accent-fg-color: hsla(326deg, 100%, 69%, 1);\n --md-accent-fg-color--transparent: hsla(326deg, 100%, 69%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=purple],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=purple] {\n --md-code-link-accent-bg-color: rgb(59.5533375, 53.64945, 81.981225);\n --md-accent-fg-color: hsla(265deg, 89%, 73%, 1);\n --md-accent-fg-color--transparent: hsla(265deg, 89%, 73%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=deep-purple],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-purple] {\n --md-code-link-accent-bg-color: rgb(59.5533375, 53.64945, 81.981225);\n --md-accent-fg-color: hsla(265deg, 89%, 73%, 1);\n --md-accent-fg-color--transparent: hsla(265deg, 89%, 73%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=blue],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=blue] {\n --md-code-link-accent-bg-color: rgb(46.0071, 50.1381, 67.2129);\n --md-accent-fg-color: hsla(225deg, 27%, 46%, 1);\n --md-accent-fg-color--transparent: hsla(225deg, 27%, 46%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=indigo],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=indigo] {\n --md-code-link-accent-bg-color: rgb(46.0071, 50.1381, 67.2129);\n --md-accent-fg-color: hsla(225deg, 27%, 46%, 1);\n --md-accent-fg-color--transparent: hsla(225deg, 27%, 46%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=light-blue],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-blue] {\n --md-code-link-accent-bg-color: rgb(46.0071, 50.1381, 67.2129);\n --md-accent-fg-color: hsla(225deg, 27%, 46%, 1);\n --md-accent-fg-color--transparent: hsla(225deg, 27%, 46%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=cyan],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=cyan] {\n --md-code-link-accent-bg-color: rgb(50.31405, 69.037935, 82.79595);\n --md-accent-fg-color: hsla(191deg, 97%, 72%, 1);\n --md-accent-fg-color--transparent: hsla(191deg, 97%, 72%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=teal],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=teal] {\n --md-code-link-accent-bg-color: rgb(50.31405, 69.037935, 82.79595);\n --md-accent-fg-color: hsla(191deg, 97%, 72%, 1);\n --md-accent-fg-color--transparent: hsla(191deg, 97%, 72%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=green],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=green] {\n --md-code-link-accent-bg-color: rgb(41.73075, 72.250425, 60.62625);\n --md-accent-fg-color: hsla(135deg, 94%, 60%, 1);\n --md-accent-fg-color--transparent: hsla(135deg, 94%, 60%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=light-green],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=light-green] {\n --md-code-link-accent-bg-color: rgb(41.73075, 72.250425, 60.62625);\n --md-accent-fg-color: hsla(135deg, 94%, 60%, 1);\n --md-accent-fg-color--transparent: hsla(135deg, 94%, 60%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=lime],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=lime] {\n --md-code-link-accent-bg-color: rgb(41.73075, 72.250425, 60.62625);\n --md-accent-fg-color: hsla(135deg, 94%, 60%, 1);\n --md-accent-fg-color--transparent: hsla(135deg, 94%, 60%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=yellow],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=yellow] {\n --md-code-link-accent-bg-color: rgb(68.8245, 72.281025, 61.81965);\n --md-accent-fg-color: hsla(65deg, 92%, 71%, 1);\n --md-accent-fg-color--transparent: hsla(65deg, 92%, 71%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=amber],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=amber] {\n --md-code-link-accent-bg-color: rgb(68.8245, 72.281025, 61.81965);\n --md-accent-fg-color: hsla(65deg, 92%, 71%, 1);\n --md-accent-fg-color--transparent: hsla(65deg, 92%, 71%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=orange],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=orange] {\n --md-code-link-accent-bg-color: rgb(71.41275, 60.596925, 57.10725);\n --md-accent-fg-color: hsla(31deg, 100%, 66%, 1);\n --md-accent-fg-color--transparent: hsla(31deg, 100%, 66%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n[data-md-color-scheme=dracula][data-md-color-accent=deep-orange],\n[data-md-color-scheme=dracula] :not([data-md-color-scheme])[data-md-color-primary=deep-orange] {\n --md-code-link-accent-bg-color: rgb(71.41275, 60.596925, 57.10725);\n --md-accent-fg-color: hsla(31deg, 100%, 66%, 1);\n --md-accent-fg-color--transparent: hsla(31deg, 100%, 66%, 0.1);\n --md-accent-bg-color: var(--md-default-bg-color);\n --md-accent-bg-color--light: var(--md-default-bg-color--light);\n}\n\n/* Normal colors */\n:root {\n --md-heart: #ff5252;\n --md-heart-big: #ff1744;\n /* Dark mode colors */\n}\n:root :focus-visible {\n outline-style: solid;\n}\n:root [data-md-color-scheme=dracula] {\n --md-heart: hsl(326, 100%, 74%);\n --md-heart-big: hsl(0, 100%, 67%);\n}\n\n.md-typeset h4 {\n margin: 2em 0 1em;\n}\n.md-typeset a.source-link {\n position: relative;\n top: -0.6rem;\n float: right;\n color: var(--md-default-fg-color--lighter);\n transition: color 125ms;\n}\n.md-typeset a.source-link:hover {\n color: var(--md-accent-fg-color);\n}\n.md-typeset a.source-link .twemoji {\n height: 1.2rem;\n}\n.md-typeset a.source-link .twemoji svg {\n width: 1.2rem;\n height: 1.2rem;\n}\n.md-typeset div.highlight.md-max-height pre > code {\n max-height: 15rem;\n}\n\n.twemoji.heart-throb svg, .twemoji.heart-throb-hover svg {\n position: relative;\n color: var(--md-heart);\n animation: pulse 1.5s ease infinite;\n}\n\n@keyframes pulse {\n 0% {\n transform: scale(1);\n }\n 40% {\n color: var(--md-heart-big);\n transform: scale(1.3);\n }\n 50% {\n transform: scale(1.2);\n }\n 60% {\n color: var(--md-heart-big);\n transform: scale(1.3);\n }\n 100% {\n transform: scale(1);\n }\n}\nfooter.sponsorship {\n text-align: center;\n}\nfooter.sponsorship hr {\n display: inline-block;\n width: 1.6rem;\n margin: 0 0.7rem;\n vertical-align: middle;\n border-bottom: 2px solid var(--md-default-fg-color--lighter);\n}\nfooter.sponsorship:hover hr {\n border-color: var(--md-accent-fg-color);\n}\nfooter.sponsorship:not(:hover) .twemoji.heart-throb-hover svg {\n color: var(--md-default-fg-color--lighter) !important;\n}\n\nbody:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=dracula] .md-icon .light-mode,\nbody:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=dracula] .md-icon .system-mode,\nbody:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=dracula] .md-icon .unknown-mode {\n display: none;\n}\nbody:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=default] .md-icon .dark-mode,\nbody:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=default] .md-icon .system-mode,\nbody:not([data-md-prefers-color-scheme=true])[data-md-color-scheme=default] .md-icon .unknown-mode {\n display: none;\n}\nbody:not([data-md-prefers-color-scheme=true]):not([data-md-color-scheme=default]):not([data-md-color-scheme=dracula]) .md-icon .dark-mode,\nbody:not([data-md-prefers-color-scheme=true]):not([data-md-color-scheme=default]):not([data-md-color-scheme=dracula]) .md-icon .light-mode,\nbody:not([data-md-prefers-color-scheme=true]):not([data-md-color-scheme=default]):not([data-md-color-scheme=dracula]) .md-icon .system-mode {\n display: none;\n}\nbody[data-md-prefers-color-scheme=true] .md-icon .dark-mode,\nbody[data-md-prefers-color-scheme=true] .md-icon .light-mode,\nbody[data-md-prefers-color-scheme=true] .md-icon .unknown-mode {\n display: none;\n}\n\n.md-header-nav__scheme {\n z-index: 0;\n}\n\n@media screen and (max-width: 59.9375em) {\n .md-header-nav__scheme {\n padding-right: 0;\n }\n label[for=__search] {\n padding-left: 0;\n }\n}\n[data-md-toggle=search]:checked ~ .md-header .md-header-nav__scheme {\n display: none;\n}\n\n.md-typeset .admonition, .md-typeset details {\n border-width: 0;\n border-left-width: 4px;\n}\n\n/* Style new admonitions with dark or light colors */\n:root > * {\n --md-admonition-bg-color: transparent;\n}\n:root > *[data-md-color-scheme=dracula] {\n --md-admonition-icon-color: dracula.$drac-dark-yellow;\n}\n:root > * {\n --md-admonition-icon--settings: svg-load(\"@mdi/svg/svg/cog.svg\");\n --md-admonition-bg-color--settings: rgba(170, 0, 255, 0.1);\n --md-admonition-icon-color--settings: #aa00ff;\n --md-admonition-shadow-color--settings: rgba(170, 0, 255, 0.1);\n}\n:root > *[data-md-color-scheme=dracula] {\n --md-admonition-bg-color--settings: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--settings: hsl(326, 100%, 74%);\n --md-admonition-shadow-color--settings: hsla(326, 100%, 74%, 0.1);\n}\n:root > * {\n --md-admonition-bg-color--note: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--note: hsl(51, 94%, 73%);\n --md-admonition-shadow-color--note: hsl(51, 94%, 73%);\n}\n:root > * {\n --md-admonition-bg-color--abstract: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--abstract: hsl(191, 97%, 77%);\n --md-admonition-shadow-color--abstract: hsl(191, 97%, 77%);\n}\n:root > * {\n --md-admonition-bg-color--info: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--info: hsl(190, 94%, 87%);\n --md-admonition-shadow-color--info: hsl(190, 94%, 87%);\n}\n:root > * {\n --md-admonition-bg-color--tip: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--tip: hsl(161, 97%, 77%);\n --md-admonition-shadow-color--tip: hsl(161, 97%, 77%);\n}\n:root > * {\n --md-admonition-bg-color--success: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--success: hsl(135, 94%, 65%);\n --md-admonition-shadow-color--success: hsl(135, 94%, 65%);\n}\n:root > * {\n --md-admonition-bg-color--question: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--question: hsl(135, 92%, 79%);\n --md-admonition-shadow-color--question: hsl(135, 92%, 79%);\n}\n:root > * {\n --md-admonition-bg-color--warning: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--warning: hsl(31, 100%, 71%);\n --md-admonition-shadow-color--warning: hsl(31, 100%, 71%);\n}\n:root > * {\n --md-admonition-bg-color--failure: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--failure: hsl(0, 100%, 59%);\n --md-admonition-shadow-color--failure: hsl(0, 100%, 59%);\n}\n:root > * {\n --md-admonition-bg-color--danger: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--danger: hsl(0, 100%, 67%);\n --md-admonition-shadow-color--danger: hsl(0, 100%, 67%);\n}\n:root > * {\n --md-admonition-bg-color--bug: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--bug: hsl(325, 100%, 64%);\n --md-admonition-shadow-color--bug: hsl(325, 100%, 64%);\n}\n:root > * {\n --md-admonition-bg-color--example: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--example: hsl(265, 89%, 78%);\n --md-admonition-shadow-color--example: hsl(265, 89%, 78%);\n}\n:root > * {\n --md-admonition-bg-color--quote: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--quote: hsl(225, 8%, 51%);\n --md-admonition-shadow-color--quote: hsl(225, 8%, 51%);\n}\n:root > * {\n --md-admonition-icon--new: svg-load(\"@mdi/svg/svg/alert-decagram.svg\");\n --md-admonition-bg-color--new: rgba(255, 214, 0, 0.1);\n --md-admonition-icon-color--new: #ffd600;\n --md-admonition-shadow-color--new: rgba(255, 214, 0, 0.1);\n}\n:root > *[data-md-color-scheme=dracula] {\n --md-admonition-bg-color--new: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--new: hsl(65, 92%, 76%);\n --md-admonition-shadow-color--new: hsla(65, 92%, 76%, 0.1);\n}\n:root > * {\n --md-admonition-bg-color--note: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--note: hsl(51, 94%, 73%);\n --md-admonition-shadow-color--note: hsl(51, 94%, 73%);\n}\n:root > * {\n --md-admonition-bg-color--abstract: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--abstract: hsl(191, 97%, 77%);\n --md-admonition-shadow-color--abstract: hsl(191, 97%, 77%);\n}\n:root > * {\n --md-admonition-bg-color--info: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--info: hsl(190, 94%, 87%);\n --md-admonition-shadow-color--info: hsl(190, 94%, 87%);\n}\n:root > * {\n --md-admonition-bg-color--tip: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--tip: hsl(161, 97%, 77%);\n --md-admonition-shadow-color--tip: hsl(161, 97%, 77%);\n}\n:root > * {\n --md-admonition-bg-color--success: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--success: hsl(135, 94%, 65%);\n --md-admonition-shadow-color--success: hsl(135, 94%, 65%);\n}\n:root > * {\n --md-admonition-bg-color--question: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--question: hsl(135, 92%, 79%);\n --md-admonition-shadow-color--question: hsl(135, 92%, 79%);\n}\n:root > * {\n --md-admonition-bg-color--warning: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--warning: hsl(31, 100%, 71%);\n --md-admonition-shadow-color--warning: hsl(31, 100%, 71%);\n}\n:root > * {\n --md-admonition-bg-color--failure: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--failure: hsl(0, 100%, 59%);\n --md-admonition-shadow-color--failure: hsl(0, 100%, 59%);\n}\n:root > * {\n --md-admonition-bg-color--danger: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--danger: hsl(0, 100%, 67%);\n --md-admonition-shadow-color--danger: hsl(0, 100%, 67%);\n}\n:root > * {\n --md-admonition-bg-color--bug: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--bug: hsl(325, 100%, 64%);\n --md-admonition-shadow-color--bug: hsl(325, 100%, 64%);\n}\n:root > * {\n --md-admonition-bg-color--example: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--example: hsl(265, 89%, 78%);\n --md-admonition-shadow-color--example: hsl(265, 89%, 78%);\n}\n:root > * {\n --md-admonition-bg-color--quote: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--quote: hsl(225, 8%, 51%);\n --md-admonition-shadow-color--quote: hsl(225, 8%, 51%);\n}\n\n/* Dark mode changes */\n[data-md-color-scheme=dracula] .md-typeset .admonition, [data-md-color-scheme=dracula] .md-typeset details {\n border-color: var(--md-admonition-icon-color--note);\n box-shadow: var(--md-shadow-z2);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition:focus-within, [data-md-color-scheme=dracula] .md-typeset details:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details > summary {\n background-color: var(--md-admonition-bg-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details > summary::before {\n background-color: var(--md-admonition-icon-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details > summary::after {\n color: var(--md-admonition-icon-color--note);\n}\n\n/* Style existing admonitions with dark mode colors */\n[data-md-color-scheme=dracula] .md-typeset .admonition.note, [data-md-color-scheme=dracula] .md-typeset details.note {\n border-color: var(--md-admonition-icon-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.note:focus-within, [data-md-color-scheme=dracula] .md-typeset details.note:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.note > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.note > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.note > summary {\n background-color: var(--md-admonition-bg-color--note);\n border-color: var(--md-admonition-icon-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.note > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.note > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.note > summary::before {\n background-color: var(--md-admonition-icon-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.note > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.note > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.note > summary::after {\n color: var(--md-admonition-icon-color--note);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.abstract, [data-md-color-scheme=dracula] .md-typeset details.abstract {\n border-color: var(--md-admonition-icon-color--abstract);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.abstract:focus-within, [data-md-color-scheme=dracula] .md-typeset details.abstract:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--abstract);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.abstract > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.abstract > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.abstract > summary {\n background-color: var(--md-admonition-bg-color--abstract);\n border-color: var(--md-admonition-icon-color--abstract);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.abstract > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.abstract > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.abstract > summary::before {\n background-color: var(--md-admonition-icon-color--abstract);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.abstract > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.abstract > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.abstract > summary::after {\n color: var(--md-admonition-icon-color--abstract);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.info, [data-md-color-scheme=dracula] .md-typeset details.info {\n border-color: var(--md-admonition-icon-color--info);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.info:focus-within, [data-md-color-scheme=dracula] .md-typeset details.info:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--info);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.info > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.info > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.info > summary {\n background-color: var(--md-admonition-bg-color--info);\n border-color: var(--md-admonition-icon-color--info);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.info > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.info > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.info > summary::before {\n background-color: var(--md-admonition-icon-color--info);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.info > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.info > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.info > summary::after {\n color: var(--md-admonition-icon-color--info);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.tip, [data-md-color-scheme=dracula] .md-typeset details.tip {\n border-color: var(--md-admonition-icon-color--tip);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.tip:focus-within, [data-md-color-scheme=dracula] .md-typeset details.tip:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--tip);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.tip > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.tip > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.tip > summary {\n background-color: var(--md-admonition-bg-color--tip);\n border-color: var(--md-admonition-icon-color--tip);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.tip > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.tip > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.tip > summary::before {\n background-color: var(--md-admonition-icon-color--tip);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.tip > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.tip > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.tip > summary::after {\n color: var(--md-admonition-icon-color--tip);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.success, [data-md-color-scheme=dracula] .md-typeset details.success {\n border-color: var(--md-admonition-icon-color--success);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.success:focus-within, [data-md-color-scheme=dracula] .md-typeset details.success:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--success);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.success > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.success > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.success > summary {\n background-color: var(--md-admonition-bg-color--success);\n border-color: var(--md-admonition-icon-color--success);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.success > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.success > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.success > summary::before {\n background-color: var(--md-admonition-icon-color--success);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.success > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.success > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.success > summary::after {\n color: var(--md-admonition-icon-color--success);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.question, [data-md-color-scheme=dracula] .md-typeset details.question {\n border-color: var(--md-admonition-icon-color--question);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.question:focus-within, [data-md-color-scheme=dracula] .md-typeset details.question:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--question);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.question > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.question > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.question > summary {\n background-color: var(--md-admonition-bg-color--question);\n border-color: var(--md-admonition-icon-color--question);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.question > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.question > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.question > summary::before {\n background-color: var(--md-admonition-icon-color--question);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.question > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.question > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.question > summary::after {\n color: var(--md-admonition-icon-color--question);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.warning, [data-md-color-scheme=dracula] .md-typeset details.warning {\n border-color: var(--md-admonition-icon-color--warning);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.warning:focus-within, [data-md-color-scheme=dracula] .md-typeset details.warning:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--warning);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.warning > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.warning > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.warning > summary {\n background-color: var(--md-admonition-bg-color--warning);\n border-color: var(--md-admonition-icon-color--warning);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.warning > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.warning > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.warning > summary::before {\n background-color: var(--md-admonition-icon-color--warning);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.warning > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.warning > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.warning > summary::after {\n color: var(--md-admonition-icon-color--warning);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.failure, [data-md-color-scheme=dracula] .md-typeset details.failure {\n border-color: var(--md-admonition-icon-color--failure);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.failure:focus-within, [data-md-color-scheme=dracula] .md-typeset details.failure:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--failure);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.failure > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.failure > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.failure > summary {\n background-color: var(--md-admonition-bg-color--failure);\n border-color: var(--md-admonition-icon-color--failure);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.failure > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.failure > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.failure > summary::before {\n background-color: var(--md-admonition-icon-color--failure);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.failure > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.failure > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.failure > summary::after {\n color: var(--md-admonition-icon-color--failure);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.danger, [data-md-color-scheme=dracula] .md-typeset details.danger {\n border-color: var(--md-admonition-icon-color--danger);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.danger:focus-within, [data-md-color-scheme=dracula] .md-typeset details.danger:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--danger);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.danger > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.danger > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.danger > summary {\n background-color: var(--md-admonition-bg-color--danger);\n border-color: var(--md-admonition-icon-color--danger);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.danger > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.danger > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.danger > summary::before {\n background-color: var(--md-admonition-icon-color--danger);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.danger > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.danger > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.danger > summary::after {\n color: var(--md-admonition-icon-color--danger);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.bug, [data-md-color-scheme=dracula] .md-typeset details.bug {\n border-color: var(--md-admonition-icon-color--bug);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.bug:focus-within, [data-md-color-scheme=dracula] .md-typeset details.bug:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--bug);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.bug > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.bug > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.bug > summary {\n background-color: var(--md-admonition-bg-color--bug);\n border-color: var(--md-admonition-icon-color--bug);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.bug > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.bug > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.bug > summary::before {\n background-color: var(--md-admonition-icon-color--bug);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.bug > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.bug > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.bug > summary::after {\n color: var(--md-admonition-icon-color--bug);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.example, [data-md-color-scheme=dracula] .md-typeset details.example {\n border-color: var(--md-admonition-icon-color--example);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.example:focus-within, [data-md-color-scheme=dracula] .md-typeset details.example:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--example);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.example > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.example > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.example > summary {\n background-color: var(--md-admonition-bg-color--example);\n border-color: var(--md-admonition-icon-color--example);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.example > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.example > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.example > summary::before {\n background-color: var(--md-admonition-icon-color--example);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.example > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.example > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.example > summary::after {\n color: var(--md-admonition-icon-color--example);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.quote, [data-md-color-scheme=dracula] .md-typeset details.quote {\n border-color: var(--md-admonition-icon-color--quote);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.quote:focus-within, [data-md-color-scheme=dracula] .md-typeset details.quote:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--quote);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.quote > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.quote > .admonition-title, [data-md-color-scheme=dracula] .md-typeset details.quote > summary {\n background-color: var(--md-admonition-bg-color--quote);\n border-color: var(--md-admonition-icon-color--quote);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.quote > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.quote > .admonition-title::before, [data-md-color-scheme=dracula] .md-typeset details.quote > summary::before {\n background-color: var(--md-admonition-icon-color--quote);\n}\n[data-md-color-scheme=dracula] .md-typeset .admonition.quote > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.quote > .admonition-title::after, [data-md-color-scheme=dracula] .md-typeset details.quote > summary::after {\n color: var(--md-admonition-icon-color--quote);\n}\n\n.md-typeset .admonition.settings, .md-typeset details.settings, .md-typeset .admonition.config, .md-typeset details.config {\n border-color: var(--md-admonition-icon-color--settings);\n}\n.md-typeset .admonition.settings:focus-within, .md-typeset details.settings:focus-within, .md-typeset .admonition.config:focus-within, .md-typeset details.config:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--settings);\n}\n.md-typeset .admonition.settings > .admonition-title, .md-typeset details.settings > .admonition-title, .md-typeset details.settings > summary, .md-typeset .admonition.config > .admonition-title, .md-typeset details.config > .admonition-title, .md-typeset details.config > summary {\n background-color: var(--md-admonition-bg-color--settings);\n border-color: var(--md-admonition-icon-color--settings);\n}\n.md-typeset .admonition.settings > .admonition-title::before, .md-typeset details.settings > .admonition-title::before, .md-typeset details.settings > summary::before, .md-typeset .admonition.config > .admonition-title::before, .md-typeset details.config > .admonition-title::before, .md-typeset details.config > summary::before {\n width: 1rem;\n height: 1rem;\n background-color: var(--md-admonition-icon-color--settings);\n background-size: 1rem;\n mask-image: var(--md-admonition-icon--settings);\n content: \" \";\n}\n.md-typeset .admonition.settings > .admonition-title::after, .md-typeset details.settings > .admonition-title::after, .md-typeset details.settings > summary::after, .md-typeset .admonition.config > .admonition-title::after, .md-typeset details.config > .admonition-title::after, .md-typeset details.config > summary::after {\n color: var(--md-admonition-icon-color--settings);\n}\n\n.md-typeset .admonition.new, .md-typeset details.new {\n border-color: var(--md-admonition-icon-color--new);\n}\n.md-typeset .admonition.new:focus-within, .md-typeset details.new:focus-within {\n box-shadow: 0 0 0 0.2rem var(--md-admonition-shadow-color--new);\n}\n.md-typeset .admonition.new > .admonition-title, .md-typeset details.new > .admonition-title, .md-typeset details.new > summary {\n background-color: var(--md-admonition-bg-color--new);\n border-color: var(--md-admonition-icon-color--new);\n}\n.md-typeset .admonition.new > .admonition-title::before, .md-typeset details.new > .admonition-title::before, .md-typeset details.new > summary::before {\n width: 1rem;\n height: 1rem;\n background-color: var(--md-admonition-icon-color--new);\n background-size: 1rem;\n mask-image: var(--md-admonition-icon--new);\n content: \" \";\n}\n.md-typeset .admonition.new > .admonition-title::after, .md-typeset details.new > .admonition-title::after, .md-typeset details.new > summary::after {\n color: var(--md-admonition-icon-color--new);\n}\n\nmjx-container[display=true] {\n font-size: 120% !important;\n}\n\nmjx-container:not([display]) {\n font-size: 100% !important;\n}\n\n[data-md-color-scheme=slate],\n[data-md-color-scheme=dracula] {\n /* stylelint-disable selector-class-pattern */\n /* stylelint-enable selector-class-pattern */\n}\n[data-md-color-scheme=slate] .CtxtMenu_InfoSignature input,\n[data-md-color-scheme=slate] .CtxtMenu_InfoContent pre,\n[data-md-color-scheme=dracula] .CtxtMenu_InfoSignature input,\n[data-md-color-scheme=dracula] .CtxtMenu_InfoContent pre {\n color: rgb(0, 0, 0);\n}\n[data-md-color-scheme=slate] .CtxtMenu_Info,\n[data-md-color-scheme=slate] .CtxtMenu_Menu,\n[data-md-color-scheme=dracula] .CtxtMenu_Info,\n[data-md-color-scheme=dracula] .CtxtMenu_Menu {\n box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.5);\n}\n\n.md-typeset .arithmatex {\n overflow-x: auto !important;\n overflow-y: hidden !important;\n}\n\n.katex-display .katex-html {\n display: flex !important;\n flex-direction: row;\n flex-wrap: nowrap;\n align-items: baseline;\n justify-content: space-between;\n}\n.katex-display .katex-html .base {\n display: inline !important;\n}\n.katex-display .katex-html .tag {\n position: relative !important;\n display: inline !important;\n margin-left: var(--margin-small);\n}\n\n/* Don't use box shadows */\n.md-typeset del.critic,\n.md-typeset ins.critic,\n.md-typeset mark.critic {\n padding: 0 0.25em;\n color: unset;\n box-shadow: none;\n}\n.md-typeset .critic.break {\n margin: 0;\n}\n\n/* Inherit admonition style */\n.md-typeset details {\n overflow: hidden;\n}\n.md-typeset details > summary:focus {\n outline-style: none;\n}\n\n.highlight .kc {\n color: var(--md-code-hl-constant-color);\n}\n.highlight .nc,\n.highlight .ne {\n color: var(--md-code-hl-class-color);\n}\n.highlight .mb {\n color: var(--md-code-hl-number-color);\n}\n.highlight .nb,\n.highlight .bp {\n color: var(--md-code-hl-builtin-color);\n}\n.highlight .nn {\n color: var(--md-code-hl-namespace-color);\n}\n.highlight .na,\n.highlight .nd,\n.highlight .ni {\n color: var(--md-code-hl-entity-color);\n}\n.highlight .nl,\n.highlight .nt {\n color: var(--md-code-hl-tag-color);\n}\n\n.md-typeset {\n /* Allow code to look like code everywhere despite Material's current preference */\n /* Code that is also a link */\n /* Don't always like code breaking in table cells */\n /* Special line number coloring for tables */\n}\n.md-typeset *:not(pre) > code {\n margin: 0;\n padding: 0 0.2941176471em;\n color: var(--md-code-fg-color);\n background-color: var(--md-code-inline-bg-color);\n border-radius: px2rem(2px);\n box-shadow: none;\n}\n.md-typeset a > code {\n color: inherit !important;\n background-color: var(--md-code-link-bg-color) !important;\n transition: color 125ms;\n transition: background-color 125ms;\n /* If we are linking highlighted, inline code, force it to just look like a code link */\n}\n.md-typeset a > code * {\n color: var(--md-typeset-a-color) !important;\n}\n.md-typeset a > code:hover {\n background-color: var(--md-code-link-accent-bg-color) !important;\n}\n.md-typeset a > code:hover * {\n color: var(--md-accent-fg-color) !important;\n}\n.md-typeset pre > code {\n outline: none;\n}\n.md-typeset td code {\n word-break: normal;\n}\n.md-typeset .highlight {\n /* Needed for tab preserving mode */\n tab-size: 8;\n /* `pymdownx-inline` mode */\n}\n.md-typeset .highlight + .result {\n border-width: px2rem(2px);\n}\n.md-typeset .highlight [data-linenos] {\n /* Special line mode coloring */\n}\n.md-typeset .highlight [data-linenos].special::before {\n background-color: var(--md-code-special-bg-color);\n}\n.md-typeset .highlighttable .linenodiv .special {\n margin-right: -0.5882352941em;\n margin-left: -1.1764705882em;\n padding-right: 0.5882352941em;\n padding-left: 1.1764705882em;\n background-color: var(--md-code-special-bg-color);\n}\n.md-typeset .highlight span.filename {\n position: relative;\n display: block;\n margin-top: 1em;\n padding: 0.5em 1.1764705882em 0.5em 2.9411764706em;\n font-weight: 700;\n font-size: px2rem(13.6px);\n background-color: var(--md-code-title-bg-color);\n border-top-left-radius: px2rem(2px);\n border-top-right-radius: px2rem(2px);\n}\n.md-typeset .highlight span.filename + pre {\n margin-top: 0;\n}\n.md-typeset .highlight span.filename + pre code {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.md-typeset .highlight span.filename::before {\n position: absolute;\n left: 0.8823529412em;\n width: 1.4705882353em;\n height: 1.4705882353em;\n background-color: var(--md-default-fg-color);\n mask-image: svg-load(\"@mdi/svg/svg/console.svg\");\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n}\n.md-typeset .collapse-code {\n position: relative;\n margin-top: 1em;\n margin-bottom: 1em;\n}\n.md-typeset .collapse-code pre {\n margin-top: 0;\n margin-bottom: 0;\n}\n.md-typeset .collapse-code input {\n display: none;\n}\n.md-typeset .collapse-code input ~ .code-footer {\n width: 100%;\n margin: 0;\n padding: 0.25em 0.5em 0.25em 0em;\n}\n.md-typeset .collapse-code input ~ .code-footer label {\n position: relative;\n margin: 0.05em;\n padding: 0.15em 0.8em;\n color: var(--md-primary-bg-color);\n font-size: 90%;\n background-color: var(--md-primary-fg-color);\n mask-repeat: no-repeat;\n mask-size: contain;\n border-radius: px2rem(2px);\n cursor: pointer;\n content: \"\";\n}\n.md-typeset .collapse-code input ~ .code-footer label:hover {\n background-color: var(--md-accent-fg-color);\n}\n.md-typeset .collapse-code input ~ .code-footer label::before {\n position: absolute;\n top: 0.15em;\n left: 0.15em;\n display: block;\n box-sizing: border-box;\n width: 1.25em;\n height: 1.25em;\n background-color: var(--md-primary-bg-color);\n background-size: 1.25em;\n content: \"\";\n}\n.md-typeset .collapse-code input ~ .code-footer label.expand {\n display: none;\n}\n.md-typeset .collapse-code input ~ .code-footer label.expand::before {\n mask-image: svg-load(\"@mdi/svg/svg/arrow-expand.svg\");\n}\n.md-typeset .collapse-code input ~ .code-footer label.collapse::before {\n mask-image: svg-load(\"@mdi/svg/svg/arrow-collapse.svg\");\n}\n.md-typeset .collapse-code input:checked ~ .code-footer label.expand {\n display: inline;\n}\n.md-typeset .collapse-code input:checked ~ .code-footer label.collapse {\n display: none;\n}\n.md-typeset .collapse-code input:checked + div.highlight code {\n max-height: 9.375em;\n overflow: hidden;\n}\n.md-typeset .collapse-code input:checked ~ .code-footer {\n position: absolute;\n bottom: 0;\n left: 0;\n padding: 2em 0.5em 0.5em px2rem(16px);\n background-image: linear-gradient(to bottom, transparent, var(--md-default-bg-color) 80% 100%);\n}\n@media screen and (max-width: 44.9375em) {\n .md-typeset > diagram-div {\n margin-right: px2rem(-16px);\n margin-left: px2rem(-16px);\n }\n .md-typeset > .collapse-code {\n margin-right: px2rem(-16px);\n margin-left: px2rem(-16px);\n }\n .md-typeset > .collapse-code label.collapse {\n left: px2rem(16px);\n }\n}\n\n.md-typeset .keys .key-power::before {\n padding-right: 0.4em;\n content: \"⏻\";\n}\n.md-typeset .keys .key-fingerprint::before {\n padding-right: 0.4em;\n content: \"☝\";\n}\n\n:root > * {\n --magiclink-email-icon: svg-load(\"@mdi/svg/svg/mail.svg\");\n --magiclink-github-icon: svg-load(\"@mdi/svg/svg/github.svg\");\n --magiclink-bitbucket-icon: svg-load(\"@mdi/svg/svg/bitbucket.svg\");\n --magiclink-gitlab-icon: svg-load(\"@mdi/svg/svg/gitlab.svg\");\n --magiclink-commit-icon: svg-load(\"@primer/octicons/build/svg/git-commit-24.svg\");\n --magiclink-compare-icon: svg-load(\"@primer/octicons/build/svg/file-diff-24.svg\");\n --magiclink-pull-icon: svg-load(\"@primer/octicons/build/svg/git-pull-request-24.svg\");\n --magiclink-issue-icon: svg-load(\"@primer/octicons/build/svg/issue-opened-24.svg\");\n --magiclink-discussion-icon: svg-load(\"@primer/octicons/build/svg/comment-discussion-24.svg\");\n}\n\n.md-typeset a[href^=\"mailto:\"]:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-email-icon);\n}\n.md-typeset .magiclink-repository:not(.magiclink-ignore),\n.md-typeset .magiclink-compare:not(.magiclink-ignore),\n.md-typeset .magiclink-commit:not(.magiclink-ignore),\n.md-typeset .magiclink-pull:not(.magiclink-ignore),\n.md-typeset .magiclink-issue:not(.magiclink-ignore),\n.md-typeset .magiclink-discussion:not(.magiclink-ignore),\n.md-typeset a[href^=\"mailto:\"]:not(.magiclink-ignore) {\n position: relative;\n padding-left: 1.375em;\n}\n.md-typeset .magiclink-repository:not(.magiclink-ignore)::before,\n.md-typeset .magiclink-compare:not(.magiclink-ignore)::before,\n.md-typeset .magiclink-commit:not(.magiclink-ignore)::before,\n.md-typeset .magiclink-pull:not(.magiclink-ignore)::before,\n.md-typeset .magiclink-issue:not(.magiclink-ignore)::before,\n.md-typeset .magiclink-discussion:not(.magiclink-ignore)::before,\n.md-typeset a[href^=\"mailto:\"]:not(.magiclink-ignore)::before {\n position: absolute;\n top: 0;\n left: 0;\n display: block;\n box-sizing: border-box;\n width: 1.25em;\n height: 1.25em;\n background-color: var(--md-typeset-a-color);\n background-size: 1.25em;\n transition: background-color 125ms;\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n}\n.md-typeset .magiclink-repository:not(.magiclink-ignore):hover::before,\n.md-typeset .magiclink-compare:not(.magiclink-ignore):hover::before,\n.md-typeset .magiclink-commit:not(.magiclink-ignore):hover::before,\n.md-typeset .magiclink-pull:not(.magiclink-ignore):hover::before,\n.md-typeset .magiclink-issue:not(.magiclink-ignore):hover::before,\n.md-typeset .magiclink-discussion:not(.magiclink-ignore):hover::before,\n.md-typeset a[href^=\"mailto:\"]:not(.magiclink-ignore):hover::before {\n background-color: var(--md-accent-fg-color);\n}\n\n.md-typeset .magiclink-commit:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-commit-icon);\n}\n\n.md-typeset .magiclink-compare:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-compare-icon);\n}\n\n.md-typeset .magiclink-pull:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-pull-icon);\n}\n\n.md-typeset .magiclink-issue:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-issue-icon);\n}\n\n.md-typeset .magiclink-discussion:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-discussion-icon);\n}\n\n.md-typeset .magiclink-repository.magiclink-github:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-github-icon);\n}\n\n.md-typeset .magiclink-repository.magiclink-gitlab:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-gitlab-icon);\n}\n\n.md-typeset .magiclink-repository.magiclink-bitbucket:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-bitbucket-icon);\n}\n\n/* Shadow boxes sometimes give issues, so just pad. */\n.md-typeset mark:not(.critic) {\n box-shadow: none;\n}\n\n.md-typeset {\n /* Progress Bars */\n /* Stripe animation */\n}\n.md-typeset .progress-label {\n position: absolute;\n width: 100%;\n margin: 0;\n color: var(--md-text-color);\n font-weight: 700;\n line-height: 1.4rem;\n white-space: nowrap;\n text-align: center;\n text-shadow: -0.0625em -0.0625em 0.375em var(--md-default-bg-color--light), 0.0625em -0.0625em 0.375em var(--md-default-bg-color--light), -0.0625em 0.0625em 0.375em var(--md-default-bg-color--light), 0.0625em 0.0625em 0.375em var(--md-default-bg-color--light);\n}\n.md-typeset .progress-bar {\n float: left;\n height: 1.2rem;\n background-color: #2979ff;\n}\n.md-typeset .candystripe-animate .progress-bar {\n animation: animate-stripes 3s linear infinite;\n}\n.md-typeset .progress {\n position: relative;\n display: block;\n width: 100%;\n height: 1.2rem;\n margin: 0.5rem 0;\n background-color: var(--md-default-fg-color--lightest);\n}\n.md-typeset .progress.thin {\n height: 0.4rem;\n margin-top: 0.9rem;\n}\n.md-typeset .progress.thin .progress-label {\n margin-top: -0.4rem;\n}\n.md-typeset .progress.thin .progress-bar {\n height: 0.4rem;\n}\n.md-typeset .progress.candystripe .progress-bar {\n background-image: linear-gradient(135deg, var(--md-progress-stripe) 27%, transparent 27%, transparent 52%, var(--md-progress-stripe) 52%, var(--md-progress-stripe) 77%, transparent 77%, transparent);\n background-size: 2rem 2rem;\n}\n.md-typeset .progress-100plus .progress-bar {\n background-color: var(--md-progress-100);\n}\n.md-typeset .progress-80plus .progress-bar {\n background-color: var(--md-progress-80);\n}\n.md-typeset .progress-60plus .progress-bar {\n background-color: var(--md-progress-60);\n}\n.md-typeset .progress-40plus .progress-bar {\n background-color: var(--md-progress-40);\n}\n.md-typeset .progress-20plus .progress-bar {\n background-color: var(--md-progress-20);\n}\n.md-typeset .progress-0plus .progress-bar {\n background-color: var(--md-progress-0);\n}\n@keyframes animate-stripes {\n 0% {\n background-position: 0 0;\n }\n 100% {\n background-position: 6rem 0;\n }\n}\n\n/* Dark mode changes */\n[data-md-color-scheme=dracula] .md-typeset .tabbed-set > .tabbed-labels {\n box-shadow: 0 -0.05rem var(--md-default-fg-color--lighter) inset;\n}\n\n/* Style code blocks to fill full tab,\n but otherwise, pad content. */\n.md-typeset .tabbed-alternate.tabbed-set .tabbed-control {\n width: 2rem;\n}\n.md-typeset .tabbed-alternate.tabbed-set .tabbed-control[hidden] {\n width: 1.2rem;\n opacity: 0;\n}\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block {\n padding: 0 0.6rem;\n}\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > pre:only-child,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .codehilite:only-child,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .codehilitetable:only-child,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .highlight:only-child,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .highlighttable:only-child {\n margin-right: -1.2rem;\n margin-left: -1.2rem;\n padding-right: 0.6rem;\n padding-left: 0.6rem;\n}\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > pre:only-child span.filename,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .codehilite:only-child span.filename,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .codehilitetable:only-child span.filename,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .highlight:only-child span.filename,\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .highlighttable:only-child span.filename {\n margin-top: 0;\n}\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .collapse-code:only-child {\n margin-top: 0;\n margin-right: -1.2rem;\n margin-left: -1.2rem;\n padding-right: 0.6rem;\n padding-left: 0.6rem;\n}\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > .collapse-code:only-child > .code-footer {\n left: 0.6rem;\n}\n.md-typeset .tabbed-alternate.tabbed-set > .tabbed-content > .tabbed-block > diagram-div:only-child {\n margin-right: -1.2rem;\n margin-left: -1.2rem;\n padding-right: 0.6rem;\n padding-left: 0.6rem;\n}\n\n.js .md-typeset .tabbed-labels::before {\n background-color: var(--md-accent-fg-color);\n}\n\n/* Ignore mobile overflow styling that extends the tab bar */\n@media screen and (max-width: 44.9375em) {\n [dir=ltr] .md-content__inner > .tabbed-set .tabbed-labels {\n padding-left: 0;\n }\n .md-content__inner > .tabbed-set .tabbed-labels {\n max-width: 100%;\n margin: 0;\n padding-inline-start: 0;\n scroll-padding-inline-start: 0;\n }\n .md-content__inner > .tabbed-set .tabbed-labels::after {\n padding-inline-end: 0;\n content: none;\n }\n .md-content__inner > .tabbed-set .tabbed-labels ~ .tabbed-control--prev {\n margin-inline-start: 0;\n padding-inline-start: 0;\n }\n .md-content__inner > .tabbed-set .tabbed-labels ~ .tabbed-control--next {\n margin-inline-end: 0;\n padding-inline-end: 0;\n }\n}\n/* Dark mode changes */\n[data-md-color-scheme=dracula] .md-typeset table:not([class]) {\n box-shadow: var(--md-shadow-z2);\n}\n[data-md-color-scheme=dracula] .md-typeset table:not([class]) tr:hover {\n background-color: rgba(0, 0, 0, 0.08);\n}\n[data-md-color-scheme=dracula] .md-typeset table:not([class]) th {\n color: var(--md-text-color);\n background-color: var(--md-default-bg-color--ultra-dark);\n border-bottom: 0.05rem solid var(--md-primary-fg-color);\n}\n[data-md-color-scheme=dracula] .md-typeset table:not([class]) td {\n border-top: 0.05rem solid var(--md-default-fg-color--lighter);\n}\n\n/* Dark mode changes */\n[data-md-color-scheme=dracula] .md-typeset .task-list-control .task-list-indicator::before {\n background-color: var(--md-default-fg-color--lighter);\n}\n[data-md-color-scheme=dracula] .md-typeset .task-list-control [type=checkbox]:checked + .task-list-indicator::before {\n background-color: hsl(135, 94%, 65%);\n}\n\n.md-typeset .headerlink {\n width: 1em;\n height: 1em;\n vertical-align: middle;\n background-color: var(--md-default-fg-color--lighter);\n background-size: 1em;\n mask-size: 1em;\n mask-repeat: no-repeat;\n visibility: visible;\n mask-image: svg-load(\"@mdi/svg/svg/link.svg\");\n}\n.md-typeset .headerlink:hover,\n.md-typeset [id]:target .headerlink {\n background-color: var(--md-accent-fg-color);\n}\n\n/* Special handling of Mermaid content. */\ndiagram-div {\n overflow: auto;\n}\n\nhtml {\n background-color: transparent;\n}\n\n[data-md-component=announce] .twemoji {\n color: var(--md-primary-fg-color);\n}\n\n/* Dark mode changes */\n[data-md-color-scheme=dracula] {\n --md-text-color: var(--md-default-fg-color);\n background-color: var(--md-default-bg-color);\n --md-footer-bg-color: transparent;\n --md-footer-bg-color--dark: var(--md-default-bg-color--darkest);\n --md-header-fg-color: var(--md-text-color);\n --md-header-bg-color: var(--md-default-bg-color--darkest);\n}\n[data-md-color-scheme=dracula] .md-header {\n color: var(--md-text-color);\n background-color: var(--md-header-bg-color);\n border-bottom: 0.05rem solid var(--md-primary-fg-color);\n}\n[data-md-color-scheme=dracula] .md-header[data-md-state=shadow] {\n box-shadow: 0 0 0.2rem rgba(0, 0, 0, 0.15), 0 0 0.2rem 0.4rem rgba(0, 0, 0, 0.2);\n}\n[data-md-color-scheme=dracula] .md-top {\n background-color: var(--md-default-bg-color--dark);\n}\n[data-md-color-scheme=dracula] .md-top:hover {\n background-color: var(--md-primary-fg-color);\n}\n[data-md-color-scheme=dracula] .md-tabs {\n color: var(--md-text-color);\n background-color: var(--md-primary-fg-color--transparent);\n}\n[data-md-color-scheme=dracula] .md-tabs__link--active {\n color: var(--md-primary-fg-color);\n}\n[data-md-color-scheme=dracula] .md-tabs__link:hover {\n color: var(--md-accent-fg-color);\n}\n[data-md-color-scheme=dracula] .md-hero {\n color: var(--md-text-color);\n background-color: var(--md-primary-fg-color--transparent);\n}\n[data-md-color-scheme=dracula] .md-nav__source {\n color: var(--md-text-color);\n}\n[data-md-color-scheme=dracula] .md-nav__link[data-md-state=blur] {\n color: var(--md-default-fg-color--light);\n}\n[data-md-color-scheme=dracula] .md-nav__item .md-nav__link--active {\n color: var(--md-primary-fg-color);\n}\n[data-md-color-scheme=dracula] .md-nav__link:focus, [data-md-color-scheme=dracula] .md-nav__link:hover {\n color: var(--md-accent-fg-color);\n}\n@media screen and (max-width: 76.1875em) {\n [data-md-color-scheme=dracula] .md-nav--primary .md-nav__item--active > .md-nav__link:not(:hover) {\n color: var(--md-primary-fg-color);\n }\n [data-md-color-scheme=dracula] .md-nav--primary .md-nav__title {\n color: var(--md-text-color);\n background-color: var(--md-header-bg-color);\n border-bottom: 0.05rem solid var(--md-primary-fg-color);\n }\n}\n@media screen and (max-width: 59.9375em) {\n [data-md-color-scheme=dracula] .md-nav__source {\n color: var(--md-text-color);\n background-color: var(--md-primary-fg-color--transparent);\n }\n [data-md-color-scheme=dracula] .md-nav .md-nav__title {\n color: var(--md-text-color);\n background-color: var(--md-header-bg-color);\n border-bottom: 0.05rem solid var(--md-primary-fg-color);\n }\n}\n[data-md-color-scheme=dracula] .md-search__input {\n color: var(--md-text-color);\n background-color: var(--md-accent-bg-color--light);\n}\n[data-md-color-scheme=dracula] .md-search__input:hover {\n background-color: var(--md-default-bg-color--light);\n}\n[data-md-color-scheme=dracula] .md-search__input ~ .md-search__icon {\n color: var(--md-text-color);\n}\n[data-md-color-scheme=dracula] .md-search__input::placeholder {\n color: var(--md-default-fg-color--light);\n}\n[data-md-color-scheme=dracula] [data-md-toggle=search]:checked ~ .md-header .md-search__input {\n background-color: transparent;\n}\n[data-md-color-scheme=dracula] .md-search__suggest {\n color: var(--md-default-autocomplete-fg-color);\n}\n[data-md-color-scheme=dracula] .md-search__overlay, [data-md-color-scheme=dracula] .md-overlay {\n background-color: var(--md-default-bg-color--light);\n}\n[data-md-color-scheme=dracula] .md-footer-nav__direction {\n color: var(--md-primary-fg-color);\n}\n[data-md-color-scheme=dracula] .md-footer-meta {\n border-top: 0.05rem solid var(--md-primary-fg-color);\n}\n[data-md-color-scheme=dracula] [data-md-component=announce] {\n background-color: var(--md-default-bg-color--ultra-dark);\n}\n\n.md-typeset {\n /* Don't force capitalization of `H5` elements. */\n}\n.md-typeset h5 {\n color: var(--md-text-color);\n text-transform: none;\n}\n\n.md-typeset__scrollwrap,\n.md-sidebar__scrollwrap,\n.md-search__scrollwrap,\n.md-typeset pre > code,\n.md-typeset div.mermaid,\n.md-typeset div.diagram,\n.md-typeset mermaid-div,\n.md-typeset diagram-div,\n.md-typeset pre.arithmatex,\n.md-typeset div.arithmatex {\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n scrollbar-width: thin;\n}\n.md-typeset__scrollwrap:hover,\n.md-sidebar__scrollwrap:hover,\n.md-search__scrollwrap:hover,\n.md-typeset pre > code:hover,\n.md-typeset div.mermaid:hover,\n.md-typeset div.diagram:hover,\n.md-typeset mermaid-div:hover,\n.md-typeset diagram-div:hover,\n.md-typeset pre.arithmatex:hover,\n.md-typeset div.arithmatex:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n}\n.md-typeset__scrollwrap::-webkit-scrollbar,\n.md-sidebar__scrollwrap::-webkit-scrollbar,\n.md-search__scrollwrap::-webkit-scrollbar,\n.md-typeset pre > code::-webkit-scrollbar,\n.md-typeset div.mermaid::-webkit-scrollbar,\n.md-typeset div.diagram::-webkit-scrollbar,\n.md-typeset mermaid-div::-webkit-scrollbar,\n.md-typeset diagram-div::-webkit-scrollbar,\n.md-typeset pre.arithmatex::-webkit-scrollbar,\n.md-typeset div.arithmatex::-webkit-scrollbar {\n width: 0.2rem;\n height: 0.2rem;\n}\n.md-typeset__scrollwrap::-webkit-scrollbar-corner,\n.md-sidebar__scrollwrap::-webkit-scrollbar-corner,\n.md-search__scrollwrap::-webkit-scrollbar-corner,\n.md-typeset pre > code::-webkit-scrollbar-corner,\n.md-typeset div.mermaid::-webkit-scrollbar-corner,\n.md-typeset div.diagram::-webkit-scrollbar-corner,\n.md-typeset mermaid-div::-webkit-scrollbar-corner,\n.md-typeset diagram-div::-webkit-scrollbar-corner,\n.md-typeset pre.arithmatex::-webkit-scrollbar-corner,\n.md-typeset div.arithmatex::-webkit-scrollbar-corner {\n background-color: transparent;\n}\n.md-typeset__scrollwrap::-webkit-scrollbar-thumb,\n.md-sidebar__scrollwrap::-webkit-scrollbar-thumb,\n.md-search__scrollwrap::-webkit-scrollbar-thumb,\n.md-typeset pre > code::-webkit-scrollbar-thumb,\n.md-typeset div.mermaid::-webkit-scrollbar-thumb,\n.md-typeset div.diagram::-webkit-scrollbar-thumb,\n.md-typeset mermaid-div::-webkit-scrollbar-thumb,\n.md-typeset diagram-div::-webkit-scrollbar-thumb,\n.md-typeset pre.arithmatex::-webkit-scrollbar-thumb,\n.md-typeset div.arithmatex::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n}\n.md-typeset__scrollwrap::-webkit-scrollbar-thumb:hover,\n.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover,\n.md-search__scrollwrap::-webkit-scrollbar-thumb:hover,\n.md-typeset pre > code::-webkit-scrollbar-thumb:hover,\n.md-typeset div.mermaid::-webkit-scrollbar-thumb:hover,\n.md-typeset div.diagram::-webkit-scrollbar-thumb:hover,\n.md-typeset mermaid-div::-webkit-scrollbar-thumb:hover,\n.md-typeset diagram-div::-webkit-scrollbar-thumb:hover,\n.md-typeset pre.arithmatex::-webkit-scrollbar-thumb:hover,\n.md-typeset div.arithmatex::-webkit-scrollbar-thumb:hover {\n background-color: var(--md-accent-fg-color);\n}","@use \"palette/material_color\";\n@use \"palette/dracula\";\n@use \"utilities/break\";\n@use \"utilities/convert\";\n\n/* Normal colors */\n:root {\n --md-heart: #{material_color.$clr-red-a200};\n --md-heart-big: #{material_color.$clr-red-a400};\n\n :focus-visible {\n outline-style: solid;\n }\n\n /* Dark mode colors */\n [data-md-color-scheme=\"dracula\"] {\n --md-heart: #{dracula.$drac-pink};\n --md-heart-big: #{dracula.$drac-red};\n }\n}\n\n.md-typeset {\n\n h4 {\n margin: 2.0em 0 1em;\n }\n\n a.source-link {\n position: relative;\n top: convert.px2rem(-12px);\n float: right;\n color: var(--md-default-fg-color--lighter);\n transition: color 125ms;\n\n &:hover {\n color: var(--md-accent-fg-color);\n }\n\n .twemoji {\n height: convert.px2rem(24px);\n\n svg {\n width: convert.px2rem(24px);\n height: convert.px2rem(24px);\n }\n }\n }\n\n div.highlight.md-max-height pre > code {\n max-height: convert.px2rem(300px);\n }\n}\n\n.twemoji {\n &.heart-throb, &.heart-throb-hover {\n svg {\n position: relative;\n color: var(--md-heart);\n animation: pulse 1.5s ease infinite;\n }\n }\n}\n\n@keyframes pulse {\n 0% { transform: scale(1); }\n 40% { color: var(--md-heart-big); transform: scale(1.3); }\n 50% { transform: scale(1.2); }\n 60% { color: var(--md-heart-big); transform: scale(1.3); }\n 100% { transform: scale(1); }\n}\n\nfooter.sponsorship {\n text-align: center;\n\n hr {\n display: inline-block;\n width: convert.px2rem(32px);\n margin: 0 convert.px2rem(14px);\n vertical-align: middle;\n border-bottom: 2px solid var(--md-default-fg-color--lighter);\n }\n\n &:hover {\n hr {\n border-color: var(--md-accent-fg-color);\n }\n }\n\n &:not(:hover) {\n .twemoji.heart-throb-hover svg{\n color: var(--md-default-fg-color--lighter) !important;\n }\n }\n}\n\n// Scheme toggle\nbody {\n &:not([data-md-prefers-color-scheme=\"true\"])[data-md-color-scheme=\"dracula\"] .md-icon {\n .light-mode,\n .system-mode,\n .unknown-mode {\n display: none;\n }\n }\n\n\n &:not([data-md-prefers-color-scheme=\"true\"])[data-md-color-scheme=\"default\"] .md-icon {\n .dark-mode,\n .system-mode,\n .unknown-mode {\n display: none;\n }\n }\n\n &:not([data-md-prefers-color-scheme=\"true\"]):not([data-md-color-scheme=\"default\"]):not([data-md-color-scheme=\"dracula\"]) .md-icon {\n .dark-mode,\n .light-mode,\n .system-mode {\n display: none;\n }\n }\n\n &[data-md-prefers-color-scheme=\"true\"] .md-icon {\n .dark-mode,\n .light-mode,\n .unknown-mode {\n display: none;\n }\n }\n}\n\n.md-header-nav__scheme {\n z-index: 0;\n}\n\n@include break.break-to-device(tablet portrait) {\n .md-header-nav__scheme {\n padding-right: 0;\n }\n\n label[for=\"__search\"] {\n padding-left: 0;\n }\n}\n\n[data-md-toggle=search]:checked~.md-header .md-header-nav__scheme {\n display: none;\n}\n","@use \"sass:color\";\n@use \"sass:list\";\n@use \"../utilities/convert\";\n@use \"../palette/material_color\";\n@use \"../palette/dracula\";\n\n.md-typeset .admonition {\n border-width: 0;\n border-left-width: 4px;\n}\n\n$new-admonitions: (\n settings config: dracula.$drac-pink material_color.$clr-purple-a700 \"@mdi/svg/svg/cog.svg\",\n new: dracula.$drac-yellow material_color.$clr-yellow-a700 \"@mdi/svg/svg/alert-decagram.svg\"\n) !default;\n\n $old-admonitions: (\n note: dracula.$drac-dark-yellow,\n abstract: dracula.$drac-cyan,\n info: dracula.$drac-light-blue,\n tip: dracula.$drac-teal,\n success: dracula.$drac-green,\n question: dracula.$drac-light-green,\n warning: dracula.$drac-orange,\n failure: dracula.$drac-dark-red,\n danger: dracula.$drac-red,\n bug: dracula.$drac-dark-pink,\n example: dracula.$drac-purple,\n quote: dracula.$drac-grey\n ) !default;\n\n/* Style new admonitions with dark or light colors */\n:root > * {\n --md-admonition-bg-color: transparent;\n\n &[data-md-color-scheme=\"dracula\"] {\n --md-admonition-icon-color: dracula.$drac-dark-yellow;\n }\n\n @each $names, $prop in $new-admonitions {\n $tint: list.nth($prop, 1);\n $tint2: list.nth($prop, 2);\n $name: list.nth($names, 1);\n\n & {\n --md-admonition-icon--#{$name}: svg-load(\"#{list.nth($prop, 3)}\");\n --md-admonition-bg-color--#{$name}: #{color.adjust($tint2, $alpha: -0.9)};\n --md-admonition-icon-color--#{$name}: #{$tint2};\n --md-admonition-shadow-color--#{$name}: #{color.adjust($tint2, $alpha: -0.9)};\n }\n\n &[data-md-color-scheme=\"dracula\"] {\n --md-admonition-bg-color--#{$name}: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--#{$name}: #{$tint};\n --md-admonition-shadow-color--#{$name}: #{color.adjust($tint, $alpha: -0.9)};\n }\n\n @each $names, $tint in $old-admonitions {\n $name: list.nth($names, 1);\n\n & {\n --md-admonition-bg-color--#{$name}: var(--md-default-bg-color--ultra-dark);\n --md-admonition-icon-color--#{$name}: #{$tint};\n --md-admonition-shadow-color--#{$name}: #{color.adjust($tint, $alpha: 0.9)};\n }\n }\n }\n}\n\n/* Dark mode changes */\n[data-md-color-scheme=\"dracula\"] .md-typeset .admonition {\n border-color: var(--md-admonition-icon-color--note);\n box-shadow: var(--md-shadow-z2);\n\n &:focus-within {\n box-shadow: 0 0 0 convert.px2rem(4px) var(--md-admonition-shadow-color--note);\n }\n\n > .admonition-title {\n background-color: var(--md-admonition-bg-color--note);\n &::before {\n background-color: var(--md-admonition-icon-color--note);\n }\n &::after {\n color: var(--md-admonition-icon-color--note);\n }\n }\n}\n\n/* Style existing admonitions with dark mode colors */\n[data-md-color-scheme=\"dracula\"] {\n\n @each $names, $prop in $old-admonitions {\n\n $name: list.nth($names, 1);\n\n // Define base class\n .md-typeset .admonition.#{$name} {\n border-color: var(--md-admonition-icon-color--#{$name});\n\n &:focus-within {\n box-shadow: 0 0 0 convert.px2rem(4px) var(--md-admonition-shadow-color--#{$name});\n }\n\n // Define base class\n > .admonition-title {\n background-color: var(--md-admonition-bg-color--#{$name});\n border-color: var(--md-admonition-icon-color--#{$name});\n\n // Icon\n &::before {\n background-color: var(--md-admonition-icon-color--#{$name});\n }\n &::after {\n color: var(--md-admonition-icon-color--#{$name});\n }\n }\n }\n\n // Define synonyms for base class\n @if list.length($names) > 1 {\n @for $n from 2 through list.length($names) {\n .#{list.nth($names, $n)} {\n @extend .#{$name};\n }\n }\n }\n }\n}\n\n@each $names, $prop in $new-admonitions {\n $name: list.nth($names, 1);\n\n // Define base class\n .md-typeset .admonition.#{$name} {\n border-color: var(--md-admonition-icon-color--#{$name});\n\n &:focus-within {\n box-shadow: 0 0 0 convert.px2rem(4px) var(--md-admonition-shadow-color--#{$name});\n }\n\n > .admonition-title {\n background-color: var(--md-admonition-bg-color--#{$name});\n border-color: var(--md-admonition-icon-color--#{$name});\n\n // Icon\n &::before {\n width: convert.px2rem(20px);\n height: convert.px2rem(20px);\n background-color: var(--md-admonition-icon-color--#{$name});\n background-size: convert.px2rem(20px);\n mask-image: var(--md-admonition-icon--#{$name});\n content: \"\\a0\";\n }\n &::after {\n color: var(--md-admonition-icon-color--#{$name});\n }\n }\n }\n\n // Define synonyms for base class\n @if list.length($names) > 1 {\n @for $n from 2 through list.length($names) {\n .#{list.nth($names, $n)} {\n @extend .#{$name};\n }\n }\n }\n}\n","mjx-container[display=true] {\n font-size: 120% !important;\n}\n\nmjx-container:not([display]) {\n font-size: 100% !important;\n}\n\n[data-md-color-scheme=\"slate\"],\n[data-md-color-scheme=\"dracula\"] {\n /* stylelint-disable selector-class-pattern */\n .CtxtMenu_InfoSignature input,\n .CtxtMenu_InfoContent pre {\n color: rgb(0, 0, 0);\n }\n .CtxtMenu_Info,\n .CtxtMenu_Menu {\n box-shadow: 0px 10px 20px rgb(0 0 0 / 0.5);\n }\n /* stylelint-enable selector-class-pattern */\n}\n\n.md-typeset .arithmatex {\n overflow-x: auto !important;\n overflow-y: hidden !important;\n}\n\n// Fix tag overlap in `KaTeX`\n.katex-display {\n .katex-html {\n display: flex !important;\n flex-direction: row;\n flex-wrap: nowrap;\n align-items: baseline;\n justify-content: space-between;\n // overflow-x: auto;\n\n .base {\n display: inline !important;\n }\n\n .tag {\n position: relative !important;\n display: inline !important;\n margin-left: var(--margin-small);\n }\n }\n}\n","@use \"../utilities/convert\";\n\n/* Don't use box shadows */\n.md-typeset {\n del,\n ins,\n mark {\n &.critic {\n padding: 0 convert.px2em(4px, 16px);\n color: unset;\n box-shadow: none;\n }\n }\n\n .critic.break {\n margin: 0;\n }\n}\n","@use \"./admonition\";\n\n/* Inherit admonition style */\n.md-typeset {\n details {\n @extend .admonition;\n\n overflow: hidden;\n\n // Title\n > summary {\n @extend .admonition-title;\n\n // Disable accessibility focus\n &:focus {\n outline-style: none;\n }\n }\n }\n}\n","@use \"../utilities/break\";\n@use \"../utilities/convert\";\n\n.highlight {\n .kc { // Keyword constant\n color: var(--md-code-hl-constant-color);\n }\n\n .nc, // Name, class\n .ne, // Name, exception\n {\n color: var(--md-code-hl-class-color);\n }\n\n .mb {\n color: var(--md-code-hl-number-color);\n }\n\n .nb, // Name, builtin\n .bp { // Name, builtin pseudo\n color: var(--md-code-hl-builtin-color);\n }\n\n .nn { // Name, namespace Name, namespace Name, namespace Name, namespace\n color: var(--md-code-hl-namespace-color);\n }\n\n .na, // Name, attribute\n .nd, // Name, decorator\n .ni { // Name, entity\n color: var(--md-code-hl-entity-color);\n }\n .nl, // Name, label\n .nt { // Name, tag\n color: var(--md-code-hl-tag-color);\n }\n}\n\n.md-typeset {\n\n /* Allow code to look like code everywhere despite Material's current preference */\n *:not(pre) > code {\n margin: 0;\n padding: 0 convert.px2em( 4px, 13.6px);\n color: var(--md-code-fg-color);\n background-color: var(--md-code-inline-bg-color);\n border-radius: px2rem(2px);\n box-shadow: none;\n }\n\n /* Code that is also a link */\n a {\n > code {\n color: inherit !important;\n background-color: var(--md-code-link-bg-color) !important;\n transition: color 125ms;\n transition: background-color 125ms;\n\n /* If we are linking highlighted, inline code, force it to just look like a code link */\n * {\n color: var(--md-typeset-a-color) !important;\n }\n\n &:hover {\n background-color: var(--md-code-link-accent-bg-color) !important;\n\n * {\n color: var(--md-accent-fg-color) !important;\n }\n }\n }\n }\n\n pre > code {\n outline: none;\n }\n\n /* Don't always like code breaking in table cells */\n td code {\n word-break: normal;\n }\n\n .highlight {\n\n /* Needed for tab preserving mode */\n tab-size: 8;\n\n + .result {\n border-width: px2rem(2px);\n }\n\n /* `pymdownx-inline` mode */\n [data-linenos] {\n\n /* Special line mode coloring */\n &.special::before {\n background-color: var(--md-code-special-bg-color);\n }\n }\n }\n\n /* Special line number coloring for tables */\n .highlighttable {\n .linenodiv {\n .special {\n margin-right: convert.px2em(-8px, 13.6px);\n margin-left: convert.px2em(-16px, 13.6px);\n padding-right: convert.px2em(8px, 13.6px);\n padding-left: convert.px2em(16px, 13.6px);\n background-color: var(--md-code-special-bg-color);\n }\n }\n }\n\n // Filename span\n .highlight span.filename {\n\n // Style the filename banner\n position: relative;\n display: block;\n margin-top: 1em;\n padding: convert.px2em(8px) convert.px2em(16px, 13.6px) convert.px2em(8px) convert.px2em(40px, 13.6px);\n font-weight: 700;\n font-size: px2rem(13.6px);\n background-color: var(--md-code-title-bg-color);\n border-top-left-radius: px2rem(2px);\n border-top-right-radius: px2rem(2px);\n\n // Adjust margins and and general container look of code block\n + pre {\n margin-top: 0;\n\n code {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n }\n\n // Add code icon\n &::before {\n position: absolute;\n left: convert.px2em(12px, 13.6px);\n width: convert.px2em(20px, 13.6px);\n height: convert.px2em(20px, 13.6px);\n background-color: var(--md-default-fg-color);\n mask-image: svg-load(\"@mdi/svg/svg/console.svg\");\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n }\n\n .collapse-code {\n position: relative;\n margin-top: 1em;\n margin-bottom: 1em;\n\n pre {\n margin-top: 0;\n margin-bottom: 0;\n }\n\n input{\n display: none;\n\n ~ .code-footer {\n width: 100%;\n margin: 0;\n padding: convert.px2em(4px) convert.px2em(8px) convert.px2em(4px) convert.px2em(0px);\n\n label {\n position: relative;\n margin: 0.05em;\n padding: 0.15em 0.8em;\n color: var(--md-primary-bg-color);\n font-size: 90%;\n background-color: var(--md-primary-fg-color);\n mask-repeat: no-repeat;\n mask-size: contain;\n border-radius: px2rem(2px);\n cursor: pointer;\n content: \"\";\n\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n\n &::before {\n position: absolute;\n top: 0.15em;\n left: 0.15em;\n display: block;\n box-sizing: border-box;\n width: 1.25em;\n height: 1.25em;\n background-color: var(--md-primary-bg-color);\n background-size: 1.25em;\n content: \"\";\n }\n\n &.expand {\n display: none;\n\n &::before {\n mask-image: svg-load(\"@mdi/svg/svg/arrow-expand.svg\");\n }\n }\n &.collapse::before {\n mask-image: svg-load(\"@mdi/svg/svg/arrow-collapse.svg\");\n }\n }\n }\n\n &:checked {\n ~ .code-footer label.expand {\n display: inline;\n }\n\n ~ .code-footer label.collapse {\n display: none;\n }\n\n + div.highlight code {\n max-height: convert.px2em(150px);\n overflow: hidden;\n }\n\n ~ .code-footer {\n position: absolute;\n bottom: 0;\n left: 0;\n padding: convert.px2em(32px) convert.px2em(8px) convert.px2em(8px) px2rem(16px);\n background-image: linear-gradient(to bottom,\n transparent,\n var(--md-default-bg-color) 80%\n 100%);\n }\n }\n }\n }\n\n @include break.break-to-device(mobile) {\n\n > {\n diagram-div {\n margin-right: px2rem(-16px);\n margin-left: px2rem(-16px);\n }\n .collapse-code {\n margin-right: px2rem(-16px);\n margin-left: px2rem(-16px);\n\n label.collapse {\n left: px2rem(16px);\n }\n }\n }\n }\n}\n","@use \"../utilities/convert\";\n\n.md-typeset {\n\n // Keyboard key\n .keys {\n\n // Define keyboard keys with left icon\n @each $name, $code in (\n // Extra Keys\n \"power\": \"\\23FB\",\n \"fingerprint\": \"\\261D\",\n ) {\n .key-#{$name}::before {\n padding-right: convert.px2em(6.4px);\n content: $code;\n }\n }\n\n // Define keyboard keys with right icon\n @each $name, $code in (\n // Extra Keys\n ) {\n .key-#{$name}::after {\n padding-left: convert.px2em(6.4px);\n content: $code;\n }\n }\n }\n}\n","@use \"../utilities/convert\";\n\n// General styling for repository link icons\n:root > * {\n --magiclink-email-icon: svg-load(\"@mdi/svg/svg/mail.svg\");\n --magiclink-github-icon: svg-load(\"@mdi/svg/svg/github.svg\");\n --magiclink-bitbucket-icon: svg-load(\"@mdi/svg/svg/bitbucket.svg\");\n --magiclink-gitlab-icon: svg-load(\"@mdi/svg/svg/gitlab.svg\");\n --magiclink-commit-icon: svg-load(\"@primer/octicons/build/svg/git-commit-24.svg\");\n --magiclink-compare-icon: svg-load(\"@primer/octicons/build/svg/file-diff-24.svg\");\n --magiclink-pull-icon: svg-load(\"@primer/octicons/build/svg/git-pull-request-24.svg\");\n --magiclink-issue-icon: svg-load(\"@primer/octicons/build/svg/issue-opened-24.svg\");\n --magiclink-discussion-icon: svg-load(\"@primer/octicons/build/svg/comment-discussion-24.svg\");\n}\n\n.md-typeset {\n a[href^=\"mailto:\"]:not(.magiclink-ignore)::before {\n mask-image: var(--magiclink-email-icon);\n }\n\n .magiclink-repository,\n .magiclink-compare,\n .magiclink-commit,\n .magiclink-pull,\n .magiclink-issue,\n .magiclink-discussion,\n a[href^=\"mailto:\"] {\n &:not(.magiclink-ignore) {\n position: relative;\n padding-left: convert.px2em(22px);\n\n &::before {\n position: absolute;\n top: 0;\n left: 0;\n display: block;\n box-sizing: border-box;\n width: convert.px2em(20px);\n height: convert.px2em(20px);\n background-color: var(--md-typeset-a-color);\n background-size: convert.px2em(20px);\n transition: background-color 125ms;\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n\n &:hover::before {\n background-color: var(--md-accent-fg-color);\n }\n }\n }\n}\n\n// Assign icons to repository links\n@each $name, $icon in (\n \"commit\": \"commit\",\n \"compare\": \"compare\",\n \"pull\": \"pull\",\n \"issue\": \"issue\",\n \"discussion\": \"discussion\"\n) {\n .md-typeset {\n .magiclink-#{$name}:not(.magiclink-ignore) {\n &::before {\n mask-image: var(--magiclink-#{$icon}-icon);\n }\n }\n }\n}\n\n// Assign icons to repository links\n@each $name, $icon in (\n \"github\": \"github\",\n \"gitlab\": \"gitlab\",\n \"bitbucket\": \"bitbucket\"\n) {\n .md-typeset {\n .magiclink-repository.magiclink-#{$name}:not(.magiclink-ignore) {\n &::before {\n mask-image: var(--magiclink-#{$icon}-icon);\n }\n }\n }\n}\n","/* Shadow boxes sometimes give issues, so just pad. */\n.md-typeset mark:not(.critic) {\n box-shadow: none;\n}\n","@use \"../palette/material_color\";\n@use \"../utilities/convert\";\n\n.md-typeset {\n\n /* Progress Bars */\n .progress-label {\n position: absolute;\n width: 100%;\n margin: 0;\n color: var(--md-text-color);\n font-weight: 700;\n line-height: convert.px2rem(28px);\n white-space: nowrap;\n text-align: center;\n text-shadow:\n convert.px2em(-1px) convert.px2em(-1px) convert.px2em(6px) var(--md-default-bg-color--light),\n convert.px2em(1px) convert.px2em(-1px) convert.px2em(6px) var(--md-default-bg-color--light),\n convert.px2em(-1px) convert.px2em(1px) convert.px2em(6px) var(--md-default-bg-color--light),\n convert.px2em(1px) convert.px2em(1px) convert.px2em(6px) var(--md-default-bg-color--light);\n }\n\n .progress-bar {\n float: left;\n height: convert.px2rem(24px);\n background-color: material_color.$clr-blue-a400;\n }\n\n /* Stripe animation */\n .candystripe-animate {\n .progress-bar{\n animation: animate-stripes 3s linear infinite;\n }\n }\n\n .progress {\n position: relative;\n display: block;\n width: 100%;\n height: convert.px2rem(24px);\n margin: convert.px2rem(10px) 0;\n background-color: var(--md-default-fg-color--lightest);\n\n &.thin {\n height: convert.px2rem(8px);\n margin-top: convert.px2rem(18px);\n\n .progress-label {\n margin-top: convert.px2rem(-8px);\n }\n\n .progress-bar {\n height: convert.px2rem(8px);\n }\n }\n\n &.candystripe .progress-bar {\n background-image:\n linear-gradient(\n 135deg,\n var(--md-progress-stripe) 27%,\n transparent 27%,\n transparent 52%,\n var(--md-progress-stripe) 52%,\n var(--md-progress-stripe) 77%,\n transparent 77%,\n transparent\n );\n background-size: convert.px2rem(40px) convert.px2rem(40px);\n }\n }\n\n @each $percent, $color in (\n \"100\": var(--md-progress-100),\n \"80\": var(--md-progress-80),\n \"60\": var(--md-progress-60),\n \"40\": var(--md-progress-40),\n \"20\": var(--md-progress-20),\n \"0\": var(--md-progress-0)\n ) {\n .progress-#{$percent}plus {\n .progress-bar {\n background-color: $color;\n }\n }\n }\n\n @keyframes animate-stripes {\n 0% {\n background-position: 0 0;\n }\n\n 100% {\n background-position: convert.px2rem(120px) 0;\n }\n }\n}\n","@use \"../utilities/break\";\n@use \"../utilities/convert\";\n\n/* Dark mode changes */\n[data-md-color-scheme=\"dracula\"] {\n .md-typeset {\n .tabbed-set > .tabbed-labels {\n box-shadow: 0 convert.px2rem(-1px) var(--md-default-fg-color--lighter) inset;\n }\n }\n}\n\n/* Style code blocks to fill full tab,\n but otherwise, pad content. */\n.md-typeset {\n .tabbed-alternate {\n &.tabbed-set .tabbed-control {\n width: convert.px2rem(40px);\n\n &[hidden] {\n width: convert.px2rem(24px);\n opacity: 0;\n }\n }\n\n &.tabbed-set > .tabbed-content > .tabbed-block {\n padding: 0 convert.px2rem(12px);\n\n > {\n pre,\n .codehilite,\n .codehilitetable,\n .highlight,\n .highlighttable {\n\n &:only-child {\n margin-right: convert.px2rem(-24px);\n margin-left: convert.px2rem(-24px);\n padding-right: convert.px2rem(12px);\n padding-left: convert.px2rem(12px);\n\n span.filename {\n margin-top: 0;\n }\n }\n }\n\n .collapse-code:only-child {\n margin-top: 0;\n\n margin-right: convert.px2rem(-24px);\n margin-left: convert.px2rem(-24px);\n padding-right: convert.px2rem(12px);\n padding-left: convert.px2rem(12px);\n\n > .code-footer {\n left: convert.px2rem(12px)\n }\n }\n\n diagram-div:only-child {\n margin-right: convert.px2rem(-24px);\n margin-left: convert.px2rem(-24px);\n padding-right: convert.px2rem(12px);\n padding-left: convert.px2rem(12px);\n }\n }\n }\n }\n}\n\n.js .md-typeset .tabbed-labels::before {\n background-color: var(--md-accent-fg-color);\n}\n\n/* Ignore mobile overflow styling that extends the tab bar */\n@include break.break-to-device(mobile) {\n [dir=ltr] .md-content__inner > .tabbed-set .tabbed-labels {\n padding-left: 0;\n }\n\n .md-content__inner > .tabbed-set .tabbed-labels {\n max-width: 100%;\n margin: 0;\n padding-inline-start: 0;\n scroll-padding-inline-start: 0;\n\n &::after {\n padding-inline-end: 0;\n content: none;\n }\n\n // Tabbed control previous\n ~ .tabbed-control--prev {\n margin-inline-start: 0;\n padding-inline-start: 0;\n }\n\n // Tabbed control next\n ~ .tabbed-control--next {\n margin-inline-end: 0;\n padding-inline-end: 0;\n }\n }\n}\n","@use \"../utilities/convert\";\n\n/* Dark mode changes */\n[data-md-color-scheme=\"dracula\"] {\n .md-typeset table:not([class]) {\n box-shadow: var(--md-shadow-z2);\n\n tr:hover {\n background-color: rgba(0,0,0,.08);\n }\n\n th {\n color: var(--md-text-color);\n background-color: var(--md-default-bg-color--ultra-dark);\n border-bottom: convert.px2rem(1px) solid var(--md-primary-fg-color);\n }\n\n td {\n border-top: convert.px2rem(1px) solid var(--md-default-fg-color--lighter);\n }\n }\n}\n","@use \"palette/dracula\";\n\n/* Dark mode changes */\n[data-md-color-scheme=\"dracula\"] {\n .md-typeset .task-list-control {\n .task-list-indicator::before {\n \tbackground-color: var(--md-default-fg-color--lighter);\n }\n\n [type=checkbox]:checked + .task-list-indicator::before {\n \tbackground-color: dracula.$drac-green;\n }\n }\n}\n","@use \"../utilities/convert\";\n\n// Header anchors\n.md-typeset {\n .headerlink {\n width: convert.px2em(16px);\n height: convert.px2em(16px);\n vertical-align: middle;\n background-color: var(--md-default-fg-color--lighter);\n background-size: convert.px2em(16px);\n mask-size: convert.px2em(16px);\n mask-repeat: no-repeat;\n visibility: visible;\n mask-image: svg-load(\"@mdi/svg/svg/link.svg\");\n }\n\n .headerlink:hover,\n [id]:target .headerlink {\n background-color: var(--md-accent-fg-color);\n }\n}\n","/* Special handling of Mermaid content. */\ndiagram-div {\n overflow: auto;\n}\n","@use \"utilities/break\";\n@use \"utilities/convert\";\n\nhtml {\n background-color: transparent;\n}\n\n[data-md-component=\"announce\"] .twemoji {\n color: var(--md-primary-fg-color);\n}\n\n/* Dark mode changes */\n[data-md-color-scheme=\"dracula\"] {\n\n --md-text-color: var(--md-default-fg-color);\n background-color: var(--md-default-bg-color);\n\n // Footer color shades\n --md-footer-bg-color: transparent;\n --md-footer-bg-color--dark: var(--md-default-bg-color--darkest);\n\n // Header colors\n --md-header-fg-color: var(--md-text-color);\n --md-header-bg-color: var(--md-default-bg-color--darkest);\n\n // Header\n .md-header {\n color: var(--md-text-color);\n background-color: var(--md-header-bg-color);\n border-bottom: convert.px2rem(1px) solid var(--md-primary-fg-color);\n\n &[data-md-state=shadow] {\n box-shadow: 0 0 convert.px2rem(4px) rgba(0,0,0,.15),\n 0 0 convert.px2rem(4px) convert.px2rem(8px) rgba(0,0,0,.2);\n }\n }\n\n .md-top {\n background-color: var(--md-default-bg-color--dark);\n\n &:hover {\n background-color: var(--md-primary-fg-color);\n }\n }\n\n // Tabs\n .md-tabs {\n color: var(--md-text-color);\n background-color: var(--md-primary-fg-color--transparent);\n\n &__link--active {\n color: var(--md-primary-fg-color);\n }\n\n &__link:hover {\n color: var(--md-accent-fg-color);\n }\n }\n\n // Hero\n .md-hero {\n color: var(--md-text-color);\n background-color: var(--md-primary-fg-color--transparent);\n }\n\n // Navigation\n .md-nav__source {\n color: var(--md-text-color);\n }\n\n .md-nav__link[data-md-state=blur] {\n color: var(--md-default-fg-color--light);\n }\n\n .md-nav__item .md-nav__link--active {\n color: var(--md-primary-fg-color);\n }\n\n .md-nav__link {\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n }\n\n @include break.break-to-device(tablet) {\n\n .md-nav--primary .md-nav__item--active > .md-nav__link:not(:hover) {\n color: var(--md-primary-fg-color);\n }\n\n // Site title in main navigation\n .md-nav--primary .md-nav__title {\n color: var(--md-text-color);\n background-color: var(--md-header-bg-color);\n border-bottom: convert.px2rem(1px) solid var(--md-primary-fg-color);\n }\n }\n\n @include break.break-to-device(tablet portrait) {\n\n // Repository containing source\n .md-nav__source {\n color: var(--md-text-color);\n background-color: var(--md-primary-fg-color--transparent);\n }\n\n .md-nav .md-nav__title {\n color: var(--md-text-color);\n background-color: var(--md-header-bg-color);\n border-bottom: convert.px2rem(1px) solid var(--md-primary-fg-color);\n }\n }\n\n // Search\n .md-search__input {\n color: var(--md-text-color);\n background-color: var(--md-accent-bg-color--light);\n\n &:hover {\n background-color: var(--md-default-bg-color--light);\n }\n\n ~ .md-search__icon {\n color: var(--md-text-color);\n }\n &::placeholder {\n color: var(--md-default-fg-color--light);\n }\n }\n\n [data-md-toggle=search]:checked~.md-header .md-search__input {\n background-color: transparent;\n }\n\n .md-search__suggest {\n color: var(--md-default-autocomplete-fg-color);\n }\n\n .md-search__overlay, .md-overlay {\n background-color: var(--md-default-bg-color--light);\n }\n\n // Footer\n .md-footer {\n &-nav__direction {\n color: var(--md-primary-fg-color);\n }\n\n &-meta {\n border-top: convert.px2rem(1px) solid var(--md-primary-fg-color);\n }\n }\n\n // Announcements\n [data-md-component=\"announce\"] {\n background-color: var(--md-default-bg-color--ultra-dark);\n }\n}\n\n.md-typeset {\n\n /* Don't force capitalization of `H5` elements. */\n h5 {\n color: var(--md-text-color);\n text-transform: none;\n }\n}\n\n.md-typeset__scrollwrap,\n.md-sidebar__scrollwrap,\n.md-search__scrollwrap,\n.md-typeset pre > code,\n.md-typeset div.mermaid,\n.md-typeset div.diagram,\n.md-typeset mermaid-div,\n.md-typeset diagram-div,\n.md-typeset pre.arithmatex,\n.md-typeset div.arithmatex {\n // Firefox scrollbar and thumb\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n scrollbar-width: thin;\n\n // Firefox hovered scrollbar and thumb\n &:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n }\n\n // Override native scrollbar styles\n &::-webkit-scrollbar {\n width: convert.px2rem(4px);\n height: convert.px2rem(4px);\n }\n\n &::-webkit-scrollbar-corner {\n background-color: transparent;\n }\n\n // Scrollbar thumb\n &::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n\n // Hovered scrollbar thumb\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Variables\n// ----------------------------------------------------------------------------\n\n///\n/// Device-specific breakpoints\n///\n/// @example\n/// $break-devices: (\n/// mobile: (\n/// portrait: 220px 479px,\n/// landscape: 480px 719px\n/// ),\n/// tablet: (\n/// portrait: 720px 959px,\n/// landscape: 960px 1219px\n/// ),\n/// screen: (\n/// small: 1220px 1599px,\n/// medium: 1600px 1999px,\n/// large: 2000px\n/// )\n/// );\n///\n@use \"sass:map\";\n@use \"sass:list\";\n@use \"sass:meta\";\n@use \"./convert\";\n\n$break-devices: (\n mobile: (\n portrait: convert.px2em(220px) convert.px2em(479px),\n landscape: convert.px2em(480px) convert.px2em(719px)\n ),\n tablet: (\n portrait: convert.px2em(720px) convert.px2em(959px),\n landscape: convert.px2em(960px) convert.px2em(1219px)\n ),\n screen: (\n small: convert.px2em(1220px) convert.px2em(1599px),\n medium: convert.px2em(1600px) convert.px2em(1999px),\n large: convert.px2em(2000px)\n )\n) !default;\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n///\n/// Choose minimum and maximum device widths\n///\n@function break-select-min-max($devices) {\n $min: 1000000;\n $max: 0;\n @each $key, $value in $devices {\n @while meta.type-of($value) == map {\n $value: break-select-min-max($value);\n }\n @if meta.type-of($value) == list {\n @each $number in $value {\n @if meta.type-of($number) == number {\n $min: min($number, $min);\n @if $max != null {\n $max: max($number, $max);\n }\n } @else {\n @error \"Invalid number: #{$number}\";\n }\n }\n } @else if meta.type-of($value) == number {\n $min: min($value, $min);\n $max: null;\n } @else {\n @error \"Invalid value: #{$value}\";\n }\n }\n @return $min, $max;\n}\n\n///\n/// Select minimum and maximum widths for a device breakpoint\n///\n@function break-select-device($device) {\n $current: $break-devices;\n @for $n from 1 through list.length($device) {\n @if meta.type-of($current) == map {\n $current: map.get($current, list.nth($device, $n));\n } @else {\n @error \"Invalid device map: #{$devices}\";\n }\n }\n @if meta.type-of($current) == list or meta.type-of($current) == number {\n $current: (default: $current);\n }\n @return break-select-min-max($current);\n}\n\n// ----------------------------------------------------------------------------\n// Mixins\n// ----------------------------------------------------------------------------\n\n///\n/// A minimum-maximum media query breakpoint\n///\n@mixin break-at($breakpoint) {\n @if meta.type-of($breakpoint) == number {\n @media screen and (min-width: $breakpoint) {\n @content;\n }\n } @else if meta.type-of($breakpoint) == list {\n $min: list.nth($breakpoint, 1);\n $max: list.nth($breakpoint, 2);\n @if meta.type-of($min) == number and meta.type-of($max) == number {\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// An orientation media query breakpoint\n///\n@mixin break-at-orientation($breakpoint) {\n @if meta.type-of($breakpoint) == string {\n @media screen and (orientation: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A maximum-aspect-ratio media query breakpoint\n///\n@mixin break-at-ratio($breakpoint) {\n @if meta.type-of($breakpoint) == number {\n @media screen and (max-aspect-ratio: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A minimum-maximum media query device breakpoint\n///\n@mixin break-at-device($device) {\n @if meta.type-of($device) == string {\n $device: $device,;\n }\n @if meta.type-of($device) == list {\n $breakpoint: break-select-device($device);\n @if list.nth($breakpoint, 2) != null {\n $min: list.nth($breakpoint, 1);\n $max: list.nth($breakpoint, 2);\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A minimum media query device breakpoint\n///\n@mixin break-from-device($device) {\n @if meta.type-of($device) == string {\n $device: $device,;\n }\n @if meta.type-of($device) == list {\n $breakpoint: break-select-device($device);\n $min: list.nth($breakpoint, 1);\n @media screen and (min-width: $min) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A maximum media query device breakpoint\n///\n@mixin break-to-device($device) {\n @if meta.type-of($device) == string {\n $device: $device,;\n }\n @if meta.type-of($device) == list {\n $breakpoint: break-select-device($device);\n $max: list.nth($breakpoint, 2);\n @media screen and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n"]}
diff --git a/docs/assets/css/extra.css b/docs/assets/css/extra.css
new file mode 100644
index 0000000..054ac92
--- /dev/null
+++ b/docs/assets/css/extra.css
@@ -0,0 +1,48 @@
+/* Symbols in Navigation and ToC. */
+:root, :host,
+[data-md-color-scheme="default"] {
+ --doc-symbol-parameter-fg-color: #df50af;
+ --doc-symbol-attribute-fg-color: #953800;
+ --doc-symbol-function-fg-color: #8250df;
+ --doc-symbol-method-fg-color: #8250df;
+ --doc-symbol-class-fg-color: #0550ae;
+ --doc-symbol-module-fg-color: #5cad0f;
+
+ --doc-symbol-parameter-bg-color: #df50af1a;
+ --doc-symbol-attribute-bg-color: #9538001a;
+ --doc-symbol-function-bg-color: #8250df1a;
+ --doc-symbol-method-bg-color: #8250df1a;
+ --doc-symbol-class-bg-color: #0550ae1a;
+ --doc-symbol-module-bg-color: #5cad0f1a;
+}
+
+[data-md-color-scheme="dracula"] {
+ --doc-symbol-parameter-fg-color: #ffa8cc;
+ --doc-symbol-attribute-fg-color: #ffa657;
+ --doc-symbol-function-fg-color: #d2a8ff;
+ --doc-symbol-method-fg-color: #d2a8ff;
+ --doc-symbol-class-fg-color: #79c0ff;
+ --doc-symbol-module-fg-color: #baff79;
+
+ --doc-symbol-parameter-bg-color: #ffa8cc1a;
+ --doc-symbol-attribute-bg-color: #ffa6571a;
+ --doc-symbol-function-bg-color: #d2a8ff1a;
+ --doc-symbol-method-bg-color: #d2a8ff1a;
+ --doc-symbol-class-bg-color: #79c0ff1a;
+ --doc-symbol-module-bg-color: #baff791a;
+}
+
+code.doc-symbol-heading.doc-symbol-module {
+ color: var(--doc-symbol-module-fg-color) !important;
+ background-color: var(--doc-symbol-module-bg-color) !important;
+}
+
+code.doc-symbol-heading.doc-symbol-class {
+ color: var(--doc-symbol-class-fg-color) !important;
+ background-color: var(--doc-symbol-class-bg-color) !important;
+}
+
+code.doc-symbol-heading.doc-symbol-method {
+ color: var(--doc-symbol-method-fg-color) !important;
+ background-color: var(--doc-symbol-method-bg-color) !important;
+}
diff --git a/docs/assets/images/favicon.png b/docs/assets/images/favicon.png
new file mode 100644
index 0000000..7ebe95b
Binary files /dev/null and b/docs/assets/images/favicon.png differ
diff --git a/docs/assets/images/logo-round.svg b/docs/assets/images/logo-round.svg
new file mode 100644
index 0000000..5950813
--- /dev/null
+++ b/docs/assets/images/logo-round.svg
@@ -0,0 +1,119 @@
+
+
+
+
diff --git a/docs/assets/images/logo.svg b/docs/assets/images/logo.svg
new file mode 100644
index 0000000..e6e9474
--- /dev/null
+++ b/docs/assets/images/logo.svg
@@ -0,0 +1,119 @@
+
+
+
+
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..6b3ed6e
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,252 @@
+# TheCodeCrate's Pipeline
+
+This package provides a pipeline pattern implementation.
+
+The implementation is inspired by the excellent [PHP League Pipeline](https://github.com/thephpleague/pipeline) package.
+
+## Installation
+
+```bash
+pip install thecodecrate-pipeline
+```
+
+## Pipeline Pattern
+
+The pipeline pattern allows you to easily compose sequential stages by chaining stages.
+
+In this particular implementation, the interface consists of two parts:
+
+- `StageInterface`
+- `PipelineInterface`
+
+A pipeline consists of zero, one, or multiple stages. A pipeline can process a payload. During the processing, the payload will be passed to the first stage. From that moment on, the resulting value is passed on from stage to stage.
+
+In the simplest form, the execution chain can be represented as a for loop:
+
+```python
+result = payload
+
+for stage in stages:
+ result = stage(result)
+
+return result
+```
+
+Effectively, this is the same as:
+
+```python
+result = stage3(stage2(stage1(payload)))
+```
+
+## Immutability
+
+Pipelines are implemented as immutable stage chains. When you pipe a new stage, a new pipeline will be created with the added stage. This makes pipelines easy to reuse and minimizes side-effects.
+
+## Usage
+
+Operations in a pipeline, stages, can be anything that satisfies the `Callable` type hint. So functions and anything that's callable is acceptable.
+
+```python
+pipeline = Pipeline().pipe(lambda payload: payload * 10)
+
+# Returns 100
+await pipeline.process(10)
+```
+
+## Class-Based Stages
+
+Class-based stages are also possible. The `StageInterface[InputType, OutputType]` interface can be implemented, which ensures you have the correct method signature for the `__call__` method.
+
+```python
+class TimesTwoStage(StageInterface[int, int]):
+ async def __call__(self, payload: int) -> int:
+ return payload * 2
+
+class AddOneStage(StageInterface[int, int]):
+ async def __call__(self, payload: int) -> int:
+ return payload + 1
+
+pipeline = (
+ Pipeline[int, int]()
+ .pipe(TimesTwoStage())
+ .pipe(AddOneStage())
+)
+
+# Returns 21
+await pipeline.process(10)
+```
+
+## Reusable Pipelines
+
+Because the `PipelineInterface` is an extension of the `StageInterface`, pipelines can be reused as stages. This creates a highly composable model to create complex execution patterns while keeping the cognitive load low.
+
+For example, if we'd want to compose a pipeline to process API calls, we'd create something along these lines:
+
+```python
+process_api_request = (
+ Pipeline()
+ .pipe(ExecuteHttpRequest())
+ .pipe(ParseJsonResponse())
+)
+
+pipeline = (
+ Pipeline()
+ .pipe(ConvertToPsr7Request())
+ .pipe(process_api_request)
+ .pipe(ConvertToResponseDto())
+)
+
+await pipeline.process(DeleteBlogPost(post_id))
+```
+
+## Type Hinting
+
+You can specify the input and output types for pipelines and stages using type variables `T_in` and `T_out`. This allows you to handle varying types between stages, enhancing type safety and code clarity.
+
+The `T_out` type variable is optional and defaults to `T_in`. Similarly, `T_in` is also optional and defaults to `Any`.
+
+```python
+from typing import Any
+
+pipeline = Pipeline[int]().pipe(lambda payload: payload * 2)
+
+# Returns 20
+await pipeline.process(10)
+```
+
+You can also handle varying types between stages:
+
+```python
+pipeline = Pipeline[int, str]().pipe(lambda payload: f"Number: {payload}")
+
+# Returns "Number: 10"
+await pipeline.process(10)
+```
+
+This flexibility allows you to build pipelines that transform data types between stages seamlessly.
+
+## Custom Processors
+
+You can create your own processors to customize how the pipeline processes stages. This allows you to implement different execution strategies, such as handling exceptions, processing resources, or implementing middleware patterns.
+
+For example, you can define a custom processor:
+
+```python
+class MyCustomProcessor(Processor[T_in, T_out]):
+ async def process(
+ self,
+ payload: T_in,
+ stages: StageInstanceCollection,
+ ) -> T_out:
+ # Custom processing logic
+ for stage in stages:
+ payload = await stage(payload)
+ return payload
+```
+
+And use it in your pipeline:
+
+```python
+pipeline = Pipeline[int, int](processor=MyCustomProcessor()).pipe(lambda x: x * 2)
+```
+
+## Declarative Stages
+
+Instead of using `pipe` to add stages at runtime, you can define stages declaratively by specifying them as class-level attributes. This makes pipelines easier to set up and reuse with predefined stages.
+
+```python
+class MyPipeline(Pipeline[int, int]):
+ stages = [
+ TimesTwoStage(),
+ TimesThreeStage(),
+ ]
+
+# Process the payload through the pipeline with the declared stages
+result = await MyPipeline().process(5)
+
+# Returns 30
+print(result)
+```
+
+In this example, `MyPipeline` declares its stages directly in the class definition, making the pipeline setup more readable and maintainable.
+
+## Declarative Processor
+
+You can also specify the processor in a declarative way by setting the `processor_class` attribute in your pipeline class.
+
+```python
+class MyPipeline(Pipeline[T_in, T_out]):
+ processor_class = MyCustomProcessor
+```
+
+This allows you to customize the processing behavior of your pipeline while keeping the definition clean and declarative.
+
+## Processing Streams
+
+The pipeline can also process streams in real-time, allowing you to handle asynchronous iterators and process data as it becomes available.
+
+```python
+from typing import AsyncIterator
+import asyncio
+
+async def input_stream() -> AsyncIterator[int]:
+ for i in range(5):
+ yield i
+
+async def stage1(stream: AsyncIterator[int]) -> AsyncIterator[int]:
+ async for item in stream:
+ yield item * 2
+ await asyncio.sleep(1) # Simulate processing delay
+
+async def stage2(stream: AsyncIterator[int]) -> AsyncIterator[str]:
+ async for item in stream:
+ yield f"Number: {item}"
+
+
+async def main():
+ pipeline = (
+ Pipeline[AsyncIterator[int], AsyncIterator[str]]()
+ .pipe(stage1)
+ .pipe(stage2)
+ )
+
+ stream = await pipeline.process(input_stream())
+
+ async for result in stream:
+ print(result)
+
+# Run the async main function
+await main()
+```
+
+This allows you to process data in a streaming fashion, where each stage can yield results that are immediately consumed by the next stage.
+
+## Pipeline Factory
+
+Because pipelines themselves are immutable, pipeline factory is introduced to facilitate distributed composition of a pipeline.
+
+The `PipelineFactory[InputType, OutputType]` collects stages and allows you to create a pipeline at any given time.
+
+```python
+pipeline_factory = PipelineFactory().with_stages([LogicalStage(), AddOneStage()])
+
+# Additional stages can be added later
+pipeline_factory.add_stage(LastStage()).with_processor(MyCustomProcessor())
+
+# Build the pipeline
+pipeline = pipeline_factory.build()
+```
+
+## Exception Handling
+
+This package is completely transparent when dealing with exceptions. In no case will this package catch an exception or silence an error. Exceptions should be dealt with on a per-case basis, either inside a _stage_ or at the time the pipeline processes a payload.
+
+```python
+pipeline = Pipeline().pipe(lambda payload: payload / 0)
+
+try:
+ await pipeline.process(10)
+except ZeroDivisionError as e:
+ # Handle the exception.
+ pass
+```
diff --git a/jupyter/01-playground.ipynb b/jupyter/01-playground.ipynb
index 14eadc5..10add74 100644
--- a/jupyter/01-playground.ipynb
+++ b/jupyter/01-playground.ipynb
@@ -9,7 +9,18 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from thecodecrate_pipeline import Pipeline\n",
+ "\n",
+ "pipeline = Pipeline()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
"metadata": {},
"outputs": [
{
@@ -18,7 +29,7 @@
"'result is 3'"
]
},
- "execution_count": 7,
+ "execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -43,7 +54,7 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 3,
"metadata": {},
"outputs": [
{
@@ -52,7 +63,7 @@
"21"
]
},
- "execution_count": 8,
+ "execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@@ -84,7 +95,7 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 4,
"metadata": {},
"outputs": [
{
@@ -93,7 +104,7 @@
"36"
]
},
- "execution_count": 9,
+ "execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -123,7 +134,7 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 5,
"metadata": {},
"outputs": [
{
@@ -132,7 +143,7 @@
"36"
]
},
- "execution_count": 10,
+ "execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
@@ -155,7 +166,7 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 6,
"metadata": {},
"outputs": [
{
@@ -164,7 +175,7 @@
"'hello: 0: 1'"
]
},
- "execution_count": 11,
+ "execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
@@ -252,7 +263,7 @@
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 7,
"metadata": {},
"outputs": [
{
@@ -261,7 +272,7 @@
"12"
]
},
- "execution_count": 12,
+ "execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
@@ -290,7 +301,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "venv",
+ "display_name": ".venv",
"language": "python",
"name": "python3"
},
@@ -304,7 +315,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.13.0"
+ "version": "3.13.1"
}
},
"nbformat": 4,
diff --git a/jupyter/02-streams.ipynb b/jupyter/02-streams.ipynb
index efc4177..834a429 100644
--- a/jupyter/02-streams.ipynb
+++ b/jupyter/02-streams.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 1,
"metadata": {},
"outputs": [
{
@@ -56,7 +56,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "venv",
+ "display_name": ".venv",
"language": "python",
"name": "python3"
},
@@ -70,7 +70,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.13.0"
+ "version": "3.13.1"
}
},
"nbformat": 4,
diff --git a/jupyter/03-pipeline-factory.ipynb b/jupyter/03-pipeline-factory.ipynb
index fa77420..8a9358b 100644
--- a/jupyter/03-pipeline-factory.ipynb
+++ b/jupyter/03-pipeline-factory.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
"outputs": [
{
@@ -39,7 +39,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"metadata": {},
"outputs": [
{
@@ -90,7 +90,7 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 3,
"metadata": {},
"outputs": [
{
@@ -98,7 +98,7 @@
"output_type": "stream",
"text": [
"result is 12\n",
- "<__main__.MyProcessor object at 0x7b8db67dd940>\n"
+ "<__main__.MyProcessor object at 0x7c51b8bf6120>\n"
]
}
],
@@ -134,7 +134,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "venv",
+ "display_name": ".venv",
"language": "python",
"name": "python3"
},
@@ -148,7 +148,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.13.0"
+ "version": "3.13.1"
}
},
"nbformat": 4,
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..e35292f
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,150 @@
+site_name: "TheCodeCrate's Pipeline"
+site_url: "https://thecodecrate.github.io/python-pipeline"
+repo_url: "https://github.com/thecodecrate/python-pipeline"
+
+extra_css:
+ - assets/css/extra.css
+ - assets/css/extra-pymdownx.css
+
+theme:
+ name: material
+ logo: assets/images/logo.svg
+ favicon: assets/images/favicon.png
+ font:
+ text: Roboto
+ code: Roboto Mono
+ palette:
+ - media: "(prefers-color-scheme)"
+ toggle:
+ icon: material/theme-light-dark
+ name: Switch to light mode
+ - media: "(prefers-color-scheme: light)"
+ scheme: default
+ primary: deep purple
+ accent: deep purple
+ toggle:
+ icon: material/weather-sunny
+ name: Switch to dark mode
+ - media: "(prefers-color-scheme: dark)"
+ scheme: dracula
+ primary: deep purple
+ accent: deep purple
+ toggle:
+ icon: material/weather-night
+ name: Switch to system preference
+
+ features:
+ - content.code.annotate
+ - content.code.copy
+ - content.tabs.link
+ - toc.integrate
+ - toc.follow
+ - navigation.instant
+ - navigation.instant.prefetch
+ - navigation.path
+ - navigation.tabs
+ - navigation.top
+ - navigation.tracking
+
+markdown_extensions:
+ - markdown.extensions.attr_list:
+ - markdown.extensions.md_in_html:
+ - markdown.extensions.toc:
+ anchorlink: true
+ anchorlink_class: "toclink"
+ - pymdownx.blocks.admonition:
+ types:
+ - new
+ - settings
+ - note
+ - abstract
+ - info
+ - tip
+ - success
+ - question
+ - warning
+ - failure
+ - danger
+ - bug
+ - example
+ - quote
+ - pymdownx.blocks.tab:
+ alternate_style: True
+ combine_header_slug: True
+ slugify: !!python/object/apply:pymdownx.slugs.slugify {kwds: {case: lower}}
+ - pymdownx.blocks.caption:
+ - pymdownx.details:
+ - pymdownx.snippets:
+ - pymdownx.magiclink:
+ repo_url_shortener: true
+ repo_url_shorthand: true
+ social_url_shorthand: true
+ social_url_shortener: true
+ normalize_issue_symbols: true
+ - pymdownx.highlight:
+ anchor_linenums: true
+ - pymdownx.inlinehilite:
+ - pymdownx.superfences:
+ - pymdownx.keys:
+ - pymdownx.tasklist:
+ custom_checkbox: true
+ - pymdownx.highlight:
+ linenums_style: pymdownx-inline
+ extend_pygments_lang:
+ - name: pycon3
+ lang: pycon
+ options:
+ python3: true
+
+plugins:
+ # - autorefs
+ - search
+ - mkdocstrings:
+ default_handler: python
+ handlers:
+ python:
+ paths: [src]
+ options:
+ docstring_options:
+ ignore_init_summary: true
+ docstring_section_style: list
+ # docstring_section_style: spacy
+ filters: ["!^_"]
+ heading_level: 1
+ inherited_members: true
+ merge_init_into_class: true
+ parameter_headings: true
+ allow_inspection: true
+ # preload_modules: [mkdocstrings]
+ relative_crossrefs: true
+ scoped_crossrefs: true
+ separate_signature: true
+ # line_length: 60
+ show_bases: false
+ # show_inheritance_diagram: true
+ show_root_heading: true
+ show_root_full_path: false
+ show_signature_annotations: true
+ show_source: false
+ show_symbol_type_heading: true
+ show_symbol_type_toc: true
+ signature_crossrefs: true
+ summary: true
+ unwrap_annotated: true
+
+extra:
+ social:
+ - icon: fontawesome/brands/github
+ link: https://github.com/thecodecrate/python-pipeline
+ - icon: fontawesome/brands/python
+ link: https://pypi.org/project/thecodecrate-pipeline/
+validation:
+ omitted_files: warn
+ absolute_links: warn
+ unrecognized_links: warn
+ anchors: warn
+nav:
+ - Home: index.md
+ - API Reference:
+ - core: api/core.md
+ - processors: api/processors.md
diff --git a/pyproject.toml b/pyproject.toml
index 06835ac..3d929b7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,7 +14,7 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
"Typing :: Typed",
]
-keywords = ["pipeline", "python", "library", "python-pipeline"]
+keywords = ["data pipelines"]
dependencies = []
requires-python = ">=3.13"
@@ -31,6 +31,13 @@ dev = [
"ruff>=0.8.2",
"ipykernel>=6.29.5",
"debugpy>=1.8.9",
+ "mkdocstrings[python]>=0.27.0",
+ "mkdocs-material>=9.5.48",
+ "mkdocs-gen-files>=0.5.0",
+ "mkdocs-autorefs>=1.2.0",
+ "mkdocs-git-revision-date-localized-plugin>=1.3.0",
+ "mkdocs-minify-plugin>=0.8.0",
+ "black>=24.10.0",
]
[build-system]
diff --git a/src/_api/__init__.py b/src/_api/__init__.py
new file mode 100644
index 0000000..cfa8f00
--- /dev/null
+++ b/src/_api/__init__.py
@@ -0,0 +1,40 @@
+# Version of the package
+# DO NOT MODIFY MANUALLY
+# This will be updated by `bumpver` command.
+# - Make sure to commit all changes first before running `bumpver`.
+# - Run `bumpver update --[minor|major|patch]`
+__version__ = "1.23.0"
+
+# ruff: noqa
+from .core import (
+ ChainedProcessor,
+ Pipeline,
+ PipelineFactory,
+ PipelineFactoryInterface,
+ PipelineInterface,
+ Processor,
+ ProcessorInterface,
+ Stage,
+ StageCallable,
+ StageClassOrInstance,
+ StageCollection,
+ StageInstance,
+ StageInstanceCollection,
+ StageInterface,
+ T_in,
+ T_out,
+)
+from .core import (
+ __all__ as _core_all,
+)
+
+# ruff: noqa
+from .processors import (
+ ChainedProcessor,
+ ChainedPipeline,
+ InterruptibleProcessor,
+ InterruptiblePipeline,
+ __all__ as _processor_all,
+)
+
+__all__ = (*_core_all, *_processor_all)
diff --git a/src/_api/core/__init__.py b/src/_api/core/__init__.py
new file mode 100644
index 0000000..a2b9e7c
--- /dev/null
+++ b/src/_api/core/__init__.py
@@ -0,0 +1,24 @@
+# ruff: noqa
+from .final import (
+ ChainedProcessor,
+ Pipeline,
+ PipelineFactory,
+ PipelineFactoryInterface,
+ PipelineInterface,
+ Processor,
+ ProcessorInterface,
+ Stage,
+ StageCallable,
+ StageClassOrInstance,
+ StageCollection,
+ StageInstance,
+ StageInstanceCollection,
+ StageInterface,
+ T_in,
+ T_out,
+)
+from .final import (
+ __all__ as _final_all,
+)
+
+__all__ = (*_final_all,)
diff --git a/src/_api/core/final/__init__.py b/src/_api/core/final/__init__.py
new file mode 100644
index 0000000..e1d8c5f
--- /dev/null
+++ b/src/_api/core/final/__init__.py
@@ -0,0 +1,36 @@
+from .chained_processor import ChainedProcessor
+from .pipeline import Pipeline
+from .pipeline_factory import PipelineFactory
+from .pipeline_factory_interface import PipelineFactoryInterface
+from .pipeline_interface import PipelineInterface
+from .processor import Processor
+from .processor_interface import ProcessorInterface
+from .stage import Stage
+from .stage_callable import (
+ StageCallable,
+ StageClassOrInstance,
+ StageCollection,
+ StageInstance,
+ StageInstanceCollection,
+)
+from .stage_interface import StageInterface
+from .types import T_in, T_out
+
+__all__ = (
+ "Pipeline",
+ "PipelineInterface",
+ "Stage",
+ "StageInterface",
+ "Processor",
+ "ProcessorInterface",
+ "PipelineFactory",
+ "PipelineFactoryInterface",
+ "T_in",
+ "T_out",
+ "StageCallable",
+ "StageInstance",
+ "StageInstanceCollection",
+ "StageClassOrInstance",
+ "StageCollection",
+ "ChainedProcessor",
+)
diff --git a/src/_api/core/final/chained_processor.py b/src/_api/core/final/chained_processor.py
new file mode 100644
index 0000000..1812cf7
--- /dev/null
+++ b/src/_api/core/final/chained_processor.py
@@ -0,0 +1,11 @@
+from typing import Generic
+
+from ..partials.step07_pipeline_default_processor import ChainedProcessor_Base
+from .types import T_in, T_out
+
+
+class ChainedProcessor(
+ ChainedProcessor_Base[T_in, T_out],
+ Generic[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/final/pipeline.py b/src/_api/core/final/pipeline.py
new file mode 100644
index 0000000..378242a
--- /dev/null
+++ b/src/_api/core/final/pipeline.py
@@ -0,0 +1,27 @@
+from typing import Generic
+
+from ..partials.step01_base import Pipeline_Base
+from ..partials.step02_pipeline_as_list import Pipeline_WithPipelineAsList
+from ..partials.step04_pipeline_declared_stages import (
+ Pipeline_WithPipelineDeclaredStages,
+)
+from ..partials.step06_pipeline_processor import Pipeline_WithPipelineProcessor
+from ..partials.step07_pipeline_default_processor import (
+ Pipeline_WithPipelineDefaultProcessor,
+)
+from ..partials.step08_pipeline_as_stage import Pipeline_WithPipelineAsStage
+from .pipeline_interface import PipelineInterface as ImplementsInterface
+from .types import T_in, T_out
+
+
+class Pipeline(
+ Pipeline_WithPipelineAsStage[T_in, T_out],
+ Pipeline_WithPipelineDefaultProcessor[T_in, T_out],
+ Pipeline_WithPipelineProcessor[T_in, T_out],
+ Pipeline_WithPipelineDeclaredStages,
+ Pipeline_WithPipelineAsList,
+ Pipeline_Base,
+ ImplementsInterface[T_in, T_out],
+ Generic[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/final/pipeline_factory.py b/src/_api/core/final/pipeline_factory.py
new file mode 100644
index 0000000..a821c80
--- /dev/null
+++ b/src/_api/core/final/pipeline_factory.py
@@ -0,0 +1,21 @@
+from typing import Generic, Optional
+
+from ..partials.step01_base.pipeline_interface import TPipeline
+from ..partials.step05_pipeline_factory import PipelineFactory_Base
+from ..partials.step06_pipeline_processor import PipelineFactory_WithPipelineProcessor
+from ..partials.step07_pipeline_default_processor import (
+ PipelineFactory_WithPipelineDefaultProcessor,
+)
+from .pipeline import Pipeline
+from .pipeline_factory_interface import PipelineFactoryInterface as ImplementsInterface
+from .types import T_in, T_out
+
+
+class PipelineFactory(
+ PipelineFactory_WithPipelineDefaultProcessor[T_in, T_out],
+ PipelineFactory_WithPipelineProcessor[T_in, T_out],
+ PipelineFactory_Base,
+ ImplementsInterface[T_in, T_out],
+ Generic[T_in, T_out],
+):
+ _model_class: Optional[type[TPipeline]] = Pipeline
diff --git a/src/_api/core/final/pipeline_factory_interface.py b/src/_api/core/final/pipeline_factory_interface.py
new file mode 100644
index 0000000..9e14b6f
--- /dev/null
+++ b/src/_api/core/final/pipeline_factory_interface.py
@@ -0,0 +1,19 @@
+from typing import Protocol
+
+from ..partials.step05_pipeline_factory import PipelineFactory_Base_Interface
+from ..partials.step06_pipeline_processor import (
+ PipelineFactory_WithPipelineProcessor_Interface,
+)
+from ..partials.step07_pipeline_default_processor import (
+ PipelineFactory_WithPipelineDefaultProcessor_Interface,
+)
+from .types import T_in, T_out
+
+
+class PipelineFactoryInterface(
+ PipelineFactory_WithPipelineDefaultProcessor_Interface[T_in, T_out],
+ PipelineFactory_WithPipelineProcessor_Interface[T_in, T_out],
+ PipelineFactory_Base_Interface,
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/final/pipeline_interface.py b/src/_api/core/final/pipeline_interface.py
new file mode 100644
index 0000000..9f1bfda
--- /dev/null
+++ b/src/_api/core/final/pipeline_interface.py
@@ -0,0 +1,27 @@
+from typing import Protocol
+
+from ..partials.step01_base import Pipeline_Base_Interface
+from ..partials.step02_pipeline_as_list import Pipeline_WithPipelineAsList_Interface
+from ..partials.step04_pipeline_declared_stages import (
+ Pipeline_WithPipelineDeclaredStages_Interface,
+)
+from ..partials.step06_pipeline_processor import (
+ Pipeline_WithPipelineProcessor_Interface,
+)
+from ..partials.step07_pipeline_default_processor import (
+ Pipeline_WithPipelineDefaultProcessor_Interface,
+)
+from ..partials.step08_pipeline_as_stage import Pipeline_WithPipelineAsStage_Interface
+from .types import T_in, T_out
+
+
+class PipelineInterface(
+ Pipeline_WithPipelineAsStage_Interface[T_in, T_out],
+ Pipeline_WithPipelineDefaultProcessor_Interface[T_in, T_out],
+ Pipeline_WithPipelineProcessor_Interface[T_in, T_out],
+ Pipeline_WithPipelineDeclaredStages_Interface,
+ Pipeline_WithPipelineAsList_Interface,
+ Pipeline_Base_Interface,
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/final/processor.py b/src/_api/core/final/processor.py
new file mode 100644
index 0000000..6993364
--- /dev/null
+++ b/src/_api/core/final/processor.py
@@ -0,0 +1,13 @@
+from abc import ABC
+
+from ..partials.step06_pipeline_processor import Processor_Base
+from .processor_interface import ProcessorInterface as ImplementsInterface
+from .types import T_in, T_out
+
+
+class Processor(
+ Processor_Base[T_in, T_out],
+ ImplementsInterface[T_in, T_out],
+ ABC,
+):
+ pass
diff --git a/src/_api/core/final/processor_interface.py b/src/_api/core/final/processor_interface.py
new file mode 100644
index 0000000..1099522
--- /dev/null
+++ b/src/_api/core/final/processor_interface.py
@@ -0,0 +1,11 @@
+from typing import Protocol
+
+from ..partials.step06_pipeline_processor import Processor_Base_Interface
+from .types import T_in, T_out
+
+
+class ProcessorInterface(
+ Processor_Base_Interface[T_in, T_out],
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/final/stage.py b/src/_api/core/final/stage.py
new file mode 100644
index 0000000..651146f
--- /dev/null
+++ b/src/_api/core/final/stage.py
@@ -0,0 +1,15 @@
+from abc import ABC
+
+from ..partials.step01_base import Stage_Base
+from ..partials.step03_stage_as_callable import Stage_WithStageAsCallable
+from .stage_interface import StageInterface as ImplementsInterface
+from .types import T_in, T_out
+
+
+class Stage(
+ Stage_WithStageAsCallable[T_in, T_out],
+ Stage_Base,
+ ImplementsInterface[T_in, T_out],
+ ABC,
+):
+ pass
diff --git a/src/thecodecrate_pipeline/core/final/stage_callable.py b/src/_api/core/final/stage_callable.py
similarity index 51%
rename from src/thecodecrate_pipeline/core/final/stage_callable.py
rename to src/_api/core/final/stage_callable.py
index f39f63d..8348d7b 100644
--- a/src/thecodecrate_pipeline/core/final/stage_callable.py
+++ b/src/_api/core/final/stage_callable.py
@@ -1,26 +1,26 @@
from typing import Protocol
-from ..partials.step01_base.stage_callable import (
- StageCallable as WithStageCallableBase,
-)
-from ..partials.step01_base.stage_callable import (
+from ..partials.step01_base import (
+ StageCallable_Base,
StageClassOrInstance,
StageCollection,
+ StageInstance,
StageInstanceCollection,
)
-from ..partials.step01_base.types import T_in, T_out
+from .types import T_in, T_out
class StageCallable(
- WithStageCallableBase[T_in, T_out],
+ StageCallable_Base[T_in, T_out],
Protocol[T_in, T_out],
):
pass
-__all__ = [
+__all__ = (
"StageCallable",
"StageCollection",
+ "StageInstance",
"StageInstanceCollection",
"StageClassOrInstance",
-]
+)
diff --git a/src/_api/core/final/stage_interface.py b/src/_api/core/final/stage_interface.py
new file mode 100644
index 0000000..37daec0
--- /dev/null
+++ b/src/_api/core/final/stage_interface.py
@@ -0,0 +1,13 @@
+from typing import Protocol
+
+from ..partials.step01_base import Stage_Base_Interface
+from ..partials.step03_stage_as_callable import Stage_WithStageAsCallable_Interface
+from .types import T_in, T_out
+
+
+class StageInterface(
+ Stage_WithStageAsCallable_Interface[T_in, T_out],
+ Stage_Base_Interface,
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/final/types.py b/src/_api/core/final/types.py
new file mode 100644
index 0000000..8e011ed
--- /dev/null
+++ b/src/_api/core/final/types.py
@@ -0,0 +1,6 @@
+from ..partials.step01_base import T_in, T_out
+
+__all__ = (
+ "T_in",
+ "T_out",
+)
diff --git a/src/_api/core/partials/__init__.py b/src/_api/core/partials/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/_api/core/partials/step01_base/__init__.py b/src/_api/core/partials/step01_base/__init__.py
new file mode 100644
index 0000000..2e694f0
--- /dev/null
+++ b/src/_api/core/partials/step01_base/__init__.py
@@ -0,0 +1,28 @@
+from .pipeline import Pipeline as Pipeline_Base
+from .pipeline_interface import PipelineInterface as Pipeline_Base_Interface
+from .pipeline_interface import TPipeline
+from .stage import Stage as Stage_Base
+from .stage_callable import StageCallable as StageCallable_Base
+from .stage_callable import (
+ StageClassOrInstance,
+ StageCollection,
+ StageInstance,
+ StageInstanceCollection,
+)
+from .stage_interface import StageInterface as Stage_Base_Interface
+from .types import T_in, T_out
+
+__all__ = (
+ "Pipeline_Base",
+ "Pipeline_Base_Interface",
+ "Stage_Base",
+ "Stage_Base_Interface",
+ "StageCallable_Base",
+ "StageClassOrInstance",
+ "StageCollection",
+ "StageInstance",
+ "StageInstanceCollection",
+ "T_in",
+ "T_out",
+ "TPipeline",
+)
diff --git a/src/thecodecrate_pipeline/core/partials/step01_base/pipeline.py b/src/_api/core/partials/step01_base/pipeline.py
similarity index 70%
rename from src/thecodecrate_pipeline/core/partials/step01_base/pipeline.py
rename to src/_api/core/partials/step01_base/pipeline.py
index cc20a84..4b80201 100644
--- a/src/thecodecrate_pipeline/core/partials/step01_base/pipeline.py
+++ b/src/_api/core/partials/step01_base/pipeline.py
@@ -2,13 +2,13 @@
from ...support.clonable import Clonable
from .pipeline_interface import (
- PipelineInterface as ImplementsPipelineInterface,
+ PipelineInterface as ImplementsInterface,
)
class Pipeline(
Clonable,
- ImplementsPipelineInterface,
+ ImplementsInterface,
):
def __init__(self, *args: Any, **kwds: Any) -> None:
pass
diff --git a/src/thecodecrate_pipeline/core/partials/step01_base/pipeline_interface.py b/src/_api/core/partials/step01_base/pipeline_interface.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/partials/step01_base/pipeline_interface.py
rename to src/_api/core/partials/step01_base/pipeline_interface.py
diff --git a/src/_api/core/partials/step01_base/stage.py b/src/_api/core/partials/step01_base/stage.py
new file mode 100644
index 0000000..56a5393
--- /dev/null
+++ b/src/_api/core/partials/step01_base/stage.py
@@ -0,0 +1,7 @@
+from .stage_interface import StageInterface as ImplementsInterface
+
+
+class Stage(
+ ImplementsInterface,
+):
+ pass
diff --git a/src/thecodecrate_pipeline/core/partials/step01_base/stage_callable.py b/src/_api/core/partials/step01_base/stage_callable.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/partials/step01_base/stage_callable.py
rename to src/_api/core/partials/step01_base/stage_callable.py
diff --git a/src/thecodecrate_pipeline/core/partials/step01_base/stage_interface.py b/src/_api/core/partials/step01_base/stage_interface.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/partials/step01_base/stage_interface.py
rename to src/_api/core/partials/step01_base/stage_interface.py
diff --git a/src/thecodecrate_pipeline/core/partials/step01_base/types.py b/src/_api/core/partials/step01_base/types.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/partials/step01_base/types.py
rename to src/_api/core/partials/step01_base/types.py
diff --git a/src/_api/core/partials/step02_pipeline_as_list/__init__.py b/src/_api/core/partials/step02_pipeline_as_list/__init__.py
new file mode 100644
index 0000000..3576ed8
--- /dev/null
+++ b/src/_api/core/partials/step02_pipeline_as_list/__init__.py
@@ -0,0 +1,9 @@
+from .pipeline_interface_mixin import (
+ PipelineInterfaceMixin as Pipeline_WithPipelineAsList_Interface,
+)
+from .pipeline_mixin import PipelineMixin as Pipeline_WithPipelineAsList
+
+__all__ = (
+ "Pipeline_WithPipelineAsList",
+ "Pipeline_WithPipelineAsList_Interface",
+)
diff --git a/src/thecodecrate_pipeline/core/partials/step02_pipeline_as_list/pipeline_interface_mixin.py b/src/_api/core/partials/step02_pipeline_as_list/pipeline_interface_mixin.py
similarity index 68%
rename from src/thecodecrate_pipeline/core/partials/step02_pipeline_as_list/pipeline_interface_mixin.py
rename to src/_api/core/partials/step02_pipeline_as_list/pipeline_interface_mixin.py
index c81dd91..2ad3ed0 100644
--- a/src/thecodecrate_pipeline/core/partials/step02_pipeline_as_list/pipeline_interface_mixin.py
+++ b/src/_api/core/partials/step02_pipeline_as_list/pipeline_interface_mixin.py
@@ -3,15 +3,16 @@
from ...support.act_as_list.act_as_list_interface import (
ActAsListInterface,
)
-from ..step01_base.pipeline_interface import (
- PipelineInterface as WithPipelineBaseInterface,
+from ..step01_base import (
+ Pipeline_Base_Interface,
+ StageInstance,
+ StageInstanceCollection,
)
-from ..step01_base.stage_callable import StageInstance, StageInstanceCollection
class PipelineInterfaceMixin(
ActAsListInterface[StageInstance, StageInstanceCollection],
- WithPipelineBaseInterface,
+ Pipeline_Base_Interface,
Protocol,
):
def __init__(
diff --git a/src/thecodecrate_pipeline/core/partials/step02_pipeline_as_list/pipeline_mixin.py b/src/_api/core/partials/step02_pipeline_as_list/pipeline_mixin.py
similarity index 81%
rename from src/thecodecrate_pipeline/core/partials/step02_pipeline_as_list/pipeline_mixin.py
rename to src/_api/core/partials/step02_pipeline_as_list/pipeline_mixin.py
index 72f94c0..4737866 100644
--- a/src/thecodecrate_pipeline/core/partials/step02_pipeline_as_list/pipeline_mixin.py
+++ b/src/_api/core/partials/step02_pipeline_as_list/pipeline_mixin.py
@@ -2,15 +2,13 @@
from typing import Any, Optional, Self
from ...support.act_as_list import ActAsList
-from ..step01_base.stage_callable import StageInstance, StageInstanceCollection
-from .pipeline_interface_mixin import (
- PipelineInterfaceMixin as ImplementsPipelineInterface,
-)
+from ..step01_base import StageInstance, StageInstanceCollection
+from .pipeline_interface_mixin import PipelineInterfaceMixin as ImplementsInterface
class PipelineMixin(
ActAsList[StageInstance, StageInstanceCollection],
- ImplementsPipelineInterface,
+ ImplementsInterface,
ABC,
):
stage_instances: StageInstanceCollection
@@ -41,4 +39,7 @@ def _add_item(self, item: StageInstance) -> Self:
return self.clone({"stage_instances": tuple([*self.stage_instances, item])})
def pipe(self, stage: StageInstance) -> Self:
+ """
+ Adds a single stage to the pipeline.
+ """
return self._add_item(stage)
diff --git a/src/_api/core/partials/step03_stage_as_callable/__init__.py b/src/_api/core/partials/step03_stage_as_callable/__init__.py
new file mode 100644
index 0000000..e30c88a
--- /dev/null
+++ b/src/_api/core/partials/step03_stage_as_callable/__init__.py
@@ -0,0 +1,9 @@
+from .stage_interface_mixin import (
+ StageInterfaceMixin as Stage_WithStageAsCallable_Interface,
+)
+from .stage_mixin import StageMixin as Stage_WithStageAsCallable
+
+__all__ = (
+ "Stage_WithStageAsCallable",
+ "Stage_WithStageAsCallable_Interface",
+)
diff --git a/src/thecodecrate_pipeline/core/partials/step03_stage_as_callable/stage_interface_mixin.py b/src/_api/core/partials/step03_stage_as_callable/stage_interface_mixin.py
similarity index 66%
rename from src/thecodecrate_pipeline/core/partials/step03_stage_as_callable/stage_interface_mixin.py
rename to src/_api/core/partials/step03_stage_as_callable/stage_interface_mixin.py
index ae761f6..a3e81e1 100644
--- a/src/thecodecrate_pipeline/core/partials/step03_stage_as_callable/stage_interface_mixin.py
+++ b/src/_api/core/partials/step03_stage_as_callable/stage_interface_mixin.py
@@ -1,14 +1,15 @@
from abc import abstractmethod
from typing import Any, Protocol
-from ..step01_base.stage_interface import (
- StageInterface as WithStageBaseInterface,
+from ..step01_base import (
+ Stage_Base_Interface,
+ T_in,
+ T_out,
)
-from ..step01_base.types import T_in, T_out
class StageInterfaceMixin(
- WithStageBaseInterface,
+ Stage_Base_Interface,
Protocol[T_in, T_out],
):
@abstractmethod
diff --git a/src/thecodecrate_pipeline/core/partials/step03_stage_as_callable/stage_mixin.py b/src/_api/core/partials/step03_stage_as_callable/stage_mixin.py
similarity index 66%
rename from src/thecodecrate_pipeline/core/partials/step03_stage_as_callable/stage_mixin.py
rename to src/_api/core/partials/step03_stage_as_callable/stage_mixin.py
index 057e057..5cd19ce 100644
--- a/src/thecodecrate_pipeline/core/partials/step03_stage_as_callable/stage_mixin.py
+++ b/src/_api/core/partials/step03_stage_as_callable/stage_mixin.py
@@ -1,14 +1,14 @@
from abc import ABC, abstractmethod
from typing import Any
-from ..step01_base.types import T_in, T_out
+from ..step01_base import T_in, T_out
from .stage_interface_mixin import (
- StageInterfaceMixin as ImplementsStageInterface,
+ StageInterfaceMixin as ImplementsInterface,
)
class StageMixin(
- ImplementsStageInterface[T_in, T_out],
+ ImplementsInterface[T_in, T_out],
ABC,
):
@abstractmethod
@@ -19,4 +19,7 @@ async def __call__(
*args: Any,
**kwds: Any,
) -> T_out:
+ """
+ Runs the stage.
+ """
pass
diff --git a/src/_api/core/partials/step04_pipeline_declared_stages/__init__.py b/src/_api/core/partials/step04_pipeline_declared_stages/__init__.py
new file mode 100644
index 0000000..bad0a22
--- /dev/null
+++ b/src/_api/core/partials/step04_pipeline_declared_stages/__init__.py
@@ -0,0 +1,9 @@
+from .pipeline_interface_mixin import (
+ PipelineInterfaceMixin as Pipeline_WithPipelineDeclaredStages_Interface,
+)
+from .pipeline_mixin import PipelineMixin as Pipeline_WithPipelineDeclaredStages
+
+__all__ = (
+ "Pipeline_WithPipelineDeclaredStages",
+ "Pipeline_WithPipelineDeclaredStages_Interface",
+)
diff --git a/src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/pipeline_interface_mixin.py b/src/_api/core/partials/step04_pipeline_declared_stages/pipeline_interface_mixin.py
similarity index 54%
rename from src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/pipeline_interface_mixin.py
rename to src/_api/core/partials/step04_pipeline_declared_stages/pipeline_interface_mixin.py
index 4dfedb3..1115e78 100644
--- a/src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/pipeline_interface_mixin.py
+++ b/src/_api/core/partials/step04_pipeline_declared_stages/pipeline_interface_mixin.py
@@ -1,17 +1,17 @@
from typing import Any, Optional, Protocol, Self
-from ..step01_base.pipeline_interface import (
- PipelineInterface as WithPipelineBaseInterface,
+from ..step01_base import (
+ Pipeline_Base_Interface,
+ StageCollection,
)
-from ..step01_base.stage_callable import StageCollection
-from ..step02_pipeline_as_list.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineAsListInterface,
+from ..step02_pipeline_as_list import (
+ Pipeline_WithPipelineAsList_Interface,
)
class PipelineInterfaceMixin(
- WithPipelineAsListInterface,
- WithPipelineBaseInterface,
+ Pipeline_WithPipelineAsList_Interface,
+ Pipeline_Base_Interface,
Protocol,
):
def __init__(
diff --git a/src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/pipeline_mixin.py b/src/_api/core/partials/step04_pipeline_declared_stages/pipeline_mixin.py
similarity index 79%
rename from src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/pipeline_mixin.py
rename to src/_api/core/partials/step04_pipeline_declared_stages/pipeline_mixin.py
index 47fbf00..f5d2dc8 100644
--- a/src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/pipeline_mixin.py
+++ b/src/_api/core/partials/step04_pipeline_declared_stages/pipeline_mixin.py
@@ -1,13 +1,13 @@
+from abc import ABC
from typing import Any, Optional, Self
-from ..step01_base.stage_callable import StageCollection
-from .pipeline_interface_mixin import (
- PipelineInterfaceMixin as ImplementsPipelineInterface,
-)
+from ..step01_base import StageCollection
+from .pipeline_interface_mixin import PipelineInterfaceMixin as ImplementsInterface
class PipelineMixin(
- ImplementsPipelineInterface,
+ ImplementsInterface,
+ ABC,
):
stages: StageCollection
@@ -39,6 +39,9 @@ def _instantiate_stages(self) -> Self:
return self._set_items(instances)
def with_stages(self, stages: StageCollection) -> Self:
+ """
+ Adds a collection of stages to the pipeline.
+ """
cloned = self.clone({"stages": stages, "stage_instances": []})
return cloned._instantiate_stages()
diff --git a/src/_api/core/partials/step05_pipeline_factory/__init__.py b/src/_api/core/partials/step05_pipeline_factory/__init__.py
new file mode 100644
index 0000000..8d5a818
--- /dev/null
+++ b/src/_api/core/partials/step05_pipeline_factory/__init__.py
@@ -0,0 +1,9 @@
+from .pipeline_factory import PipelineFactory as PipelineFactory_Base
+from .pipeline_factory_interface import (
+ PipelineFactoryInterface as PipelineFactory_Base_Interface,
+)
+
+__all__ = (
+ "PipelineFactory_Base",
+ "PipelineFactory_Base_Interface",
+)
diff --git a/src/thecodecrate_pipeline/core/partials/step05_pipeline_factory/pipeline_factory.py b/src/_api/core/partials/step05_pipeline_factory/pipeline_factory.py
similarity index 78%
rename from src/thecodecrate_pipeline/core/partials/step05_pipeline_factory/pipeline_factory.py
rename to src/_api/core/partials/step05_pipeline_factory/pipeline_factory.py
index 85497c4..0216372 100644
--- a/src/thecodecrate_pipeline/core/partials/step05_pipeline_factory/pipeline_factory.py
+++ b/src/_api/core/partials/step05_pipeline_factory/pipeline_factory.py
@@ -1,20 +1,19 @@
-from typing import Any, Generic, Optional, Self
+from typing import Any, Optional, Self
from ...support.act_as_factory import ActAsFactory
from ...support.act_as_list import ActAsList
-from ..step01_base.pipeline_interface import TPipeline
-from ..step01_base.stage_callable import (
+from ..step01_base import (
StageClassOrInstance,
StageCollection,
+ TPipeline,
)
-from .pipeline_factory_interface import PipelineFactoryInterface
+from .pipeline_factory_interface import PipelineFactoryInterface as ImplementsInterface
class PipelineFactory(
- PipelineFactoryInterface[TPipeline],
ActAsFactory[TPipeline],
ActAsList[StageClassOrInstance, StageCollection],
- Generic[TPipeline],
+ ImplementsInterface[TPipeline],
):
_model_class: Optional[type[TPipeline]] # ActAsFactory
stages: StageCollection # ActAsList
@@ -22,6 +21,7 @@ class PipelineFactory(
def __init__(
self,
stages: Optional[StageCollection] = None,
+ model_class: Optional[type[TPipeline]] = None,
*args: Any,
**kwds: Any,
) -> None:
@@ -34,6 +34,9 @@ def __init__(
if stages:
self.stages = stages
+ if model_class:
+ self._model_class = model_class
+
# ActAsList
def _get_items(self) -> StageCollection:
return self.stages
@@ -54,8 +57,14 @@ def _definition(self) -> dict[str, Any]:
# public API: factory configuration
def add_stage(self, stage: StageClassOrInstance) -> Self:
+ """
+ Adds a single stage to the pipeline.
+ """
return self._add_item(stage)
# public API: factory configuration
def with_stages(self, stages: StageCollection) -> Self:
+ """
+ Adds a collection of stages to the pipeline.
+ """
return self._set_items(stages)
diff --git a/src/thecodecrate_pipeline/core/partials/step05_pipeline_factory/pipeline_factory_interface.py b/src/_api/core/partials/step05_pipeline_factory/pipeline_factory_interface.py
similarity index 81%
rename from src/thecodecrate_pipeline/core/partials/step05_pipeline_factory/pipeline_factory_interface.py
rename to src/_api/core/partials/step05_pipeline_factory/pipeline_factory_interface.py
index 3a1b72d..27ca8ce 100644
--- a/src/thecodecrate_pipeline/core/partials/step05_pipeline_factory/pipeline_factory_interface.py
+++ b/src/_api/core/partials/step05_pipeline_factory/pipeline_factory_interface.py
@@ -2,8 +2,7 @@
from ...support.act_as_factory import ActAsFactoryInterface
from ...support.act_as_list import ActAsListInterface
-from ..step01_base.pipeline_interface import TPipeline
-from ..step01_base.stage_callable import StageClassOrInstance, StageCollection
+from ..step01_base import StageClassOrInstance, StageCollection, TPipeline
class PipelineFactoryInterface(
@@ -14,6 +13,7 @@ class PipelineFactoryInterface(
def __init__(
self,
stages: Optional[StageCollection] = None,
+ model_class: Optional[type[TPipeline]] = None,
*args: Any,
**kwds: Any,
) -> None: ...
diff --git a/src/_api/core/partials/step06_pipeline_processor/__init__.py b/src/_api/core/partials/step06_pipeline_processor/__init__.py
new file mode 100644
index 0000000..b30bee8
--- /dev/null
+++ b/src/_api/core/partials/step06_pipeline_processor/__init__.py
@@ -0,0 +1,21 @@
+from .pipeline_factory_interface_mixin import (
+ PipelineFactoryInterfaceMixin as PipelineFactory_WithPipelineProcessor_Interface,
+)
+from .pipeline_factory_mixin import (
+ PipelineFactoryMixin as PipelineFactory_WithPipelineProcessor,
+)
+from .pipeline_interface_mixin import (
+ PipelineInterfaceMixin as Pipeline_WithPipelineProcessor_Interface,
+)
+from .pipeline_mixin import PipelineMixin as Pipeline_WithPipelineProcessor
+from .processor import Processor as Processor_Base
+from .processor_interface import ProcessorInterface as Processor_Base_Interface
+
+__all__ = (
+ "Pipeline_WithPipelineProcessor",
+ "Pipeline_WithPipelineProcessor_Interface",
+ "PipelineFactory_WithPipelineProcessor",
+ "PipelineFactory_WithPipelineProcessor_Interface",
+ "Processor_Base",
+ "Processor_Base_Interface",
+)
diff --git a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_factory_interface_mixin.py b/src/_api/core/partials/step06_pipeline_processor/pipeline_factory_interface_mixin.py
similarity index 74%
rename from src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_factory_interface_mixin.py
rename to src/_api/core/partials/step06_pipeline_processor/pipeline_factory_interface_mixin.py
index 23051aa..98693e6 100644
--- a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_factory_interface_mixin.py
+++ b/src/_api/core/partials/step06_pipeline_processor/pipeline_factory_interface_mixin.py
@@ -1,15 +1,12 @@
from typing import Any, Optional, Protocol, Self
-from ..step01_base.pipeline_interface import PipelineInterface
-from ..step01_base.types import T_in, T_out
-from ..step05_pipeline_factory.pipeline_factory_interface import (
- PipelineFactoryInterface as WithPipelineFactoryBaseInterface,
-)
+from ..step01_base import Pipeline_Base_Interface, T_in, T_out
+from ..step05_pipeline_factory import PipelineFactory_Base_Interface
from .processor_interface import ProcessorInterface
class PipelineFactoryInterfaceMixin(
- WithPipelineFactoryBaseInterface[PipelineInterface],
+ PipelineFactory_Base_Interface[Pipeline_Base_Interface],
Protocol[T_in, T_out],
):
def __init__(
diff --git a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_factory_mixin.py b/src/_api/core/partials/step06_pipeline_processor/pipeline_factory_mixin.py
similarity index 82%
rename from src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_factory_mixin.py
rename to src/_api/core/partials/step06_pipeline_processor/pipeline_factory_mixin.py
index 3dc9c2a..90146c4 100644
--- a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_factory_mixin.py
+++ b/src/_api/core/partials/step06_pipeline_processor/pipeline_factory_mixin.py
@@ -1,15 +1,15 @@
from abc import ABC
from typing import Any, Optional, Self
-from ..step01_base.types import T_in, T_out
+from ..step01_base import T_in, T_out
from .pipeline_factory_interface_mixin import (
- PipelineFactoryInterfaceMixin as PipelineFactoryInterface,
+ PipelineFactoryInterfaceMixin as ImplementsInterface,
)
from .processor_interface import ProcessorInterface
class PipelineFactoryMixin(
- PipelineFactoryInterface[T_in, T_out],
+ ImplementsInterface[T_in, T_out],
ABC,
):
processor_class: Optional[type[ProcessorInterface[T_in, T_out]]] = None
@@ -37,12 +37,18 @@ def __init__(
def with_processor(
self, processor: type[ProcessorInterface] | ProcessorInterface
) -> Self:
+ """
+ Attachs a processor (class or instance) to the pipeline factory.
+ """
if isinstance(processor, type):
return self.with_processor_class(processor)
return self.with_processor_instance(processor)
def with_processor_instance(self, processor_instance: ProcessorInterface) -> Self:
+ """
+ Attachs a processor instance to the pipeline factory.
+ """
self.processor_class = processor_instance.__class__
self.processor_instance = processor_instance
@@ -50,6 +56,9 @@ def with_processor_instance(self, processor_instance: ProcessorInterface) -> Sel
return self
def with_processor_class(self, processor_class: type[ProcessorInterface]) -> Self:
+ """
+ Attachs a processor class to the pipeline factory.
+ """
self.processor_class = processor_class
return self
diff --git a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_interface_mixin.py b/src/_api/core/partials/step06_pipeline_processor/pipeline_interface_mixin.py
similarity index 73%
rename from src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_interface_mixin.py
rename to src/_api/core/partials/step06_pipeline_processor/pipeline_interface_mixin.py
index aef45da..d18a2d0 100644
--- a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_interface_mixin.py
+++ b/src/_api/core/partials/step06_pipeline_processor/pipeline_interface_mixin.py
@@ -1,18 +1,13 @@
from typing import Any, Optional, Protocol, Self
-from ..step01_base.pipeline_interface import (
- PipelineInterface as WithPipelineBaseInterface,
-)
-from ..step01_base.types import T_in, T_out
-from ..step02_pipeline_as_list.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineAsListInterface,
-)
+from ..step01_base import Pipeline_Base_Interface, T_in, T_out
+from ..step02_pipeline_as_list import Pipeline_WithPipelineAsList_Interface
from .processor_interface import ProcessorInterface
class PipelineInterfaceMixin(
- WithPipelineAsListInterface,
- WithPipelineBaseInterface,
+ Pipeline_WithPipelineAsList_Interface,
+ Pipeline_Base_Interface,
Protocol[T_in, T_out],
):
def __init__(
diff --git a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_mixin.py b/src/_api/core/partials/step06_pipeline_processor/pipeline_mixin.py
similarity index 84%
rename from src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_mixin.py
rename to src/_api/core/partials/step06_pipeline_processor/pipeline_mixin.py
index 1003ecb..fde3624 100644
--- a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/pipeline_mixin.py
+++ b/src/_api/core/partials/step06_pipeline_processor/pipeline_mixin.py
@@ -1,15 +1,15 @@
from abc import ABC
from typing import Any, Optional, Self
-from ..step01_base.types import T_in, T_out
+from ..step01_base import T_in, T_out
from .pipeline_interface_mixin import (
- PipelineInterfaceMixin as PipelineInterface,
+ PipelineInterfaceMixin as ImplementsInterface,
)
from .processor_interface import ProcessorInterface
class PipelineMixin(
- PipelineInterface[T_in, T_out],
+ ImplementsInterface[T_in, T_out],
ABC,
):
processor_class: Optional[type[ProcessorInterface]]
@@ -50,12 +50,18 @@ def __init__(
def with_processor(
self, processor: type[ProcessorInterface] | ProcessorInterface
) -> Self:
+ """
+ Attachs a processor (class or instance) to the pipeline.
+ """
if isinstance(processor, type):
return self.with_processor_class(processor)
return self.with_processor_instance(processor)
def with_processor_instance(self, processor_instance: ProcessorInterface) -> Self:
+ """
+ Attachs a processor instance to the pipeline.
+ """
return self.clone(
{
"processor_class": processor_instance.__class__,
@@ -64,6 +70,9 @@ def with_processor_instance(self, processor_instance: ProcessorInterface) -> Sel
)
def with_processor_class(self, processor_class: type[ProcessorInterface]) -> Self:
+ """
+ Attachs a processor class to the pipeline.
+ """
return self.clone({"processor_class": processor_class})
def _make_processor(self) -> ProcessorInterface:
@@ -73,6 +82,9 @@ def _make_processor(self) -> ProcessorInterface:
return self.processor_class()
async def process(self, payload: T_in, *args: Any, **kwds: Any) -> T_out:
+ """
+ Process the given payload through the pipeline.
+ """
if self.processor_instance is None:
raise ValueError("Processor not set")
diff --git a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/processor.py b/src/_api/core/partials/step06_pipeline_processor/processor.py
similarity index 70%
rename from src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/processor.py
rename to src/_api/core/partials/step06_pipeline_processor/processor.py
index a435793..ababc4e 100644
--- a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/processor.py
+++ b/src/_api/core/partials/step06_pipeline_processor/processor.py
@@ -1,23 +1,23 @@
-from abc import ABC, abstractmethod
+from abc import abstractmethod
from typing import Any
from ...support.clonable import Clonable
from ...support.has_call_async import HasCallAsync
-from ..step01_base.stage_callable import (
+from ..step01_base import (
StageInstance,
StageInstanceCollection,
+ T_in,
+ T_out,
)
-from ..step01_base.types import T_in, T_out
from .processor_interface import (
- ProcessorInterface as ImplementsProcessorInterface,
+ ProcessorInterface as ImplementsInterface,
)
class Processor(
HasCallAsync,
Clonable,
- ImplementsProcessorInterface[T_in, T_out],
- ABC,
+ ImplementsInterface[T_in, T_out],
):
@abstractmethod
async def process(
@@ -27,6 +27,9 @@ async def process(
*args: Any,
**kwds: Any,
) -> T_out:
+ """
+ Process the given payload through the provided stages.
+ """
pass
# HasCallAsync: include callable type and `payload` in the signature
@@ -37,4 +40,7 @@ async def _call(
*args: Any,
**kwds: Any,
) -> Any:
+ """
+ Alias to `process` method.
+ """
return await super()._call(stage, payload, *args, **kwds)
diff --git a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/processor_interface.py b/src/_api/core/partials/step06_pipeline_processor/processor_interface.py
similarity index 86%
rename from src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/processor_interface.py
rename to src/_api/core/partials/step06_pipeline_processor/processor_interface.py
index b371f0b..0ca2fbc 100644
--- a/src/thecodecrate_pipeline/core/partials/step06_pipeline_processor/processor_interface.py
+++ b/src/_api/core/partials/step06_pipeline_processor/processor_interface.py
@@ -3,8 +3,7 @@
from ...support.clonable import ClonableInterface
from ...support.has_call_async import HasCallAsyncInterface
-from ..step01_base.stage_callable import StageInstance, StageInstanceCollection
-from ..step01_base.types import T_in, T_out
+from ..step01_base import StageInstance, StageInstanceCollection, T_in, T_out
class ProcessorInterface(
diff --git a/src/_api/core/partials/step07_pipeline_default_processor/__init__.py b/src/_api/core/partials/step07_pipeline_default_processor/__init__.py
new file mode 100644
index 0000000..c472493
--- /dev/null
+++ b/src/_api/core/partials/step07_pipeline_default_processor/__init__.py
@@ -0,0 +1,19 @@
+from .pipeline_factory_interface_mixin import (
+ PipelineFactoryInterfaceMixin as PipelineFactory_WithPipelineDefaultProcessor_Interface,
+)
+from .pipeline_factory_mixin import (
+ PipelineFactory as PipelineFactory_WithPipelineDefaultProcessor,
+)
+from .pipeline_interface_mixin import (
+ PipelineInterfaceMixin as Pipeline_WithPipelineDefaultProcessor_Interface,
+)
+from .pipeline_mixin import PipelineMixin as Pipeline_WithPipelineDefaultProcessor
+from .processors.chained_processor import ChainedProcessor as ChainedProcessor_Base
+
+__all__ = (
+ "ChainedProcessor_Base",
+ "Pipeline_WithPipelineDefaultProcessor",
+ "Pipeline_WithPipelineDefaultProcessor_Interface",
+ "PipelineFactory_WithPipelineDefaultProcessor",
+ "PipelineFactory_WithPipelineDefaultProcessor_Interface",
+)
diff --git a/src/_api/core/partials/step07_pipeline_default_processor/pipeline_factory_interface_mixin.py b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_factory_interface_mixin.py
new file mode 100644
index 0000000..c34b67e
--- /dev/null
+++ b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_factory_interface_mixin.py
@@ -0,0 +1,15 @@
+from typing import Protocol
+
+from ..step01_base import Pipeline_Base_Interface, T_in, T_out
+from ..step05_pipeline_factory import PipelineFactory_Base_Interface
+from ..step06_pipeline_processor import (
+ PipelineFactory_WithPipelineProcessor_Interface,
+)
+
+
+class PipelineFactoryInterfaceMixin(
+ PipelineFactory_WithPipelineProcessor_Interface[T_in, T_out],
+ PipelineFactory_Base_Interface[Pipeline_Base_Interface],
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/partials/step07_pipeline_default_processor/pipeline_factory_mixin.py b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_factory_mixin.py
new file mode 100644
index 0000000..074b145
--- /dev/null
+++ b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_factory_mixin.py
@@ -0,0 +1,18 @@
+from typing import Generic, Optional
+
+from ..step01_base import Pipeline_Base_Interface, T_in, T_out, TPipeline
+from ..step05_pipeline_factory import PipelineFactory_Base
+from ..step06_pipeline_processor import PipelineFactory_WithPipelineProcessor
+from .pipeline_factory_interface_mixin import (
+ PipelineFactoryInterfaceMixin as ImplementsInterface,
+)
+from .pipeline_mixin import PipelineMixin as Pipeline
+
+
+class PipelineFactory(
+ PipelineFactory_WithPipelineProcessor[T_in, T_out],
+ PipelineFactory_Base[Pipeline_Base_Interface],
+ ImplementsInterface[T_in, T_out],
+ Generic[T_in, T_out],
+):
+ _model_class: Optional[type[TPipeline]] = Pipeline
diff --git a/src/_api/core/partials/step07_pipeline_default_processor/pipeline_interface_mixin.py b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_interface_mixin.py
new file mode 100644
index 0000000..5eb5214
--- /dev/null
+++ b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_interface_mixin.py
@@ -0,0 +1,14 @@
+from typing import Protocol
+
+from ..step01_base import Pipeline_Base_Interface, T_in, T_out
+from ..step02_pipeline_as_list import Pipeline_WithPipelineAsList_Interface
+from ..step06_pipeline_processor import Pipeline_WithPipelineProcessor_Interface
+
+
+class PipelineInterfaceMixin(
+ Pipeline_WithPipelineProcessor_Interface,
+ Pipeline_WithPipelineAsList_Interface,
+ Pipeline_Base_Interface,
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/partials/step07_pipeline_default_processor/pipeline_mixin.py b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_mixin.py
new file mode 100644
index 0000000..4aa36ea
--- /dev/null
+++ b/src/_api/core/partials/step07_pipeline_default_processor/pipeline_mixin.py
@@ -0,0 +1,12 @@
+from abc import ABC
+
+from ..step01_base import T_in, T_out
+from .pipeline_interface_mixin import PipelineInterfaceMixin as ImplementsInterface
+from .processors.chained_processor import ChainedProcessor
+
+
+class PipelineMixin(
+ ImplementsInterface[T_in, T_out],
+ ABC,
+):
+ processor_class = ChainedProcessor
diff --git a/src/thecodecrate_pipeline/processors/chained_processor/chained_processor.py b/src/_api/core/partials/step07_pipeline_default_processor/processors/chained_processor.py
similarity index 60%
rename from src/thecodecrate_pipeline/processors/chained_processor/chained_processor.py
rename to src/_api/core/partials/step07_pipeline_default_processor/processors/chained_processor.py
index ff2b93a..bfcf93f 100644
--- a/src/thecodecrate_pipeline/processors/chained_processor/chained_processor.py
+++ b/src/_api/core/partials/step07_pipeline_default_processor/processors/chained_processor.py
@@ -1,11 +1,15 @@
from typing import Any, cast
-from ...core.final.processor import Processor
-from ...core.final.stage_callable import StageInstanceCollection
-from ...core.final.types import T_in, T_out
+from ...step01_base.stage_callable import StageInstanceCollection
+from ...step01_base.types import T_in, T_out
+from ...step06_pipeline_processor.processor import Processor
class ChainedProcessor(Processor[T_in, T_out]):
+ """
+ A processor that processes the payload through a series of stages.
+ """
+
async def process(
self,
payload: T_in,
diff --git a/src/_api/core/partials/step08_pipeline_as_stage/__init__.py b/src/_api/core/partials/step08_pipeline_as_stage/__init__.py
new file mode 100644
index 0000000..8caa6a4
--- /dev/null
+++ b/src/_api/core/partials/step08_pipeline_as_stage/__init__.py
@@ -0,0 +1,9 @@
+from .pipeline_interface_mixin import (
+ PipelineInterfaceMixin as Pipeline_WithPipelineAsStage_Interface,
+)
+from .pipeline_mixin import PipelineMixin as Pipeline_WithPipelineAsStage
+
+__all__ = (
+ "Pipeline_WithPipelineAsStage",
+ "Pipeline_WithPipelineAsStage_Interface",
+)
diff --git a/src/_api/core/partials/step08_pipeline_as_stage/pipeline_interface_mixin.py b/src/_api/core/partials/step08_pipeline_as_stage/pipeline_interface_mixin.py
new file mode 100644
index 0000000..ae4adbf
--- /dev/null
+++ b/src/_api/core/partials/step08_pipeline_as_stage/pipeline_interface_mixin.py
@@ -0,0 +1,20 @@
+from typing import Protocol
+
+from ..step01_base import Pipeline_Base_Interface, T_in, T_out
+from ..step02_pipeline_as_list import Pipeline_WithPipelineAsList_Interface
+from ..step06_pipeline_processor import Pipeline_WithPipelineProcessor_Interface
+from ..step07_pipeline_default_processor import (
+ Pipeline_WithPipelineDefaultProcessor_Interface,
+)
+from .stage_stub_interface import StageStubInterface
+
+
+class PipelineInterfaceMixin(
+ StageStubInterface[T_in, T_out],
+ Pipeline_WithPipelineDefaultProcessor_Interface[T_in, T_out],
+ Pipeline_WithPipelineProcessor_Interface[T_in, T_out],
+ Pipeline_WithPipelineAsList_Interface,
+ Pipeline_Base_Interface,
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/partials/step08_pipeline_as_stage/pipeline_mixin.py b/src/_api/core/partials/step08_pipeline_as_stage/pipeline_mixin.py
new file mode 100644
index 0000000..ef2b8e5
--- /dev/null
+++ b/src/_api/core/partials/step08_pipeline_as_stage/pipeline_mixin.py
@@ -0,0 +1,16 @@
+from abc import ABC
+from typing import Any
+
+from ..step01_base import T_in, T_out
+from .pipeline_interface_mixin import PipelineInterfaceMixin as ImplementsInterface
+
+
+class PipelineMixin(
+ ImplementsInterface[T_in, T_out],
+ ABC,
+):
+ async def __call__(self, payload: T_in, *args: Any, **kwds: Any) -> T_out:
+ """
+ Processes the payload through the pipeline.
+ """
+ return await self.process(payload, *args, **kwds)
diff --git a/src/_api/core/partials/step08_pipeline_as_stage/stage_stub_interface.py b/src/_api/core/partials/step08_pipeline_as_stage/stage_stub_interface.py
new file mode 100644
index 0000000..b068ce7
--- /dev/null
+++ b/src/_api/core/partials/step08_pipeline_as_stage/stage_stub_interface.py
@@ -0,0 +1,12 @@
+from typing import Protocol
+
+from ..step01_base import Stage_Base_Interface, T_in, T_out
+from ..step03_stage_as_callable import Stage_WithStageAsCallable_Interface
+
+
+class StageStubInterface(
+ Stage_WithStageAsCallable_Interface[T_in, T_out],
+ Stage_Base_Interface,
+ Protocol[T_in, T_out],
+):
+ pass
diff --git a/src/_api/core/support/__init__.py b/src/_api/core/support/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/thecodecrate_pipeline/core/support/act_as_factory/__init__.py b/src/_api/core/support/act_as_factory/__init__.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/act_as_factory/__init__.py
rename to src/_api/core/support/act_as_factory/__init__.py
diff --git a/src/thecodecrate_pipeline/core/support/act_as_factory/act_as_factory.py b/src/_api/core/support/act_as_factory/act_as_factory.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/act_as_factory/act_as_factory.py
rename to src/_api/core/support/act_as_factory/act_as_factory.py
diff --git a/src/thecodecrate_pipeline/core/support/act_as_factory/act_as_factory_interface.py b/src/_api/core/support/act_as_factory/act_as_factory_interface.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/act_as_factory/act_as_factory_interface.py
rename to src/_api/core/support/act_as_factory/act_as_factory_interface.py
diff --git a/src/thecodecrate_pipeline/core/support/act_as_list/__init__.py b/src/_api/core/support/act_as_list/__init__.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/act_as_list/__init__.py
rename to src/_api/core/support/act_as_list/__init__.py
diff --git a/src/thecodecrate_pipeline/core/support/act_as_list/act_as_list.py b/src/_api/core/support/act_as_list/act_as_list.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/act_as_list/act_as_list.py
rename to src/_api/core/support/act_as_list/act_as_list.py
diff --git a/src/thecodecrate_pipeline/core/support/act_as_list/act_as_list_interface.py b/src/_api/core/support/act_as_list/act_as_list_interface.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/act_as_list/act_as_list_interface.py
rename to src/_api/core/support/act_as_list/act_as_list_interface.py
diff --git a/src/thecodecrate_pipeline/core/support/act_as_list/types.py b/src/_api/core/support/act_as_list/types.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/act_as_list/types.py
rename to src/_api/core/support/act_as_list/types.py
diff --git a/src/thecodecrate_pipeline/core/support/clonable/__init__.py b/src/_api/core/support/clonable/__init__.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/clonable/__init__.py
rename to src/_api/core/support/clonable/__init__.py
diff --git a/src/thecodecrate_pipeline/core/support/clonable/clonable.py b/src/_api/core/support/clonable/clonable.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/clonable/clonable.py
rename to src/_api/core/support/clonable/clonable.py
diff --git a/src/thecodecrate_pipeline/core/support/clonable/clonable_interface.py b/src/_api/core/support/clonable/clonable_interface.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/clonable/clonable_interface.py
rename to src/_api/core/support/clonable/clonable_interface.py
diff --git a/src/thecodecrate_pipeline/core/support/has_call_async/__init__.py b/src/_api/core/support/has_call_async/__init__.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/has_call_async/__init__.py
rename to src/_api/core/support/has_call_async/__init__.py
diff --git a/src/thecodecrate_pipeline/core/support/has_call_async/has_call_async.py b/src/_api/core/support/has_call_async/has_call_async.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/has_call_async/has_call_async.py
rename to src/_api/core/support/has_call_async/has_call_async.py
diff --git a/src/thecodecrate_pipeline/core/support/has_call_async/has_call_async_interface.py b/src/_api/core/support/has_call_async/has_call_async_interface.py
similarity index 100%
rename from src/thecodecrate_pipeline/core/support/has_call_async/has_call_async_interface.py
rename to src/_api/core/support/has_call_async/has_call_async_interface.py
diff --git a/src/_api/processors/__init__.py b/src/_api/processors/__init__.py
new file mode 100644
index 0000000..0388665
--- /dev/null
+++ b/src/_api/processors/__init__.py
@@ -0,0 +1,16 @@
+# ruff: noqa
+from .chained_processor import (
+ ChainedProcessor,
+ ChainedPipeline,
+ __all__ as _chained_processor_all,
+)
+from .interruptible_processor import (
+ InterruptibleProcessor,
+ InterruptiblePipeline,
+ __all__ as _interruptible_processor_all,
+)
+
+__all__ = (
+ *_chained_processor_all,
+ *_interruptible_processor_all,
+)
diff --git a/src/_api/processors/chained_processor/__init__.py b/src/_api/processors/chained_processor/__init__.py
new file mode 100644
index 0000000..26f2618
--- /dev/null
+++ b/src/_api/processors/chained_processor/__init__.py
@@ -0,0 +1,7 @@
+from .chained_pipeline import ChainedPipeline
+from .chained_processor import ChainedProcessor
+
+__all__ = (
+ "ChainedPipeline",
+ "ChainedProcessor",
+)
diff --git a/src/thecodecrate_pipeline/processors/chained_processor/chained_pipeline.py b/src/_api/processors/chained_processor/chained_pipeline.py
similarity index 60%
rename from src/thecodecrate_pipeline/processors/chained_processor/chained_pipeline.py
rename to src/_api/processors/chained_processor/chained_pipeline.py
index 154881c..613999e 100644
--- a/src/thecodecrate_pipeline/processors/chained_processor/chained_pipeline.py
+++ b/src/_api/processors/chained_processor/chained_pipeline.py
@@ -1,5 +1,4 @@
-from ...core.final.pipeline import Pipeline
-from ...core.final.types import T_in, T_out
+from ...core import Pipeline, T_in, T_out
from .chained_processor import ChainedProcessor
diff --git a/src/_api/processors/chained_processor/chained_processor.py b/src/_api/processors/chained_processor/chained_processor.py
new file mode 100644
index 0000000..2f7c892
--- /dev/null
+++ b/src/_api/processors/chained_processor/chained_processor.py
@@ -0,0 +1,3 @@
+from ...core import ChainedProcessor
+
+__all__ = ("ChainedProcessor",)
diff --git a/src/_api/processors/interruptible_processor/__init__.py b/src/_api/processors/interruptible_processor/__init__.py
new file mode 100644
index 0000000..1e000eb
--- /dev/null
+++ b/src/_api/processors/interruptible_processor/__init__.py
@@ -0,0 +1,7 @@
+from .interruptible_pipeline import InterruptiblePipeline
+from .interruptible_processor import InterruptibleProcessor
+
+__all__ = (
+ "InterruptiblePipeline",
+ "InterruptibleProcessor",
+)
diff --git a/src/thecodecrate_pipeline/processors/interruptible_processor/interruptible_pipeline.py b/src/_api/processors/interruptible_processor/interruptible_pipeline.py
similarity index 80%
rename from src/thecodecrate_pipeline/processors/interruptible_processor/interruptible_pipeline.py
rename to src/_api/processors/interruptible_processor/interruptible_pipeline.py
index 51ce95e..a6af134 100644
--- a/src/thecodecrate_pipeline/processors/interruptible_processor/interruptible_pipeline.py
+++ b/src/_api/processors/interruptible_processor/interruptible_pipeline.py
@@ -1,7 +1,6 @@
from typing import Any
-from ...core.final.pipeline import Pipeline
-from ...core.final.types import T_in, T_out
+from ...core import Pipeline, T_in, T_out
from .interruptible_processor import CheckCallable, InterruptibleProcessor
diff --git a/src/thecodecrate_pipeline/processors/interruptible_processor/interruptible_processor.py b/src/_api/processors/interruptible_processor/interruptible_processor.py
similarity index 85%
rename from src/thecodecrate_pipeline/processors/interruptible_processor/interruptible_processor.py
rename to src/_api/processors/interruptible_processor/interruptible_processor.py
index 0d88abb..d0d1427 100644
--- a/src/thecodecrate_pipeline/processors/interruptible_processor/interruptible_processor.py
+++ b/src/_api/processors/interruptible_processor/interruptible_processor.py
@@ -1,9 +1,7 @@
import inspect
from typing import Any, Awaitable, Callable, cast
-from ...core.final.processor import Processor
-from ...core.final.stage_callable import StageInstanceCollection
-from ...core.final.types import T_in, T_out
+from ...core import Processor, StageInstanceCollection, T_in, T_out
CheckCallable = Callable[[T_in], bool | Awaitable[bool]]
diff --git a/src/_api/py.typed b/src/_api/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/src/thecodecrate_pipeline/__init__.py b/src/thecodecrate_pipeline/__init__.py
index 4f3448c..af578fb 100644
--- a/src/thecodecrate_pipeline/__init__.py
+++ b/src/thecodecrate_pipeline/__init__.py
@@ -1,110 +1,34 @@
-from .core.final.pipeline import Pipeline
-from .core.final.pipeline_factory import PipelineFactory
-from .core.final.pipeline_factory_interface import PipelineFactoryInterface
-from .core.final.pipeline_interface import PipelineInterface
-from .core.final.processor import Processor
-from .core.final.processor_interface import ProcessorInterface
-from .core.final.stage import Stage
-from .core.final.stage_interface import StageInterface
-from .core.final.types import T_in, T_out
-from .core.partials.step01_base.pipeline import Pipeline as WithPipelineBase
-from .core.partials.step01_base.pipeline_interface import (
- PipelineInterface as WithPipelineBaseInterface,
-)
-from .core.partials.step01_base.stage import Stage as WithStageBase
-from .core.partials.step01_base.stage_callable import (
+# Version of the package
+# DO NOT MODIFY MANUALLY
+# This will be updated by `bumpver` command.
+# - Make sure to commit all changes first before running `bumpver`.
+# - Run `bumpver update --[minor|major|patch]`
+__version__ = "1.23.0"
+
+# ruff: noqa
+from _api import (
+ ChainedPipeline,
+ ChainedProcessor,
+ InterruptiblePipeline,
+ InterruptibleProcessor,
+ Pipeline,
+ PipelineFactory,
+ PipelineFactoryInterface,
+ PipelineInterface,
+ Processor,
+ ProcessorInterface,
+ Stage,
StageCallable,
StageClassOrInstance,
StageCollection,
StageInstance,
StageInstanceCollection,
+ StageInterface,
+ T_in,
+ T_out,
)
-from .core.partials.step01_base.stage_interface import (
- StageInterface as WithStageBaseInterface,
-)
-from .core.partials.step02_pipeline_as_list.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineAsListInterface,
-)
-from .core.partials.step02_pipeline_as_list.pipeline_mixin import (
- PipelineMixin as WithPipelineAsList,
-)
-from .core.partials.step03_stage_as_callable.stage_interface_mixin import (
- StageInterfaceMixin as WithStageAsCallableInterface,
-)
-from .core.partials.step03_stage_as_callable.stage_mixin import (
- StageMixin as WithStageAsCallable,
-)
-from .core.partials.step06_pipeline_processor.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineProcessorInterface,
-)
-from .core.partials.step06_pipeline_processor.pipeline_mixin import (
- PipelineMixin as WithPipelineProcessor,
+from _api import (
+ __all__ as _api_all,
)
-from .core.partials.step06_pipeline_processor.processor import (
- Processor as WithProcessorBase,
-)
-from .core.partials.step06_pipeline_processor.processor_interface import (
- ProcessorInterface as WithProcessorBaseInterface,
-)
-from .core.partials.step07_pipeline_as_stage.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineAsStageInterface,
-)
-from .core.partials.step07_pipeline_as_stage.pipeline_mixin import (
- PipelineMixin as WithPipelineAsStage,
-)
-from .processors.chained_processor.chained_pipeline import ChainedPipeline
-from .processors.chained_processor.chained_processor import ChainedProcessor
-from .processors.interruptible_processor.interruptible_pipeline import (
- InterruptiblePipeline,
-)
-from .processors.interruptible_processor.interruptible_processor import (
- InterruptibleProcessor,
-)
-
-# Version of the package
-# DO NOT MODIFY MANUALLY
-# This will be updated by `bumpver` command.
-# - Make sure to commit all changes first before running `bumpver`.
-# - Run `bumpver update --[minor|major|patch]`
-__version__ = "1.23.0"
-# Expose the public API
-__all__ = [
- # Core
- "Pipeline",
- "PipelineInterface",
- "Stage",
- "StageInterface",
- "Processor",
- "ProcessorInterface",
- "PipelineFactory",
- "PipelineFactoryInterface",
- # Types
- "T_in",
- "T_out",
- "StageCallable",
- "StageInstance",
- "StageInstanceCollection",
- "StageClassOrInstance",
- "StageCollection",
- # Processors
- "ChainedProcessor",
- "ChainedPipeline",
- "InterruptibleProcessor",
- "InterruptiblePipeline",
- # Partials
- "WithPipelineBase",
- "WithPipelineBaseInterface",
- "WithStageBase",
- "WithStageBaseInterface",
- "WithPipelineAsList",
- "WithPipelineAsListInterface",
- "WithPipelineProcessor",
- "WithPipelineProcessorInterface",
- "WithProcessorBase",
- "WithProcessorBaseInterface",
- "WithPipelineAsStage",
- "WithPipelineAsStageInterface",
- "WithStageAsCallable",
- "WithStageAsCallableInterface",
-]
+__all__ = (*_api_all,)
diff --git a/src/thecodecrate_pipeline/core/final/pipeline.py b/src/thecodecrate_pipeline/core/final/pipeline.py
deleted file mode 100644
index 21df7e3..0000000
--- a/src/thecodecrate_pipeline/core/final/pipeline.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from ...processors.chained_processor.chained_processor import ChainedProcessor
-from ..partials.step01_base.pipeline import (
- Pipeline as WithPipelineBaseConcern,
-)
-from ..partials.step01_base.types import T_in, T_out
-from ..partials.step02_pipeline_as_list.pipeline_mixin import (
- PipelineMixin as WithPipelineAsListConcern,
-)
-from ..partials.step04_pipeline_declared_stages.pipeline_mixin import (
- PipelineMixin as WithPipelineDeclaredStagesConcern,
-)
-from ..partials.step06_pipeline_processor.pipeline_mixin import (
- PipelineMixin as WithPipelineProcessorConcern,
-)
-from ..partials.step07_pipeline_as_stage.pipeline_mixin import (
- PipelineMixin as WithPipelineAsStageConcern,
-)
-from .pipeline_interface import (
- PipelineInterface as ImplementsPipelineInterface,
-)
-
-
-class Pipeline(
- WithPipelineAsStageConcern[T_in, T_out],
- WithPipelineProcessorConcern[T_in, T_out],
- WithPipelineDeclaredStagesConcern,
- WithPipelineAsListConcern,
- WithPipelineBaseConcern,
- ImplementsPipelineInterface[T_in, T_out],
-):
- processor_class = ChainedProcessor
diff --git a/src/thecodecrate_pipeline/core/final/pipeline_factory.py b/src/thecodecrate_pipeline/core/final/pipeline_factory.py
deleted file mode 100644
index 638dad0..0000000
--- a/src/thecodecrate_pipeline/core/final/pipeline_factory.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Generic
-
-from ..partials.step01_base.types import T_in, T_out
-from ..partials.step05_pipeline_factory.pipeline_factory import (
- PipelineFactory as WithPipelineFactoryBaseConcern,
-)
-from ..partials.step06_pipeline_processor.pipeline_factory_mixin import (
- PipelineFactoryMixin as WithProcessorConcern,
-)
-from .pipeline import Pipeline
-from .pipeline_factory_interface import (
- PipelineFactoryInterface as ImplementsPipelineFactoryInterface,
-)
-
-
-class PipelineFactory(
- WithProcessorConcern,
- WithPipelineFactoryBaseConcern[Pipeline[T_in, T_out]],
- ImplementsPipelineFactoryInterface,
- Generic[T_in, T_out],
-):
- _model_class = Pipeline
diff --git a/src/thecodecrate_pipeline/core/final/pipeline_factory_interface.py b/src/thecodecrate_pipeline/core/final/pipeline_factory_interface.py
deleted file mode 100644
index ac772ac..0000000
--- a/src/thecodecrate_pipeline/core/final/pipeline_factory_interface.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from typing import Protocol
-
-from ..partials.step01_base.pipeline_interface import PipelineInterface
-from ..partials.step05_pipeline_factory.pipeline_factory_interface import (
- PipelineFactoryInterface as WithPipelineFactoryBaseInterface,
-)
-from ..partials.step06_pipeline_processor.pipeline_factory_interface_mixin import ( # noqa
- PipelineFactoryInterfaceMixin as WithProcessorInterface,
-)
-
-
-class PipelineFactoryInterface(
- WithProcessorInterface,
- WithPipelineFactoryBaseInterface[PipelineInterface],
- Protocol,
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/final/pipeline_interface.py b/src/thecodecrate_pipeline/core/final/pipeline_interface.py
deleted file mode 100644
index a57596c..0000000
--- a/src/thecodecrate_pipeline/core/final/pipeline_interface.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from typing import Protocol
-
-from ..partials.step01_base.pipeline_interface import (
- PipelineInterface as WithPipelineBaseInterface,
-)
-from ..partials.step01_base.types import T_in, T_out
-from ..partials.step02_pipeline_as_list.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineAsListInterface,
-)
-from ..partials.step04_pipeline_declared_stages.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineDeclaredStagesInterface,
-)
-from ..partials.step06_pipeline_processor.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineProcessorInterface,
-)
-from ..partials.step07_pipeline_as_stage.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineAsStageInterface,
-)
-
-
-class PipelineInterface(
- WithPipelineAsStageInterface[T_in, T_out],
- WithPipelineProcessorInterface[T_in, T_out],
- WithPipelineDeclaredStagesInterface,
- WithPipelineAsListInterface,
- WithPipelineBaseInterface,
- Protocol[T_in, T_out],
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/final/processor.py b/src/thecodecrate_pipeline/core/final/processor.py
deleted file mode 100644
index c68b0ee..0000000
--- a/src/thecodecrate_pipeline/core/final/processor.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from abc import ABC
-
-from ..partials.step01_base.types import T_in, T_out
-from ..partials.step06_pipeline_processor.processor import (
- Processor as WithProcessorBaseConcern,
-)
-from .processor_interface import (
- ProcessorInterface as ImplementsProcessorInterface,
-)
-
-
-class Processor(
- WithProcessorBaseConcern[T_in, T_out],
- ImplementsProcessorInterface[T_in, T_out],
- ABC,
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/final/processor_interface.py b/src/thecodecrate_pipeline/core/final/processor_interface.py
deleted file mode 100644
index 707d75b..0000000
--- a/src/thecodecrate_pipeline/core/final/processor_interface.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from typing import Protocol
-
-from ..partials.step01_base.types import T_in, T_out
-from ..partials.step06_pipeline_processor.processor_interface import (
- ProcessorInterface as WithProcessorBaseInterface,
-)
-
-
-class ProcessorInterface(
- WithProcessorBaseInterface[T_in, T_out],
- Protocol[T_in, T_out],
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/final/stage.py b/src/thecodecrate_pipeline/core/final/stage.py
deleted file mode 100644
index 1fc10c4..0000000
--- a/src/thecodecrate_pipeline/core/final/stage.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from abc import ABC
-
-from ..partials.step01_base.stage import (
- Stage as WithStageBaseConcern,
-)
-from ..partials.step01_base.types import T_in, T_out
-from ..partials.step03_stage_as_callable.stage_mixin import (
- StageMixin as WithStageAsCallableConcern,
-)
-from .stage_interface import StageInterface as ImplementsStageInterface
-
-
-class Stage(
- WithStageAsCallableConcern[T_in, T_out],
- WithStageBaseConcern,
- ImplementsStageInterface,
- ABC,
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/final/stage_interface.py b/src/thecodecrate_pipeline/core/final/stage_interface.py
deleted file mode 100644
index 31ce02d..0000000
--- a/src/thecodecrate_pipeline/core/final/stage_interface.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from typing import Protocol
-
-from ..partials.step01_base.stage_interface import (
- StageInterface as WithStageBaseInterface,
-)
-from ..partials.step01_base.types import T_in, T_out
-from ..partials.step03_stage_as_callable.stage_interface_mixin import (
- StageInterfaceMixin as WithStageAsCallableInterface,
-)
-
-
-class StageInterface(
- WithStageAsCallableInterface[T_in, T_out],
- WithStageBaseInterface,
- Protocol[T_in, T_out],
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/final/types.py b/src/thecodecrate_pipeline/core/final/types.py
deleted file mode 100644
index d497bf0..0000000
--- a/src/thecodecrate_pipeline/core/final/types.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from ..partials.step01_base.types import T_in, T_out
-
-__all__ = [
- "T_in",
- "T_out",
-]
diff --git a/src/thecodecrate_pipeline/core/partials/step01_base/stage.py b/src/thecodecrate_pipeline/core/partials/step01_base/stage.py
deleted file mode 100644
index 23dc532..0000000
--- a/src/thecodecrate_pipeline/core/partials/step01_base/stage.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from .stage_interface import StageInterface as ImplementsStageInterface
-
-
-class Stage(
- ImplementsStageInterface,
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/stage_facade.py b/src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/stage_facade.py
deleted file mode 100644
index 52263e5..0000000
--- a/src/thecodecrate_pipeline/core/partials/step04_pipeline_declared_stages/stage_facade.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from typing import Protocol
-
-from ..step01_base.stage_interface import (
- StageInterface as WithStageBaseInterface,
-)
-from ..step01_base.types import T_in, T_out
-from ..step03_stage_as_callable.stage_interface_mixin import (
- StageInterfaceMixin as WithStageAsCallableInterface,
-)
-
-
-class StageFacade(
- WithStageAsCallableInterface[T_in, T_out],
- WithStageBaseInterface,
- Protocol[T_in, T_out],
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/pipeline_interface_mixin.py b/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/pipeline_interface_mixin.py
deleted file mode 100644
index 7081fe4..0000000
--- a/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/pipeline_interface_mixin.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from typing import Protocol
-
-from ..step01_base.pipeline_interface import (
- PipelineInterface as WithPipelineBaseInterface,
-)
-from ..step01_base.types import T_in, T_out
-from ..step02_pipeline_as_list.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineAsListInterface,
-)
-from ..step06_pipeline_processor.pipeline_interface_mixin import (
- PipelineInterfaceMixin as WithPipelineProcessorInterface,
-)
-from .stage_facade import StageFacade as WithStageInterface
-
-
-class PipelineInterfaceMixin(
- WithStageInterface[T_in, T_out],
- WithPipelineProcessorInterface[T_in, T_out],
- WithPipelineAsListInterface,
- WithPipelineBaseInterface,
- Protocol[T_in, T_out],
-):
- pass
diff --git a/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/pipeline_mixin.py b/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/pipeline_mixin.py
deleted file mode 100644
index f3b11d2..0000000
--- a/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/pipeline_mixin.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from abc import ABC
-from typing import Any
-
-from ..step01_base.types import T_in, T_out
-from .pipeline_interface_mixin import (
- PipelineInterfaceMixin as ImplementsPipelineInterface,
-)
-
-
-class PipelineMixin(
- ImplementsPipelineInterface[T_in, T_out],
- ABC,
-):
- async def __call__(self, payload: T_in, *args: Any, **kwds: Any) -> T_out:
- return await self.process(payload, *args, **kwds)
diff --git a/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/stage_facade.py b/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/stage_facade.py
deleted file mode 100644
index 52263e5..0000000
--- a/src/thecodecrate_pipeline/core/partials/step07_pipeline_as_stage/stage_facade.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from typing import Protocol
-
-from ..step01_base.stage_interface import (
- StageInterface as WithStageBaseInterface,
-)
-from ..step01_base.types import T_in, T_out
-from ..step03_stage_as_callable.stage_interface_mixin import (
- StageInterfaceMixin as WithStageAsCallableInterface,
-)
-
-
-class StageFacade(
- WithStageAsCallableInterface[T_in, T_out],
- WithStageBaseInterface,
- Protocol[T_in, T_out],
-):
- pass
diff --git a/uv.lock b/uv.lock
index a6ed470..453a888 100644
--- a/uv.lock
+++ b/uv.lock
@@ -19,6 +19,35 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 },
]
+[[package]]
+name = "babel"
+version = "2.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/2a/74/f1bc80f23eeba13393b7222b11d95ca3af2c1e28edca18af487137eefed9/babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316", size = 9348104 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 },
+]
+
+[[package]]
+name = "black"
+version = "24.10.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "mypy-extensions" },
+ { name = "packaging" },
+ { name = "pathspec" },
+ { name = "platformdirs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d8/0d/cc2fb42b8c50d80143221515dd7e4766995bd07c56c9a3ed30baf080b6dc/black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875", size = 645813 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/a0/a993f58d4ecfba035e61fca4e9f64a2ecae838fc9f33ab798c62173ed75c/black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981", size = 1643986 },
+ { url = "https://files.pythonhosted.org/packages/37/d5/602d0ef5dfcace3fb4f79c436762f130abd9ee8d950fa2abdbf8bbc555e0/black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b", size = 1448085 },
+ { url = "https://files.pythonhosted.org/packages/47/6d/a3a239e938960df1a662b93d6230d4f3e9b4a22982d060fc38c42f45a56b/black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2", size = 1760928 },
+ { url = "https://files.pythonhosted.org/packages/dd/cf/af018e13b0eddfb434df4d9cd1b2b7892bab119f7a20123e93f6910982e8/black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b", size = 1436875 },
+ { url = "https://files.pythonhosted.org/packages/8d/a7/4b27c50537ebca8bec139b872861f9d2bf501c5ec51fcf897cb924d9e264/black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d", size = 206898 },
+]
+
[[package]]
name = "bumpver"
version = "2024.1130"
@@ -34,6 +63,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/09/34/57d038ae30374976ce4ec57db9dea95bf55d1b5543b35e77aa9ce3543198/bumpver-2024.1130-py2.py3-none-any.whl", hash = "sha256:8e54220aefe7db25148622f45959f7beb6b8513af0b0429b38b9072566665a49", size = 65273 },
]
+[[package]]
+name = "certifi"
+version = "2024.12.14"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/bd/1d41ee578ce09523c81a15426705dd20969f5abf006d1afe8aeff0dd776a/certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db", size = 166010 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a5/32/8f6669fc4798494966bf446c8c4a162e0b5d893dff088afddf76414f70e1/certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", size = 164927 },
+]
+
[[package]]
name = "cffi"
version = "1.17.1"
@@ -56,6 +94,30 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 },
]
+[[package]]
+name = "charset-normalizer"
+version = "3.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", size = 106620 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f3/89/68a4c86f1a0002810a27f12e9a7b22feb198c59b2f05231349fbce5c06f4/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", size = 194617 },
+ { url = "https://files.pythonhosted.org/packages/4f/cd/8947fe425e2ab0aa57aceb7807af13a0e4162cd21eee42ef5b053447edf5/charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", size = 125310 },
+ { url = "https://files.pythonhosted.org/packages/5b/f0/b5263e8668a4ee9becc2b451ed909e9c27058337fda5b8c49588183c267a/charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", size = 119126 },
+ { url = "https://files.pythonhosted.org/packages/ff/6e/e445afe4f7fda27a533f3234b627b3e515a1b9429bc981c9a5e2aa5d97b6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", size = 139342 },
+ { url = "https://files.pythonhosted.org/packages/a1/b2/4af9993b532d93270538ad4926c8e37dc29f2111c36f9c629840c57cd9b3/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", size = 149383 },
+ { url = "https://files.pythonhosted.org/packages/fb/6f/4e78c3b97686b871db9be6f31d64e9264e889f8c9d7ab33c771f847f79b7/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", size = 142214 },
+ { url = "https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", size = 144104 },
+ { url = "https://files.pythonhosted.org/packages/ee/68/efad5dcb306bf37db7db338338e7bb8ebd8cf38ee5bbd5ceaaaa46f257e6/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", size = 146255 },
+ { url = "https://files.pythonhosted.org/packages/0c/75/1ed813c3ffd200b1f3e71121c95da3f79e6d2a96120163443b3ad1057505/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", size = 140251 },
+ { url = "https://files.pythonhosted.org/packages/7d/0d/6f32255c1979653b448d3c709583557a4d24ff97ac4f3a5be156b2e6a210/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", size = 148474 },
+ { url = "https://files.pythonhosted.org/packages/ac/a0/c1b5298de4670d997101fef95b97ac440e8c8d8b4efa5a4d1ef44af82f0d/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", size = 151849 },
+ { url = "https://files.pythonhosted.org/packages/04/4f/b3961ba0c664989ba63e30595a3ed0875d6790ff26671e2aae2fdc28a399/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", size = 149781 },
+ { url = "https://files.pythonhosted.org/packages/d8/90/6af4cd042066a4adad58ae25648a12c09c879efa4849c705719ba1b23d8c/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482", size = 144970 },
+ { url = "https://files.pythonhosted.org/packages/cc/67/e5e7e0cbfefc4ca79025238b43cdf8a2037854195b37d6417f3d0895c4c2/charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", size = 94973 },
+ { url = "https://files.pythonhosted.org/packages/65/97/fc9bbc54ee13d33dc54a7fcf17b26368b18505500fc01e228c27b5222d80/charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", size = 102308 },
+ { url = "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", size = 49446 },
+]
+
[[package]]
name = "click"
version = "8.1.7"
@@ -117,6 +179,12 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/26/74/b0729f196f328ac55e42b1e22ec2f16d8bcafe4b8158a26ec9f1cdd1d93e/coverage-7.6.9-cp313-cp313t-win_amd64.whl", hash = "sha256:97ddc94d46088304772d21b060041c97fc16bdda13c6c7f9d8fcd8d5ae0d8611", size = 211815 },
]
+[[package]]
+name = "csscompressor"
+version = "0.9.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f1/2a/8c3ac3d8bc94e6de8d7ae270bb5bc437b210bb9d6d9e46630c98f4abd20c/csscompressor-0.9.5.tar.gz", hash = "sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05", size = 237808 }
+
[[package]]
name = "debugpy"
version = "1.8.9"
@@ -148,6 +216,71 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/fd/afcd0496feca3276f509df3dbd5dae726fcc756f1a08d9e25abe1733f962/executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf", size = 25805 },
]
+[[package]]
+name = "ghp-import"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "python-dateutil" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034 },
+]
+
+[[package]]
+name = "gitdb"
+version = "4.0.11"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "smmap" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/19/0d/bbb5b5ee188dec84647a4664f3e11b06ade2bde568dbd489d9d64adef8ed/gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b", size = 394469 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/fd/5b/8f0c4a5bb9fd491c277c21eff7ccae71b47d43c4446c9d0c6cff2fe8c2c4/gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", size = 62721 },
+]
+
+[[package]]
+name = "gitpython"
+version = "3.1.43"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "gitdb" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b6/a1/106fd9fa2dd989b6fb36e5893961f82992cf676381707253e0bf93eb1662/GitPython-3.1.43.tar.gz", hash = "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c", size = 214149 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff", size = 207337 },
+]
+
+[[package]]
+name = "griffe"
+version = "1.5.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d4/c9/8167810358ca129839156dc002526e7398b5fad4a9d7b6e88b875e802d0d/griffe-1.5.1.tar.gz", hash = "sha256:72964f93e08c553257706d6cd2c42d1c172213feb48b2be386f243380b405d4b", size = 384113 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ab/00/e693a155da0a2a72fd2df75b8fe338146cae59d590ad6f56800adde90cb5/griffe-1.5.1-py3-none-any.whl", hash = "sha256:ad6a7980f8c424c9102160aafa3bcdf799df0e75f7829d75af9ee5aef656f860", size = 127132 },
+]
+
+[[package]]
+name = "htmlmin2"
+version = "0.1.13"
+source = { registry = "https://pypi.org/simple" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/be/31/a76f4bfa885f93b8167cb4c85cf32b54d1f64384d0b897d45bc6d19b7b45/htmlmin2-0.1.13-py3-none-any.whl", hash = "sha256:75609f2a42e64f7ce57dbff28a39890363bde9e7e5885db633317efbdf8c79a2", size = 34486 },
+]
+
+[[package]]
+name = "idna"
+version = "3.10"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
+]
+
[[package]]
name = "iniconfig"
version = "2.0.0"
@@ -213,6 +346,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278 },
]
+[[package]]
+name = "jinja2"
+version = "3.1.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markupsafe" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 },
+]
+
+[[package]]
+name = "jsmin"
+version = "3.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/5e/73/e01e4c5e11ad0494f4407a3f623ad4d87714909f50b17a06ed121034ff6e/jsmin-3.0.1.tar.gz", hash = "sha256:c0959a121ef94542e807a674142606f7e90214a2b3d1eb17300244bbb5cc2bfc", size = 13925 }
+
[[package]]
name = "jupyter-client"
version = "8.6.3"
@@ -252,6 +403,43 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/cf/e3/35764404a4b7e2021be1f88f42264c2e92e0c4720273559a62461ce64a47/lexid-2021.1006-py2.py3-none-any.whl", hash = "sha256:5526bb5606fd74c7add23320da5f02805bddd7c77916f2dc1943e6bada8605ed", size = 7587 },
]
+[[package]]
+name = "markdown"
+version = "3.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/54/28/3af612670f82f4c056911fbbbb42760255801b3068c48de792d354ff4472/markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2", size = 357086 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3f/08/83871f3c50fc983b88547c196d11cf8c3340e37c32d2e9d6152abe2c61f7/Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803", size = 106349 },
+]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 },
+ { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 },
+ { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 },
+ { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 },
+ { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 },
+ { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 },
+ { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 },
+ { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 },
+ { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 },
+ { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 },
+ { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 },
+ { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 },
+ { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 },
+ { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 },
+ { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 },
+ { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 },
+ { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 },
+ { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 },
+ { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 },
+ { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
+]
+
[[package]]
name = "matplotlib-inline"
version = "0.1.7"
@@ -264,6 +452,187 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899 },
]
+[[package]]
+name = "mergedeep"
+version = "1.3.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354 },
+]
+
+[[package]]
+name = "mkdocs"
+version = "1.6.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "colorama", marker = "platform_system == 'Windows'" },
+ { name = "ghp-import" },
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "markupsafe" },
+ { name = "mergedeep" },
+ { name = "mkdocs-get-deps" },
+ { name = "packaging" },
+ { name = "pathspec" },
+ { name = "pyyaml" },
+ { name = "pyyaml-env-tag" },
+ { name = "watchdog" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451 },
+]
+
+[[package]]
+name = "mkdocs-autorefs"
+version = "1.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown" },
+ { name = "markupsafe" },
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/fb/ae/0f1154c614d6a8b8a36fff084e5b82af3a15f7d2060cf0dcdb1c53297a71/mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f", size = 40262 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/71/26/4d39d52ea2219604053a4d05b98e90d6a335511cc01806436ec4886b1028/mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f", size = 16522 },
+]
+
+[[package]]
+name = "mkdocs-gen-files"
+version = "0.5.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/48/85/2d634462fd59136197d3126ca431ffb666f412e3db38fd5ce3a60566303e/mkdocs_gen_files-0.5.0.tar.gz", hash = "sha256:4c7cf256b5d67062a788f6b1d035e157fc1a9498c2399be9af5257d4ff4d19bc", size = 7539 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl", hash = "sha256:7ac060096f3f40bd19039e7277dd3050be9a453c8ac578645844d4d91d7978ea", size = 8380 },
+]
+
+[[package]]
+name = "mkdocs-get-deps"
+version = "0.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mergedeep" },
+ { name = "platformdirs" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521 },
+]
+
+[[package]]
+name = "mkdocs-git-revision-date-localized-plugin"
+version = "1.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "babel" },
+ { name = "gitpython" },
+ { name = "mkdocs" },
+ { name = "pytz" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/73/85/6dc9d4eca486ed5734a05f7fd5c612a8e60a35e65610dad6aa9c58118c3f/mkdocs_git_revision_date_localized_plugin-1.3.0.tar.gz", hash = "sha256:439e2f14582204050a664c258861c325064d97cdc848c541e48bb034a6c4d0cb", size = 384797 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/67/e5/ffeb92db53af8c3aa2d92e21a3cf6b5f83eee7e03b9cf9234ef6b30230d5/mkdocs_git_revision_date_localized_plugin-1.3.0-py3-none-any.whl", hash = "sha256:c99377ee119372d57a9e47cff4e68f04cce634a74831c06bc89b33e456e840a1", size = 22549 },
+]
+
+[[package]]
+name = "mkdocs-material"
+version = "9.5.48"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "babel" },
+ { name = "colorama" },
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "mkdocs" },
+ { name = "mkdocs-material-extensions" },
+ { name = "paginate" },
+ { name = "pygments" },
+ { name = "pymdown-extensions" },
+ { name = "regex" },
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/73/e3/925e4c619c03cd538b77d329479f64d75ed9ae35f5d936a19023204de6eb/mkdocs_material-9.5.48.tar.gz", hash = "sha256:a582531e8b34f4c7ed38c29d5c44763053832cf2a32f7409567e0c74749a47db", size = 3936033 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3e/c2/5cb2482c12d3473c00b6a8b8fe7305613142d418d87871edb83a9eb89981/mkdocs_material-9.5.48-py3-none-any.whl", hash = "sha256:b695c998f4b939ce748adbc0d3bff73fa886a670ece948cf27818fa115dc16f8", size = 8666114 },
+]
+
+[[package]]
+name = "mkdocs-material-extensions"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728 },
+]
+
+[[package]]
+name = "mkdocs-minify-plugin"
+version = "0.8.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "csscompressor" },
+ { name = "htmlmin2" },
+ { name = "jsmin" },
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/52/67/fe4b77e7a8ae7628392e28b14122588beaf6078b53eb91c7ed000fd158ac/mkdocs-minify-plugin-0.8.0.tar.gz", hash = "sha256:bc11b78b8120d79e817308e2b11539d790d21445eb63df831e393f76e52e753d", size = 8366 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1b/cd/2e8d0d92421916e2ea4ff97f10a544a9bd5588eb747556701c983581df13/mkdocs_minify_plugin-0.8.0-py3-none-any.whl", hash = "sha256:5fba1a3f7bd9a2142c9954a6559a57e946587b21f133165ece30ea145c66aee6", size = 6723 },
+]
+
+[[package]]
+name = "mkdocstrings"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "markupsafe" },
+ { name = "mkdocs" },
+ { name = "mkdocs-autorefs" },
+ { name = "platformdirs" },
+ { name = "pymdown-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e2/5a/5de70538c2cefae7ac3a15b5601e306ef3717290cb2aab11d51cbbc2d1c0/mkdocstrings-0.27.0.tar.gz", hash = "sha256:16adca6d6b0a1f9e0c07ff0b02ced8e16f228a9d65a37c063ec4c14d7b76a657", size = 94830 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cd/10/4c27c3063c2b3681a4b7942f8dbdeb4fa34fecb2c19b594e7345ebf4f86f/mkdocstrings-0.27.0-py3-none-any.whl", hash = "sha256:6ceaa7ea830770959b55a16203ac63da24badd71325b96af950e59fd37366332", size = 30658 },
+]
+
+[package.optional-dependencies]
+python = [
+ { name = "mkdocstrings-python" },
+]
+
+[[package]]
+name = "mkdocstrings-python"
+version = "1.12.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "griffe" },
+ { name = "mkdocs-autorefs" },
+ { name = "mkdocstrings" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/23/ec/cb6debe2db77f1ef42b25b21d93b5021474de3037cd82385e586aee72545/mkdocstrings_python-1.12.2.tar.gz", hash = "sha256:7a1760941c0b52a2cd87b960a9e21112ffe52e7df9d0b9583d04d47ed2e186f3", size = 168207 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5b/c1/ac524e1026d9580cbc654b5d19f5843c8b364a66d30f956372cd09fd2f92/mkdocstrings_python-1.12.2-py3-none-any.whl", hash = "sha256:7f7d40d6db3cb1f5d19dbcd80e3efe4d0ba32b073272c0c0de9de2e604eda62a", size = 111759 },
+]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
+]
+
[[package]]
name = "nest-asyncio"
version = "1.6.0"
@@ -282,6 +651,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
]
+[[package]]
+name = "paginate"
+version = "0.5.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746 },
+]
+
[[package]]
name = "parso"
version = "0.8.4"
@@ -291,6 +669,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 },
]
+[[package]]
+name = "pathspec"
+version = "0.12.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 },
+]
+
[[package]]
name = "pexpect"
version = "4.9.0"
@@ -384,6 +771,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 },
]
+[[package]]
+name = "pymdown-extensions"
+version = "10.12"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d8/0b/32f05854cfd432e9286bb41a870e0d1a926b72df5f5cdb6dec962b2e369e/pymdown_extensions-10.12.tar.gz", hash = "sha256:b0ee1e0b2bef1071a47891ab17003bfe5bf824a398e13f49f8ed653b699369a7", size = 840790 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/53/32/95a164ddf533bd676cbbe878e36e89b4ade3efde8dd61d0148c90cbbe57e/pymdown_extensions-10.12-py3-none-any.whl", hash = "sha256:49f81412242d3527b8b4967b990df395c89563043bc51a3d2d7d500e52123b77", size = 263448 },
+]
+
[[package]]
name = "pytest"
version = "8.3.4"
@@ -436,6 +836,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
]
+[[package]]
+name = "pytz"
+version = "2024.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 },
+]
+
[[package]]
name = "pywin32"
version = "308"
@@ -446,6 +855,35 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/26/df/2b63e3e4f2df0224f8aaf6d131f54fe4e8c96400eb9df563e2aae2e1a1f9/pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd", size = 7974986 },
]
+[[package]]
+name = "pyyaml"
+version = "6.0.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 },
+ { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 },
+ { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 },
+ { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 },
+ { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 },
+ { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 },
+ { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 },
+ { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 },
+ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
+]
+
+[[package]]
+name = "pyyaml-env-tag"
+version = "0.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/fb/8e/da1c6c58f751b70f8ceb1eb25bc25d524e8f14fe16edcce3f4e3ba08629c/pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", size = 5631 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069", size = 3911 },
+]
+
[[package]]
name = "pyzmq"
version = "26.2.0"
@@ -478,6 +916,44 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/7b/d6/32fd69744afb53995619bc5effa2a405ae0d343cd3e747d0fbc43fe894ee/pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0", size = 1392485 },
]
+[[package]]
+name = "regex"
+version = "2024.11.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/8e/5f/bd69653fbfb76cf8604468d3b4ec4c403197144c7bfe0e6a5fc9e02a07cb/regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", size = 399494 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/90/73/bcb0e36614601016552fa9344544a3a2ae1809dc1401b100eab02e772e1f/regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84", size = 483525 },
+ { url = "https://files.pythonhosted.org/packages/0f/3f/f1a082a46b31e25291d830b369b6b0c5576a6f7fb89d3053a354c24b8a83/regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4", size = 288324 },
+ { url = "https://files.pythonhosted.org/packages/09/c9/4e68181a4a652fb3ef5099e077faf4fd2a694ea6e0f806a7737aff9e758a/regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0", size = 284617 },
+ { url = "https://files.pythonhosted.org/packages/fc/fd/37868b75eaf63843165f1d2122ca6cb94bfc0271e4428cf58c0616786dce/regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0", size = 795023 },
+ { url = "https://files.pythonhosted.org/packages/c4/7c/d4cd9c528502a3dedb5c13c146e7a7a539a3853dc20209c8e75d9ba9d1b2/regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7", size = 833072 },
+ { url = "https://files.pythonhosted.org/packages/4f/db/46f563a08f969159c5a0f0e722260568425363bea43bb7ae370becb66a67/regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7", size = 823130 },
+ { url = "https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c", size = 796857 },
+ { url = "https://files.pythonhosted.org/packages/10/db/ac718a08fcee981554d2f7bb8402f1faa7e868c1345c16ab1ebec54b0d7b/regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3", size = 784006 },
+ { url = "https://files.pythonhosted.org/packages/c2/41/7da3fe70216cea93144bf12da2b87367590bcf07db97604edeea55dac9ad/regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07", size = 781650 },
+ { url = "https://files.pythonhosted.org/packages/a7/d5/880921ee4eec393a4752e6ab9f0fe28009435417c3102fc413f3fe81c4e5/regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e", size = 789545 },
+ { url = "https://files.pythonhosted.org/packages/dc/96/53770115e507081122beca8899ab7f5ae28ae790bfcc82b5e38976df6a77/regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6", size = 853045 },
+ { url = "https://files.pythonhosted.org/packages/31/d3/1372add5251cc2d44b451bd94f43b2ec78e15a6e82bff6a290ef9fd8f00a/regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4", size = 860182 },
+ { url = "https://files.pythonhosted.org/packages/ed/e3/c446a64984ea9f69982ba1a69d4658d5014bc7a0ea468a07e1a1265db6e2/regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d", size = 787733 },
+ { url = "https://files.pythonhosted.org/packages/2b/f1/e40c8373e3480e4f29f2692bd21b3e05f296d3afebc7e5dcf21b9756ca1c/regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff", size = 262122 },
+ { url = "https://files.pythonhosted.org/packages/45/94/bc295babb3062a731f52621cdc992d123111282e291abaf23faa413443ea/regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a", size = 273545 },
+]
+
+[[package]]
+name = "requests"
+version = "2.32.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "idna" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
+]
+
[[package]]
name = "ruff"
version = "0.8.2"
@@ -512,6 +988,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
]
+[[package]]
+name = "smmap"
+version = "5.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/88/04/b5bf6d21dc4041000ccba7eb17dd3055feb237e7ffc2c20d3fae3af62baa/smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", size = 22291 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a7/a5/10f97f73544edcdef54409f1d839f6049a0d79df68adbc1ceb24d1aaca42/smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da", size = 24282 },
+]
+
[[package]]
name = "stack-data"
version = "0.6.3"
@@ -528,14 +1013,21 @@ wheels = [
[[package]]
name = "thecodecrate-pipeline"
-version = "1.22.0"
+version = "1.23.0"
source = { editable = "." }
[package.dev-dependencies]
dev = [
+ { name = "black" },
{ name = "bumpver" },
{ name = "debugpy" },
{ name = "ipykernel" },
+ { name = "mkdocs-autorefs" },
+ { name = "mkdocs-gen-files" },
+ { name = "mkdocs-git-revision-date-localized-plugin" },
+ { name = "mkdocs-material" },
+ { name = "mkdocs-minify-plugin" },
+ { name = "mkdocstrings", extra = ["python"] },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-cov" },
@@ -546,9 +1038,16 @@ dev = [
[package.metadata.requires-dev]
dev = [
+ { name = "black", specifier = ">=24.10.0" },
{ name = "bumpver", specifier = ">=2024.1130" },
{ name = "debugpy", specifier = ">=1.8.9" },
{ name = "ipykernel", specifier = ">=6.29.5" },
+ { name = "mkdocs-autorefs", specifier = ">=1.2.0" },
+ { name = "mkdocs-gen-files", specifier = ">=0.5.0" },
+ { name = "mkdocs-git-revision-date-localized-plugin", specifier = ">=1.3.0" },
+ { name = "mkdocs-material", specifier = ">=9.5.48" },
+ { name = "mkdocs-minify-plugin", specifier = ">=0.8.0" },
+ { name = "mkdocstrings", extras = ["python"], specifier = ">=0.27.0" },
{ name = "pytest", specifier = ">=8.3.4" },
{ name = "pytest-asyncio", specifier = ">=0.24.0" },
{ name = "pytest-cov", specifier = ">=6.0.0" },
@@ -591,6 +1090,36 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359 },
]
+[[package]]
+name = "urllib3"
+version = "2.2.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 },
+]
+
+[[package]]
+name = "watchdog"
+version = "6.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480 },
+ { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451 },
+ { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057 },
+ { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079 },
+ { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078 },
+ { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076 },
+ { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077 },
+ { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078 },
+ { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077 },
+ { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078 },
+ { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065 },
+ { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070 },
+ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067 },
+]
+
[[package]]
name = "wcwidth"
version = "0.2.13"