From d81c2cb739b6ce8662558d07441d3e0c35213a6e Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 5 May 2026 09:28:05 -0400 Subject: [PATCH 001/131] Closes #21951: Add convenience scripts for database management (#22113) --- scripts/drop_database.sh | 7 +++++++ scripts/load_database.sh | 11 +++++++++++ scripts/save_database.sh | 7 +++++++ 3 files changed, 25 insertions(+) create mode 100755 scripts/drop_database.sh create mode 100755 scripts/load_database.sh create mode 100755 scripts/save_database.sh diff --git a/scripts/drop_database.sh b/scripts/drop_database.sh new file mode 100755 index 000000000..fdb2ba154 --- /dev/null +++ b/scripts/drop_database.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +DB=${1:-netbox} + +# Drop and re-create the database locally +sudo -u postgres psql -c "drop database $DB" +sudo -u postgres psql -c "create database $DB" diff --git a/scripts/load_database.sh b/scripts/load_database.sh new file mode 100755 index 000000000..4fab3420d --- /dev/null +++ b/scripts/load_database.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +DB=${2:-netbox} + +# Drop and re-create the database locally +sudo -u postgres psql -c "DROP DATABASE $DB" +sudo -u postgres psql -c "CREATE DATABASE $DB" +sudo -u postgres psql -c "GRANT CREATE ON DATABASE $DB TO $DB" + +# Load tables from the production dump +sudo -u postgres psql $DB < $1 diff --git a/scripts/save_database.sh b/scripts/save_database.sh new file mode 100755 index 000000000..4f200877b --- /dev/null +++ b/scripts/save_database.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +DB=${2:-netbox} + +# Dump the database to a file +sudo -u postgres pg_dump $DB > $1 + From 93176be707f1a3fff376e435566f7c3329a2ab4a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 5 May 2026 09:29:57 -0400 Subject: [PATCH 002/131] Prohibit AI-generated issues (#22101) --- CONTRIBUTING.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7d87262d2..577268bef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,7 +35,10 @@ NetBox users are welcome to participate in either role, on stage or in the crowd * Familiarize yourself with [this list of discussion anti-patterns](https://github.com/bradfitz/issue-tracker-behaviors) and make every effort to avoid them. > [!CAUTION] -> We do not currently accept issues submitted via GitHub's API: All issues must be submitted using one of the [provided templates](https://github.com/netbox-community/netbox/issues/new/choose). The templates not only help ensure high-quality submissions, but they also automatically assign issue types and labels for categorization. This does not happen when issues are submitted via the API. +> We do not currently accept issues submitted via GitHub's API: All issues must be submitted using one of the [provided templates](https://github.com/netbox-community/netbox/issues/new/choose). In addition to ensuring high-quality submissions, these templates automatically assign issue types and labels for categorization to help expedite triage. This does not happen when issues are submitted via the API. + +> [!IMPORTANT] +> Every issue submitted to this repository is afforded consideration by a human reviewer. To mitigate abuse, we ask that users refrain from submitting AI-generated issues. Please note that issues which appear to be completely authored by an AI may be rejected without further discussion. ## :bug: Reporting Bugs From 589169f8604dd2d35f7ef79b0a394b773ad9e8af Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Tue, 5 May 2026 15:39:52 +0200 Subject: [PATCH 003/131] chore(ruff): Consolidate tool config into pyproject.toml Move Ruff configuration from ruff.toml into pyproject.toml and remove obsolete Black, isort, and Pylint sections. Consolidates all Python tooling config in a single file following modern Python packaging standards. Fixes #22099 --- pyproject.toml | 98 ++++++++++++++++++++++++++++++++++++++++++++------ ruff.toml | 88 --------------------------------------------- 2 files changed, 87 insertions(+), 99 deletions(-) delete mode 100644 ruff.toml diff --git a/pyproject.toml b/pyproject.toml index 06319e69c..f940a71ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,17 +26,6 @@ Documentation = "https://netboxlabs.com/docs/netbox/" Source = "https://github.com/netbox-community/netbox" Issues = "https://github.com/netbox-community/netbox/issues" -[tool.black] -line-length = 120 -target_version = ['py312', 'py313', 'py314'] -skip-string-normalization = true - -[tool.isort] -profile = "black" - -[tool.pylint] -max-line-length = 120 - [tool.pyright] include = ["netbox"] exclude = [ @@ -45,3 +34,90 @@ exclude = [ ] reportMissingImports = true reportMissingTypeStubs = false + +[tool.ruff] +exclude = [ + ".eggs", + ".git", + ".pyenv", + ".pytest_cache", + ".ruff_cache", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "build", + "dist", + "netbox/project-static/**", + "node_modules", + "site-packages", + "venv", +] + +# Enforce line length and indent-width +line-length = 120 +indent-width = 4 + +# Ignores anything in .gitignore +respect-gitignore = true + +# Always generate Python 3.12-compatible code +target-version = "py312" + +[tool.ruff.lint] +# Pin the effective default rule set used with `preview = true` to match Ruff 0.15.1. +# Ruff 0.15.2 changed the preview defaults, see https://github.com/astral-sh/ruff/releases/tag/0.15.2 +# Keeping this explicit makes ruff deterministic. +select = ["E4", "E7", "E9", "F"] +extend-select = [ + "E1", # pycodestyle errors: indentation-related (e.g., unexpected/missing indent) + "E2", # pycodestyle errors: whitespace-related (e.g., missing whitespace, extra spaces) + "E3", # pycodestyle errors: blank lines / spacing around definitions + "E501", # pycodestyle: line too long (enforced with `line-length` above) + "W", # pycodestyle warnings (various style warnings, often whitespace/newlines) + "I", # import sorting (isort-equivalent) + "RET", # return semantics (flake8-return family: consistent/explicit returns; remove redundant else/assign before return) + "UP", # pyupgrade: modernize syntax for your target Python (e.g., f-strings, built-in generics, newer stdlib idioms) + "RUF022", # ruff: enforce sorted `__all__` lists +] +# If you add a rule to `ignore`, please also update the "Linter Exceptions" section in +# docs/development/style-guide.md. +ignore = [ + "F403", # pyflakes: `from ... import *` used; unable to detect undefined names + "F405", # pyflakes: name may be undefined or defined from star imports + "RET504", # return: unnecessary assignment before `return` (e.g., `x = expr; return x` -> `return expr`) + "UP032", # pyupgrade: prefer f-strings over `str.format(...)` +] +preview = true + +[tool.ruff.lint.isort] +known-first-party = [ + "account", + "circuits", + "core", + "dcim", + "extras", + "ipam", + "netbox", + "tenancy", + "users", + "utilities", + "virtualization", + "vpn", + "wireless", +] + +[tool.ruff.lint.per-file-ignores] +"template_code.py" = ["E501"] +"netbox/netbox/graphql/filter_lookups.py" = ["UP046"] # Strawberry typing: keep `Generic[T]` for now +"netbox/netbox/graphql/scalars.py" = ["UP007"] # Strawberry scalar typing: `Union[...]` required + +[tool.ruff.format] +# Use single quotes for strings. +quote-style = "single" + +# Indent with spaces, rather than tabs. +indent-style = "space" + +# Enforce UNIX line ending +line-ending = "lf" diff --git a/ruff.toml b/ruff.toml deleted file mode 100644 index d50d42115..000000000 --- a/ruff.toml +++ /dev/null @@ -1,88 +0,0 @@ -# Ruff configuration -#################### - -exclude = [ - ".eggs", - ".git", - ".pyenv", - ".pytest_cache", - ".ruff_cache", - ".venv", - ".vscode", - "__pypackages__", - "_build", - "build", - "dist", - "netbox/project-static/**", - "node_modules", - "site-packages", - "venv", -] - -# Enforce line length and indent-width -line-length = 120 -indent-width = 4 - -# Ignores anything in .gitignore -respect-gitignore = true - -# Always generate Python 3.12-compatible code -target-version = "py312" - -[lint] -# Pin the effective default rule set used with `preview = true` to match Ruff 0.15.1. -# Ruff 0.15.2 changed the preview defaults, see https://github.com/astral-sh/ruff/releases/tag/0.15.2 -# Keeping this explicit makes ruff deterministic. -select = ["E4", "E7", "E9", "F"] -extend-select = [ - "E1", # pycodestyle errors: indentation-related (e.g., unexpected/missing indent) - "E2", # pycodestyle errors: whitespace-related (e.g., missing whitespace, extra spaces) - "E3", # pycodestyle errors: blank lines / spacing around definitions - "E501", # pycodestyle: line too long (enforced with `line-length` above) - "W", # pycodestyle warnings (various style warnings, often whitespace/newlines) - "I", # import sorting (isort-equivalent) - "RET", # return semantics (flake8-return family: consistent/explicit returns; remove redundant else/assign before return) - "UP", # pyupgrade: modernize syntax for your target Python (e.g., f-strings, built-in generics, newer stdlib idioms) - "RUF022", # ruff: enforce sorted `__all__` lists -] -# If you add a rule to `ignore`, please also update the "Linter Exceptions" section in -# docs/development/style-guide.md. -ignore = [ - "F403", # pyflakes: `from ... import *` used; unable to detect undefined names - "F405", # pyflakes: name may be undefined or defined from star imports - "RET504", # return: unnecessary assignment before `return` (e.g., `x = expr; return x` -> `return expr`) - "UP032", # pyupgrade: prefer f-strings over `str.format(...)` -] -preview = true - -[lint.isort] -known-first-party = [ - "account", - "circuits", - "core", - "dcim", - "extras", - "ipam", - "netbox", - "tenancy", - "users", - "utilities", - "virtualization", - "vpn", - "wireless", -] - -[lint.per-file-ignores] -"template_code.py" = ["E501"] -"netbox/netbox/graphql/filter_lookups.py" = ["UP046"] # Strawberry typing: keep `Generic[T]` for now -"netbox/netbox/graphql/scalars.py" = ["UP007"] # Strawberry scalar typing: `Union[...]` required - -[format] -# Use single quotes for strings. -quote-style = "single" - -# Indent with spaces, rather than tabs. -indent-style = "space" - -# Enforce UNIX line ending -line-ending = "lf" From f3c5b00932a157afbbed8610aaf601ccec493549 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Tue, 5 May 2026 18:25:06 +0200 Subject: [PATCH 004/131] Closes #22056: Clean up obsolete .gitignore entries and add comments (#22116) --- .gitignore | 68 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index ea2ce9512..71d517354 100644 --- a/.gitignore +++ b/.gitignore @@ -1,33 +1,63 @@ -*.pyc -*.swp -npm-debug.log* +# Python bytecode, cache directories, and test coverage output +__pycache__/ +*.py[cod] +.coverage + +# Python virtual environment created by the installation/upgrade workflow +/venv/ + +# Frontend dependencies and Yarn logs generated during asset development/builds +/netbox/project-static/node_modules/ yarn-debug.log* yarn-error.log* -/netbox/project-static/node_modules -/netbox/project-static/docs/* -!/netbox/project-static/docs/.info + +# Documentation generated by the upgrade/build workflow +/netbox/project-static/docs/ + +# Static files collected by Django +/netbox/static/ + +# Local NetBox configuration files created or copied during installation /netbox/netbox/configuration.py /netbox/netbox/ldap_config.py -/netbox/local/* +/local_requirements.txt + +# Local settings overrides loaded by settings.py if present +/netbox/netbox/local_settings.py + +# Deployment-local files under the optional local directory +/netbox/local/ + +# User-uploaded media files; MEDIA_ROOT defaults to netbox/media/. +# Keep the placeholder so the directory exists in a fresh checkout. /netbox/media/* !/netbox/media/.gitkeep + +# Legacy custom reports; REPORTS_ROOT defaults to netbox/reports/. +# Keep the package marker while ignoring deployment-specific reports. /netbox/reports/* !/netbox/reports/__init__.py + +# Custom scripts; SCRIPTS_ROOT defaults to netbox/scripts/. +# Keep the package marker while ignoring deployment-specific scripts. /netbox/scripts/* !/netbox/scripts/__init__.py -/netbox/static -/venv/ + +# Deployment-local WSGI configuration copied from contrib/ and edited in place +/gunicorn.py +/uwsgi.ini + +# Ignore local helper scripts in the repository root, but keep the tracked upgrade script /*.sh -local_requirements.txt -local_settings.py !upgrade.sh -fabfile.py -gunicorn.py -uwsgi.ini -netbox.log -netbox.pid + +# Git patch/diff files commonly generated locally for review or handoff +/*.patch +/*.diff + +# Common local editor, OS, and runtime-manager metadata +*.swp .DS_Store -.idea -.coverage -.vscode +.idea/ +.vscode/ .python-version From 7e9eac5b87810be31b4c56c7ebec57615bc84426 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Tue, 5 May 2026 19:06:26 +0200 Subject: [PATCH 005/131] Closes #22093: Run coverage only on a single matrix entry (#22117) Add explicit CI job names showing the Python and Node versions, with the coverage job clearly marked in the GitHub Actions UI. Run coverage only for the designated coverage matrix entry to avoid redundant coverage collection and reporting across the full test matrix. Also add the YAML document marker and clean up trailing whitespace. --- .github/workflows/ci.yml | 42 +++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87213a74b..0234c28b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,3 +1,4 @@ +--- name: CI on: @@ -26,6 +27,9 @@ concurrency: jobs: build: + name: >- + Tests (Python ${{ matrix.python-version }}, + Node ${{ matrix.node-version }}${{ matrix.coverage && ', coverage' || '' }}) runs-on: ubuntu-latest env: NETBOX_CONFIGURATION: netbox.configuration_testing @@ -33,6 +37,12 @@ jobs: matrix: python-version: ['3.12', '3.13', '3.14'] node-version: ['20.x'] + include: + - coverage: false + # Run coverage only once, using the Python 3.14 job. + - python-version: '3.14' + node-version: '20.x' + coverage: true services: redis: image: redis @@ -53,35 +63,35 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check Python linting & PEP8 compliance - uses: astral-sh/ruff-action@0ce1b0bf8b818ef400413f810f8a11cdbda0034b # v4.0.0 + uses: astral-sh/ruff-action@0ce1b0bf8b818ef400413f810f8a11cdbda0034b # v4.0.0 with: version: "0.15.10" args: "check --output-format=github" src: "netbox/" - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python-version }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} - + - name: Install Yarn Package Manager run: npm install -g yarn - + - name: Setup Node.js with Yarn Caching - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ matrix.node-version }} cache: yarn cache-dependency-path: netbox/project-static/yarn.lock - + - name: Install Frontend Dependencies run: yarn --cwd netbox/project-static @@ -102,12 +112,22 @@ jobs: - name: Check UI ESLint, TypeScript, and Prettier Compliance run: yarn --cwd netbox/project-static validate - + - name: Validate Static Asset Integrity run: scripts/verify-bundles.sh - name: Run tests - run: coverage run --source="netbox/" netbox/manage.py test netbox/ --parallel + if: ${{ ! matrix.coverage }} + run: python netbox/manage.py test netbox/ --parallel + + - name: Run tests with coverage + if: ${{ matrix.coverage }} + run: >- + coverage run --source="netbox/" + netbox/manage.py test netbox/ --parallel - name: Show coverage report - run: coverage report --skip-covered --omit '*/migrations/*,*/tests/*' + if: ${{ matrix.coverage }} + run: >- + coverage report --skip-covered + --omit '*/migrations/*,*/tests/*' From 30f9d3ed604e2a227a0835ce200bd5958707b1c6 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 05:59:55 +0000 Subject: [PATCH 006/131] Update source translation strings --- netbox/translations/en/LC_MESSAGES/django.po | 11893 +++++++++-------- 1 file changed, 6247 insertions(+), 5646 deletions(-) diff --git a/netbox/translations/en/LC_MESSAGES/django.po b/netbox/translations/en/LC_MESSAGES/django.po index ebdd078b8..98729292d 100644 --- a/netbox/translations/en/LC_MESSAGES/django.po +++ b/netbox/translations/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-28 14:05+0000\n" +"POT-Creation-Date: 2026-05-06 05:59+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,5349 +18,5711 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: account/views.py:122 +#: netbox/account/views.py:122 #, python-brace-format msgid "Logged in as {user}." msgstr "" -#: account/views.py:177 +#: netbox/account/views.py:177 msgid "You have logged out." msgstr "" -#: account/views.py:227 +#: netbox/account/views.py:227 msgid "Your preferences have been updated." msgstr "" -#: account/views.py:255 +#: netbox/account/views.py:255 msgid "LDAP-authenticated user credentials cannot be changed within NetBox." msgstr "" -#: account/views.py:270 +#: netbox/account/views.py:270 msgid "Your password has been changed successfully." msgstr "" -#: circuits/choices.py:21 dcim/choices.py:20 dcim/choices.py:102 -#: dcim/choices.py:204 dcim/choices.py:257 dcim/choices.py:1961 -#: dcim/choices.py:2019 dcim/choices.py:2086 dcim/choices.py:2108 -#: virtualization/choices.py:20 virtualization/choices.py:46 vpn/choices.py:18 -#: vpn/choices.py:281 +#: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 +#: netbox/dcim/choices.py:102 netbox/dcim/choices.py:204 +#: netbox/dcim/choices.py:257 netbox/dcim/choices.py:1961 +#: netbox/dcim/choices.py:2019 netbox/dcim/choices.py:2086 +#: netbox/dcim/choices.py:2108 netbox/virtualization/choices.py:20 +#: netbox/virtualization/choices.py:46 netbox/vpn/choices.py:18 +#: netbox/vpn/choices.py:281 msgid "Planned" msgstr "" -#: circuits/choices.py:22 netbox/navigation/menu.py:338 +#: netbox/circuits/choices.py:22 netbox/netbox/navigation/menu.py:338 msgid "Provisioning" msgstr "" -#: circuits/choices.py:23 core/tables/plugins.py:58 core/tables/tasks.py:23 -#: dcim/choices.py:22 dcim/choices.py:103 dcim/choices.py:155 -#: dcim/choices.py:203 dcim/choices.py:256 dcim/choices.py:2018 -#: dcim/choices.py:2085 dcim/choices.py:2107 extras/tables/tables.py:648 -#: extras/ui/panels.py:441 ipam/choices.py:31 ipam/choices.py:49 -#: ipam/choices.py:69 ipam/choices.py:154 users/forms/bulk_edit.py:41 -#: users/ui/panels.py:38 virtualization/choices.py:22 -#: virtualization/choices.py:45 vpn/choices.py:19 vpn/choices.py:280 -#: wireless/choices.py:25 +#: netbox/circuits/choices.py:23 netbox/core/tables/plugins.py:58 +#: netbox/core/tables/tasks.py:23 netbox/dcim/choices.py:22 +#: netbox/dcim/choices.py:103 netbox/dcim/choices.py:155 +#: netbox/dcim/choices.py:203 netbox/dcim/choices.py:256 +#: netbox/dcim/choices.py:2018 netbox/dcim/choices.py:2085 +#: netbox/dcim/choices.py:2107 netbox/extras/tables/tables.py:648 +#: netbox/extras/ui/panels.py:441 netbox/ipam/choices.py:31 +#: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 +#: netbox/ipam/choices.py:154 netbox/users/forms/bulk_edit.py:41 +#: netbox/users/ui/panels.py:38 netbox/virtualization/choices.py:22 +#: netbox/virtualization/choices.py:45 netbox/vpn/choices.py:19 +#: netbox/vpn/choices.py:280 netbox/wireless/choices.py:25 msgid "Active" msgstr "" -#: circuits/choices.py:24 dcim/choices.py:202 dcim/choices.py:255 -#: dcim/choices.py:2017 dcim/choices.py:2087 dcim/choices.py:2106 -#: virtualization/choices.py:24 virtualization/choices.py:44 +#: netbox/circuits/choices.py:24 netbox/dcim/choices.py:202 +#: netbox/dcim/choices.py:255 netbox/dcim/choices.py:2017 +#: netbox/dcim/choices.py:2087 netbox/dcim/choices.py:2106 +#: netbox/virtualization/choices.py:24 netbox/virtualization/choices.py:44 msgid "Offline" msgstr "" -#: circuits/choices.py:25 +#: netbox/circuits/choices.py:25 msgid "Deprovisioning" msgstr "" -#: circuits/choices.py:26 +#: netbox/circuits/choices.py:26 msgid "Decommissioned" msgstr "" -#: circuits/choices.py:90 dcim/choices.py:2030 dcim/tables/devices.py:1240 -#: templates/dcim/interface/attrs/mac_address.html:3 tenancy/choices.py:17 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:2030 +#: netbox/dcim/tables/devices.py:1240 +#: netbox/templates/dcim/interface/attrs/mac_address.html:3 +#: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "" -#: circuits/choices.py:91 ipam/choices.py:90 tenancy/choices.py:18 +#: netbox/circuits/choices.py:91 netbox/ipam/choices.py:90 +#: netbox/tenancy/choices.py:18 msgid "Secondary" msgstr "" -#: circuits/choices.py:92 tenancy/choices.py:19 +#: netbox/circuits/choices.py:92 netbox/tenancy/choices.py:19 msgid "Tertiary" msgstr "" -#: circuits/choices.py:93 tenancy/choices.py:20 +#: netbox/circuits/choices.py:93 netbox/tenancy/choices.py:20 msgid "Inactive" msgstr "" -#: circuits/choices.py:107 dcim/tables/devices.py:734 -#: templates/dcim/panels/interface_wireless.html:12 vpn/choices.py:63 +#: netbox/circuits/choices.py:107 netbox/dcim/tables/devices.py:734 +#: netbox/templates/dcim/panels/interface_wireless.html:12 +#: netbox/vpn/choices.py:63 msgid "Peer" msgstr "" -#: circuits/choices.py:108 vpn/choices.py:64 +#: netbox/circuits/choices.py:108 netbox/vpn/choices.py:64 msgid "Hub" msgstr "" -#: circuits/choices.py:109 vpn/choices.py:65 +#: netbox/circuits/choices.py:109 netbox/vpn/choices.py:65 msgid "Spoke" msgstr "" -#: circuits/filtersets.py:43 circuits/filtersets.py:223 -#: circuits/filtersets.py:307 dcim/base_filtersets.py:23 dcim/filtersets.py:123 -#: dcim/filtersets.py:182 dcim/filtersets.py:243 dcim/filtersets.py:384 -#: dcim/filtersets.py:542 dcim/filtersets.py:1282 dcim/filtersets.py:1644 -#: dcim/filtersets.py:1751 dcim/filtersets.py:2539 dcim/filtersets.py:2822 -#: dcim/filtersets.py:2883 ipam/filtersets.py:1005 -#: virtualization/filtersets.py:218 vpn/filtersets.py:402 +#: netbox/circuits/filtersets.py:43 netbox/circuits/filtersets.py:223 +#: netbox/circuits/filtersets.py:307 netbox/dcim/base_filtersets.py:23 +#: netbox/dcim/filtersets.py:123 netbox/dcim/filtersets.py:182 +#: netbox/dcim/filtersets.py:243 netbox/dcim/filtersets.py:384 +#: netbox/dcim/filtersets.py:542 netbox/dcim/filtersets.py:1282 +#: netbox/dcim/filtersets.py:1644 netbox/dcim/filtersets.py:1751 +#: netbox/dcim/filtersets.py:2539 netbox/dcim/filtersets.py:2822 +#: netbox/dcim/filtersets.py:2883 netbox/ipam/filtersets.py:1005 +#: netbox/virtualization/filtersets.py:218 netbox/vpn/filtersets.py:402 msgid "Region (ID)" msgstr "" -#: circuits/filtersets.py:50 circuits/filtersets.py:230 -#: circuits/filtersets.py:314 dcim/base_filtersets.py:30 dcim/filtersets.py:130 -#: dcim/filtersets.py:188 dcim/filtersets.py:250 dcim/filtersets.py:391 -#: dcim/filtersets.py:549 dcim/filtersets.py:1289 dcim/filtersets.py:1651 -#: dcim/filtersets.py:1758 dcim/filtersets.py:2546 dcim/filtersets.py:2829 -#: dcim/filtersets.py:2890 extras/filtersets.py:716 ipam/filtersets.py:1012 -#: virtualization/filtersets.py:225 vpn/filtersets.py:397 +#: netbox/circuits/filtersets.py:50 netbox/circuits/filtersets.py:230 +#: netbox/circuits/filtersets.py:314 netbox/dcim/base_filtersets.py:30 +#: netbox/dcim/filtersets.py:130 netbox/dcim/filtersets.py:188 +#: netbox/dcim/filtersets.py:250 netbox/dcim/filtersets.py:391 +#: netbox/dcim/filtersets.py:549 netbox/dcim/filtersets.py:1289 +#: netbox/dcim/filtersets.py:1651 netbox/dcim/filtersets.py:1758 +#: netbox/dcim/filtersets.py:2546 netbox/dcim/filtersets.py:2829 +#: netbox/dcim/filtersets.py:2890 netbox/extras/filtersets.py:716 +#: netbox/ipam/filtersets.py:1012 netbox/virtualization/filtersets.py:225 +#: netbox/vpn/filtersets.py:397 msgid "Region (slug)" msgstr "" -#: circuits/filtersets.py:56 circuits/filtersets.py:236 -#: circuits/filtersets.py:320 dcim/base_filtersets.py:36 dcim/filtersets.py:156 -#: dcim/filtersets.py:256 dcim/filtersets.py:397 dcim/filtersets.py:555 -#: dcim/filtersets.py:1295 dcim/filtersets.py:1657 dcim/filtersets.py:1764 -#: dcim/filtersets.py:2552 dcim/filtersets.py:2835 dcim/filtersets.py:2896 -#: ipam/filtersets.py:261 ipam/filtersets.py:1018 -#: virtualization/filtersets.py:231 +#: netbox/circuits/filtersets.py:56 netbox/circuits/filtersets.py:236 +#: netbox/circuits/filtersets.py:320 netbox/dcim/base_filtersets.py:36 +#: netbox/dcim/filtersets.py:156 netbox/dcim/filtersets.py:256 +#: netbox/dcim/filtersets.py:397 netbox/dcim/filtersets.py:555 +#: netbox/dcim/filtersets.py:1295 netbox/dcim/filtersets.py:1657 +#: netbox/dcim/filtersets.py:1764 netbox/dcim/filtersets.py:2552 +#: netbox/dcim/filtersets.py:2835 netbox/dcim/filtersets.py:2896 +#: netbox/ipam/filtersets.py:261 netbox/ipam/filtersets.py:1018 +#: netbox/virtualization/filtersets.py:231 msgid "Site group (ID)" msgstr "" -#: circuits/filtersets.py:63 circuits/filtersets.py:243 -#: circuits/filtersets.py:327 dcim/base_filtersets.py:43 dcim/filtersets.py:163 -#: dcim/filtersets.py:263 dcim/filtersets.py:404 dcim/filtersets.py:562 -#: dcim/filtersets.py:1302 dcim/filtersets.py:1664 dcim/filtersets.py:1771 -#: dcim/filtersets.py:2559 dcim/filtersets.py:2842 dcim/filtersets.py:2903 -#: extras/filtersets.py:722 ipam/filtersets.py:268 ipam/filtersets.py:1025 -#: virtualization/filtersets.py:238 +#: netbox/circuits/filtersets.py:63 netbox/circuits/filtersets.py:243 +#: netbox/circuits/filtersets.py:327 netbox/dcim/base_filtersets.py:43 +#: netbox/dcim/filtersets.py:163 netbox/dcim/filtersets.py:263 +#: netbox/dcim/filtersets.py:404 netbox/dcim/filtersets.py:562 +#: netbox/dcim/filtersets.py:1302 netbox/dcim/filtersets.py:1664 +#: netbox/dcim/filtersets.py:1771 netbox/dcim/filtersets.py:2559 +#: netbox/dcim/filtersets.py:2842 netbox/dcim/filtersets.py:2903 +#: netbox/extras/filtersets.py:722 netbox/ipam/filtersets.py:268 +#: netbox/ipam/filtersets.py:1025 netbox/virtualization/filtersets.py:238 msgid "Site group (slug)" msgstr "" -#: circuits/filtersets.py:68 circuits/forms/filtersets.py:63 -#: circuits/forms/filtersets.py:191 circuits/forms/filtersets.py:249 -#: circuits/tables/circuits.py:125 dcim/forms/bulk_edit.py:176 -#: dcim/forms/bulk_edit.py:339 dcim/forms/bulk_edit.py:696 -#: dcim/forms/bulk_edit.py:906 dcim/forms/bulk_import.py:148 -#: dcim/forms/bulk_import.py:256 dcim/forms/bulk_import.py:365 -#: dcim/forms/bulk_import.py:656 dcim/forms/bulk_import.py:1700 -#: dcim/forms/bulk_import.py:1728 dcim/forms/filtersets.py:108 -#: dcim/forms/filtersets.py:258 dcim/forms/filtersets.py:390 -#: dcim/forms/filtersets.py:500 dcim/forms/filtersets.py:888 -#: dcim/forms/filtersets.py:1110 dcim/forms/filtersets.py:1191 -#: dcim/forms/filtersets.py:1228 dcim/forms/filtersets.py:1329 -#: dcim/forms/filtersets.py:1368 dcim/forms/filtersets.py:2105 -#: dcim/forms/filtersets.py:2129 dcim/forms/filtersets.py:2153 -#: dcim/forms/model_forms.py:168 dcim/forms/model_forms.py:211 -#: dcim/forms/model_forms.py:294 dcim/forms/model_forms.py:615 -#: dcim/forms/model_forms.py:900 dcim/forms/object_create.py:294 -#: dcim/tables/devices.py:157 dcim/tables/power.py:26 dcim/tables/power.py:90 -#: dcim/tables/racks.py:135 dcim/tables/racks.py:222 dcim/tables/sites.py:102 -#: extras/filtersets.py:732 ipam/forms/bulk_edit.py:419 -#: ipam/forms/bulk_import.py:515 ipam/forms/filtersets.py:176 -#: ipam/forms/filtersets.py:256 ipam/forms/filtersets.py:481 -#: ipam/forms/filtersets.py:588 ipam/forms/model_forms.py:693 -#: ipam/tables/vlans.py:94 templates/dcim/inc/cable_termination.html:8 -#: templates/dcim/inc/cable_termination.html:36 -#: templates/ipam/vlan_edit.html:52 virtualization/forms/bulk_edit.py:129 -#: virtualization/forms/bulk_import.py:62 -#: virtualization/forms/bulk_import.py:124 -#: virtualization/forms/filtersets.py:86 virtualization/forms/filtersets.py:210 -#: virtualization/forms/model_forms.py:102 -#: virtualization/forms/model_forms.py:204 -#: virtualization/tables/virtualmachines.py:73 vpn/forms/filtersets.py:288 -#: wireless/forms/filtersets.py:94 wireless/forms/model_forms.py:78 -#: wireless/forms/model_forms.py:120 +#: netbox/circuits/filtersets.py:68 netbox/circuits/forms/filtersets.py:63 +#: netbox/circuits/forms/filtersets.py:191 +#: netbox/circuits/forms/filtersets.py:249 +#: netbox/circuits/tables/circuits.py:125 netbox/dcim/forms/bulk_edit.py:176 +#: netbox/dcim/forms/bulk_edit.py:339 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:906 netbox/dcim/forms/bulk_import.py:148 +#: netbox/dcim/forms/bulk_import.py:256 netbox/dcim/forms/bulk_import.py:365 +#: netbox/dcim/forms/bulk_import.py:656 netbox/dcim/forms/bulk_import.py:1700 +#: netbox/dcim/forms/bulk_import.py:1728 netbox/dcim/forms/filtersets.py:108 +#: netbox/dcim/forms/filtersets.py:258 netbox/dcim/forms/filtersets.py:390 +#: netbox/dcim/forms/filtersets.py:500 netbox/dcim/forms/filtersets.py:888 +#: netbox/dcim/forms/filtersets.py:1110 netbox/dcim/forms/filtersets.py:1191 +#: netbox/dcim/forms/filtersets.py:1228 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/filtersets.py:1368 netbox/dcim/forms/filtersets.py:2105 +#: netbox/dcim/forms/filtersets.py:2129 netbox/dcim/forms/filtersets.py:2153 +#: netbox/dcim/forms/model_forms.py:168 netbox/dcim/forms/model_forms.py:211 +#: netbox/dcim/forms/model_forms.py:294 netbox/dcim/forms/model_forms.py:615 +#: netbox/dcim/forms/model_forms.py:900 netbox/dcim/forms/object_create.py:294 +#: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:26 +#: netbox/dcim/tables/power.py:90 netbox/dcim/tables/racks.py:135 +#: netbox/dcim/tables/racks.py:222 netbox/dcim/tables/sites.py:102 +#: netbox/extras/filtersets.py:732 netbox/ipam/forms/bulk_edit.py:419 +#: netbox/ipam/forms/bulk_import.py:515 netbox/ipam/forms/filtersets.py:176 +#: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/filtersets.py:481 +#: netbox/ipam/forms/filtersets.py:588 netbox/ipam/forms/model_forms.py:693 +#: netbox/ipam/tables/vlans.py:94 +#: netbox/templates/dcim/inc/cable_termination.html:8 +#: netbox/templates/dcim/inc/cable_termination.html:36 +#: netbox/templates/ipam/vlan_edit.html:52 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:62 +#: netbox/virtualization/forms/bulk_import.py:124 +#: netbox/virtualization/forms/filtersets.py:86 +#: netbox/virtualization/forms/filtersets.py:210 +#: netbox/virtualization/forms/model_forms.py:102 +#: netbox/virtualization/forms/model_forms.py:204 +#: netbox/virtualization/tables/virtualmachines.py:73 +#: netbox/vpn/forms/filtersets.py:288 netbox/wireless/forms/filtersets.py:94 +#: netbox/wireless/forms/model_forms.py:78 +#: netbox/wireless/forms/model_forms.py:120 msgid "Site" msgstr "" -#: circuits/filtersets.py:74 circuits/filtersets.py:254 -#: circuits/filtersets.py:340 dcim/base_filtersets.py:56 dcim/filtersets.py:275 -#: dcim/filtersets.py:416 dcim/filtersets.py:536 extras/filtersets.py:738 -#: ipam/filtersets.py:279 ipam/filtersets.py:1037 -#: virtualization/filtersets.py:250 vpn/filtersets.py:407 +#: netbox/circuits/filtersets.py:74 netbox/circuits/filtersets.py:254 +#: netbox/circuits/filtersets.py:340 netbox/dcim/base_filtersets.py:56 +#: netbox/dcim/filtersets.py:275 netbox/dcim/filtersets.py:416 +#: netbox/dcim/filtersets.py:536 netbox/extras/filtersets.py:738 +#: netbox/ipam/filtersets.py:279 netbox/ipam/filtersets.py:1037 +#: netbox/virtualization/filtersets.py:250 netbox/vpn/filtersets.py:407 msgid "Site (slug)" msgstr "" -#: circuits/filtersets.py:79 +#: netbox/circuits/filtersets.py:79 msgid "ASN (ID)" msgstr "" -#: circuits/filtersets.py:85 circuits/forms/filtersets.py:42 -#: ipam/forms/model_forms.py:169 ipam/models/asns.py:137 -#: ipam/models/asns.py:163 ipam/tables/asn.py:51 +#: netbox/circuits/filtersets.py:85 netbox/circuits/forms/filtersets.py:42 +#: netbox/ipam/forms/model_forms.py:169 netbox/ipam/models/asns.py:137 +#: netbox/ipam/models/asns.py:163 netbox/ipam/tables/asn.py:51 msgid "ASN" msgstr "" -#: circuits/filtersets.py:107 circuits/filtersets.py:137 -#: circuits/filtersets.py:175 circuits/filtersets.py:365 -#: circuits/filtersets.py:436 circuits/filtersets.py:517 -#: circuits/filtersets.py:596 ipam/filtersets.py:284 +#: netbox/circuits/filtersets.py:107 netbox/circuits/filtersets.py:137 +#: netbox/circuits/filtersets.py:175 netbox/circuits/filtersets.py:365 +#: netbox/circuits/filtersets.py:436 netbox/circuits/filtersets.py:517 +#: netbox/circuits/filtersets.py:596 netbox/ipam/filtersets.py:284 msgid "Provider (ID)" msgstr "" -#: circuits/filtersets.py:114 circuits/filtersets.py:144 -#: circuits/filtersets.py:182 circuits/filtersets.py:372 -#: circuits/filtersets.py:524 circuits/filtersets.py:603 ipam/filtersets.py:290 +#: netbox/circuits/filtersets.py:114 netbox/circuits/filtersets.py:144 +#: netbox/circuits/filtersets.py:182 netbox/circuits/filtersets.py:372 +#: netbox/circuits/filtersets.py:524 netbox/circuits/filtersets.py:603 +#: netbox/ipam/filtersets.py:290 msgid "Provider (slug)" msgstr "" -#: circuits/filtersets.py:188 circuits/filtersets.py:530 -#: circuits/filtersets.py:609 +#: netbox/circuits/filtersets.py:188 netbox/circuits/filtersets.py:530 +#: netbox/circuits/filtersets.py:609 msgid "Provider account (ID)" msgstr "" -#: circuits/filtersets.py:195 circuits/filtersets.py:537 -#: circuits/filtersets.py:616 +#: netbox/circuits/filtersets.py:195 netbox/circuits/filtersets.py:537 +#: netbox/circuits/filtersets.py:616 msgid "Provider account (account)" msgstr "" -#: circuits/filtersets.py:200 circuits/filtersets.py:542 -#: circuits/filtersets.py:622 +#: netbox/circuits/filtersets.py:200 netbox/circuits/filtersets.py:542 +#: netbox/circuits/filtersets.py:622 msgid "Provider network (ID)" msgstr "" -#: circuits/filtersets.py:205 +#: netbox/circuits/filtersets.py:205 msgid "Circuit type (ID)" msgstr "" -#: circuits/filtersets.py:212 +#: netbox/circuits/filtersets.py:212 msgid "Circuit type (slug)" msgstr "" -#: circuits/filtersets.py:248 circuits/filtersets.py:333 -#: dcim/base_filtersets.py:49 dcim/filtersets.py:268 dcim/filtersets.py:409 -#: dcim/filtersets.py:529 dcim/filtersets.py:1307 dcim/filtersets.py:1670 -#: dcim/filtersets.py:1777 dcim/filtersets.py:2565 dcim/filtersets.py:2847 -#: dcim/filtersets.py:2909 ipam/filtersets.py:273 ipam/filtersets.py:1030 -#: virtualization/filtersets.py:243 vpn/filtersets.py:412 +#: netbox/circuits/filtersets.py:248 netbox/circuits/filtersets.py:333 +#: netbox/dcim/base_filtersets.py:49 netbox/dcim/filtersets.py:268 +#: netbox/dcim/filtersets.py:409 netbox/dcim/filtersets.py:529 +#: netbox/dcim/filtersets.py:1307 netbox/dcim/filtersets.py:1670 +#: netbox/dcim/filtersets.py:1777 netbox/dcim/filtersets.py:2565 +#: netbox/dcim/filtersets.py:2847 netbox/dcim/filtersets.py:2909 +#: netbox/ipam/filtersets.py:273 netbox/ipam/filtersets.py:1030 +#: netbox/virtualization/filtersets.py:243 netbox/vpn/filtersets.py:412 msgid "Site (ID)" msgstr "" -#: circuits/filtersets.py:258 circuits/filtersets.py:346 -#: dcim/base_filtersets.py:62 dcim/filtersets.py:293 dcim/filtersets.py:422 -#: dcim/filtersets.py:568 dcim/filtersets.py:1320 dcim/filtersets.py:1683 -#: dcim/filtersets.py:1790 dcim/filtersets.py:2860 +#: netbox/circuits/filtersets.py:258 netbox/circuits/filtersets.py:346 +#: netbox/dcim/base_filtersets.py:62 netbox/dcim/filtersets.py:293 +#: netbox/dcim/filtersets.py:422 netbox/dcim/filtersets.py:568 +#: netbox/dcim/filtersets.py:1320 netbox/dcim/filtersets.py:1683 +#: netbox/dcim/filtersets.py:1790 netbox/dcim/filtersets.py:2860 msgid "Location (ID)" msgstr "" -#: circuits/filtersets.py:264 circuits/filtersets.py:269 +#: netbox/circuits/filtersets.py:264 netbox/circuits/filtersets.py:269 msgid "Termination A (ID)" msgstr "" -#: circuits/filtersets.py:295 circuits/filtersets.py:405 -#: circuits/filtersets.py:580 core/filtersets.py:91 core/filtersets.py:162 -#: core/filtersets.py:188 core/filtersets.py:231 dcim/filtersets.py:911 -#: dcim/filtersets.py:1745 dcim/filtersets.py:2961 extras/filtersets.py:47 -#: extras/filtersets.py:71 extras/filtersets.py:102 extras/filtersets.py:144 -#: extras/filtersets.py:198 extras/filtersets.py:252 extras/filtersets.py:283 -#: extras/filtersets.py:324 extras/filtersets.py:379 extras/filtersets.py:459 -#: extras/filtersets.py:503 extras/filtersets.py:560 extras/filtersets.py:621 -#: extras/filtersets.py:660 extras/filtersets.py:693 extras/filtersets.py:867 -#: ipam/forms/model_forms.py:514 netbox/filtersets.py:302 -#: netbox/forms/filtersets.py:32 netbox/forms/search.py:20 -#: templates/htmx/object_selector.html:28 templates/inc/filter_list.html:43 -#: templates/ipam/ipaddress_assign.html:29 templates/search.html:7 -#: templates/search.html:26 tenancy/filtersets.py:117 users/filtersets.py:26 -#: users/filtersets.py:72 users/filtersets.py:129 users/filtersets.py:193 -#: users/filtersets.py:260 users/filtersets.py:280 utilities/forms/forms.py:150 -#: utilities/templates/navigation/menu.html:16 +#: netbox/circuits/filtersets.py:295 netbox/circuits/filtersets.py:405 +#: netbox/circuits/filtersets.py:580 netbox/core/filtersets.py:91 +#: netbox/core/filtersets.py:162 netbox/core/filtersets.py:188 +#: netbox/core/filtersets.py:231 netbox/dcim/filtersets.py:911 +#: netbox/dcim/filtersets.py:1745 netbox/dcim/filtersets.py:2961 +#: netbox/extras/filtersets.py:47 netbox/extras/filtersets.py:71 +#: netbox/extras/filtersets.py:102 netbox/extras/filtersets.py:144 +#: netbox/extras/filtersets.py:198 netbox/extras/filtersets.py:252 +#: netbox/extras/filtersets.py:283 netbox/extras/filtersets.py:324 +#: netbox/extras/filtersets.py:379 netbox/extras/filtersets.py:459 +#: netbox/extras/filtersets.py:503 netbox/extras/filtersets.py:560 +#: netbox/extras/filtersets.py:621 netbox/extras/filtersets.py:660 +#: netbox/extras/filtersets.py:693 netbox/extras/filtersets.py:867 +#: netbox/ipam/forms/model_forms.py:514 netbox/netbox/filtersets.py:302 +#: netbox/netbox/forms/filtersets.py:32 netbox/netbox/forms/search.py:20 +#: netbox/templates/htmx/object_selector.html:28 +#: netbox/templates/inc/filter_list.html:43 +#: netbox/templates/ipam/ipaddress_assign.html:29 +#: netbox/templates/search.html:7 netbox/templates/search.html:26 +#: netbox/tenancy/filtersets.py:117 netbox/users/filtersets.py:26 +#: netbox/users/filtersets.py:72 netbox/users/filtersets.py:129 +#: netbox/users/filtersets.py:193 netbox/users/filtersets.py:260 +#: netbox/users/filtersets.py:280 netbox/utilities/forms/forms.py:150 +#: netbox/utilities/templates/navigation/menu.html:16 msgid "Search" msgstr "" -#: circuits/filtersets.py:300 circuits/forms/bulk_edit.py:172 -#: circuits/forms/bulk_edit.py:256 circuits/forms/bulk_import.py:128 -#: circuits/forms/filtersets.py:232 circuits/forms/filtersets.py:259 -#: circuits/forms/filtersets.py:306 circuits/forms/model_forms.py:168 -#: circuits/forms/model_forms.py:191 circuits/forms/model_forms.py:289 -#: circuits/tables/circuits.py:103 circuits/tables/circuits.py:200 -#: dcim/forms/connections.py:83 templates/dcim/inc/cable_termination.html:62 -#: templates/dcim/trace/circuit.html:4 +#: netbox/circuits/filtersets.py:300 netbox/circuits/forms/bulk_edit.py:172 +#: netbox/circuits/forms/bulk_edit.py:256 +#: netbox/circuits/forms/bulk_import.py:128 +#: netbox/circuits/forms/filtersets.py:232 +#: netbox/circuits/forms/filtersets.py:259 +#: netbox/circuits/forms/filtersets.py:306 +#: netbox/circuits/forms/model_forms.py:168 +#: netbox/circuits/forms/model_forms.py:191 +#: netbox/circuits/forms/model_forms.py:289 +#: netbox/circuits/tables/circuits.py:103 +#: netbox/circuits/tables/circuits.py:200 netbox/dcim/forms/connections.py:83 +#: netbox/templates/dcim/inc/cable_termination.html:62 +#: netbox/templates/dcim/trace/circuit.html:4 msgid "Circuit" msgstr "" -#: circuits/filtersets.py:353 dcim/base_filtersets.py:69 dcim/filtersets.py:300 -#: dcim/filtersets.py:429 dcim/filtersets.py:575 dcim/filtersets.py:1327 -#: dcim/filtersets.py:1690 dcim/filtersets.py:1797 extras/filtersets.py:749 +#: netbox/circuits/filtersets.py:353 netbox/dcim/base_filtersets.py:69 +#: netbox/dcim/filtersets.py:300 netbox/dcim/filtersets.py:429 +#: netbox/dcim/filtersets.py:575 netbox/dcim/filtersets.py:1327 +#: netbox/dcim/filtersets.py:1690 netbox/dcim/filtersets.py:1797 +#: netbox/extras/filtersets.py:749 msgid "Location (slug)" msgstr "" -#: circuits/filtersets.py:359 +#: netbox/circuits/filtersets.py:359 msgid "ProviderNetwork (ID)" msgstr "" -#: circuits/filtersets.py:411 +#: netbox/circuits/filtersets.py:411 msgid "Circuit (CID)" msgstr "" -#: circuits/filtersets.py:416 +#: netbox/circuits/filtersets.py:416 msgid "Circuit (ID)" msgstr "" -#: circuits/filtersets.py:421 +#: netbox/circuits/filtersets.py:421 msgid "Virtual circuit (CID)" msgstr "" -#: circuits/filtersets.py:426 dcim/filtersets.py:2321 +#: netbox/circuits/filtersets.py:426 netbox/dcim/filtersets.py:2321 msgid "Virtual circuit (ID)" msgstr "" -#: circuits/filtersets.py:431 +#: netbox/circuits/filtersets.py:431 msgid "Provider (name)" msgstr "" -#: circuits/filtersets.py:441 +#: netbox/circuits/filtersets.py:441 msgid "Circuit group (ID)" msgstr "" -#: circuits/filtersets.py:448 +#: netbox/circuits/filtersets.py:448 msgid "Circuit group (slug)" msgstr "" -#: circuits/filtersets.py:547 +#: netbox/circuits/filtersets.py:547 msgid "Virtual circuit type (ID)" msgstr "" -#: circuits/filtersets.py:554 +#: netbox/circuits/filtersets.py:554 msgid "Virtual circuit type (slug)" msgstr "" -#: circuits/filtersets.py:585 circuits/forms/bulk_edit.py:316 -#: circuits/forms/bulk_import.py:248 circuits/forms/filtersets.py:384 -#: circuits/forms/filtersets.py:390 circuits/forms/model_forms.py:367 -#: circuits/forms/model_forms.py:382 circuits/tables/virtual_circuits.py:84 +#: netbox/circuits/filtersets.py:585 netbox/circuits/forms/bulk_edit.py:316 +#: netbox/circuits/forms/bulk_import.py:248 +#: netbox/circuits/forms/filtersets.py:384 +#: netbox/circuits/forms/filtersets.py:390 +#: netbox/circuits/forms/model_forms.py:367 +#: netbox/circuits/forms/model_forms.py:382 +#: netbox/circuits/tables/virtual_circuits.py:84 msgid "Virtual circuit" msgstr "" -#: circuits/filtersets.py:628 dcim/filtersets.py:1557 dcim/filtersets.py:2046 -#: ipam/filtersets.py:680 vpn/filtersets.py:117 vpn/filtersets.py:445 +#: netbox/circuits/filtersets.py:628 netbox/dcim/filtersets.py:1557 +#: netbox/dcim/filtersets.py:2046 netbox/ipam/filtersets.py:680 +#: netbox/vpn/filtersets.py:117 netbox/vpn/filtersets.py:445 msgid "Interface (ID)" msgstr "" -#: circuits/forms/bulk_edit.py:48 circuits/forms/filtersets.py:68 -#: circuits/forms/model_forms.py:48 circuits/tables/providers.py:32 -#: circuits/ui/panels.py:108 dcim/forms/bulk_edit.py:142 -#: dcim/forms/filtersets.py:227 dcim/forms/model_forms.py:144 -#: dcim/tables/sites.py:74 ipam/models/asns.py:164 ipam/tables/asn.py:37 -#: ipam/tables/ip.py:126 ipam/views.py:382 netbox/navigation/menu.py:189 -#: netbox/navigation/menu.py:192 +#: netbox/circuits/forms/bulk_edit.py:48 netbox/circuits/forms/filtersets.py:68 +#: netbox/circuits/forms/model_forms.py:48 +#: netbox/circuits/tables/providers.py:32 netbox/circuits/ui/panels.py:108 +#: netbox/dcim/forms/bulk_edit.py:142 netbox/dcim/forms/filtersets.py:227 +#: netbox/dcim/forms/model_forms.py:144 netbox/dcim/tables/sites.py:74 +#: netbox/ipam/models/asns.py:164 netbox/ipam/tables/asn.py:37 +#: netbox/ipam/tables/ip.py:126 netbox/ipam/views.py:382 +#: netbox/netbox/navigation/menu.py:189 netbox/netbox/navigation/menu.py:192 msgid "ASNs" msgstr "" -#: circuits/forms/bulk_edit.py:63 circuits/forms/bulk_edit.py:79 -#: circuits/forms/bulk_edit.py:118 circuits/forms/bulk_import.py:43 -#: circuits/forms/bulk_import.py:58 circuits/forms/bulk_import.py:81 -#: circuits/forms/filtersets.py:84 circuits/forms/filtersets.py:103 -#: circuits/forms/filtersets.py:132 circuits/forms/filtersets.py:151 -#: circuits/forms/filtersets.py:233 circuits/forms/filtersets.py:277 -#: circuits/forms/filtersets.py:301 circuits/forms/filtersets.py:340 -#: circuits/forms/filtersets.py:349 circuits/forms/filtersets.py:385 -#: circuits/forms/filtersets.py:408 circuits/forms/model_forms.py:90 -#: circuits/forms/model_forms.py:109 circuits/forms/model_forms.py:140 -#: circuits/tables/circuits.py:56 circuits/tables/circuits.py:107 -#: circuits/tables/circuits.py:192 circuits/tables/providers.py:67 -#: circuits/tables/providers.py:95 circuits/tables/virtual_circuits.py:46 -#: circuits/tables/virtual_circuits.py:89 -#: templates/dcim/inc/cable_termination.html:58 -#: templates/dcim/panels/interface_virtual_circuit.html:7 +#: netbox/circuits/forms/bulk_edit.py:63 netbox/circuits/forms/bulk_edit.py:79 +#: netbox/circuits/forms/bulk_edit.py:118 +#: netbox/circuits/forms/bulk_import.py:43 +#: netbox/circuits/forms/bulk_import.py:58 +#: netbox/circuits/forms/bulk_import.py:81 +#: netbox/circuits/forms/filtersets.py:84 +#: netbox/circuits/forms/filtersets.py:103 +#: netbox/circuits/forms/filtersets.py:132 +#: netbox/circuits/forms/filtersets.py:151 +#: netbox/circuits/forms/filtersets.py:233 +#: netbox/circuits/forms/filtersets.py:277 +#: netbox/circuits/forms/filtersets.py:301 +#: netbox/circuits/forms/filtersets.py:340 +#: netbox/circuits/forms/filtersets.py:349 +#: netbox/circuits/forms/filtersets.py:385 +#: netbox/circuits/forms/filtersets.py:408 +#: netbox/circuits/forms/model_forms.py:90 +#: netbox/circuits/forms/model_forms.py:109 +#: netbox/circuits/forms/model_forms.py:140 +#: netbox/circuits/tables/circuits.py:56 netbox/circuits/tables/circuits.py:107 +#: netbox/circuits/tables/circuits.py:192 +#: netbox/circuits/tables/providers.py:67 +#: netbox/circuits/tables/providers.py:95 +#: netbox/circuits/tables/virtual_circuits.py:46 +#: netbox/circuits/tables/virtual_circuits.py:89 +#: netbox/templates/dcim/inc/cable_termination.html:58 +#: netbox/templates/dcim/panels/interface_virtual_circuit.html:7 msgid "Provider" msgstr "" -#: circuits/forms/bulk_edit.py:86 circuits/forms/filtersets.py:106 -#: circuits/ui/panels.py:122 +#: netbox/circuits/forms/bulk_edit.py:86 +#: netbox/circuits/forms/filtersets.py:106 netbox/circuits/ui/panels.py:122 msgid "Service ID" msgstr "" -#: circuits/forms/bulk_edit.py:100 circuits/forms/bulk_edit.py:275 -#: circuits/forms/filtersets.py:123 circuits/forms/filtersets.py:331 -#: dcim/forms/bulk_edit.py:222 dcim/forms/bulk_edit.py:628 -#: dcim/forms/bulk_edit.py:849 dcim/forms/bulk_edit.py:1103 -#: dcim/forms/bulk_edit.py:1202 dcim/forms/bulk_edit.py:1229 -#: dcim/forms/bulk_edit.py:1773 dcim/forms/bulk_import.py:1541 -#: dcim/forms/filtersets.py:1276 dcim/forms/filtersets.py:1606 -#: dcim/forms/filtersets.py:1822 dcim/forms/filtersets.py:1841 -#: dcim/forms/filtersets.py:1865 dcim/forms/filtersets.py:1884 -#: dcim/tables/devices.py:806 dcim/tables/devices.py:859 -#: dcim/tables/devices.py:1132 dcim/tables/devicetypes.py:214 -#: dcim/tables/devicetypes.py:255 dcim/tables/devicetypes.py:274 -#: dcim/tables/racks.py:54 extras/forms/bulk_edit.py:313 -#: extras/tables/tables.py:558 netbox/ui/attrs.py:232 -#: templates/extras/panels/customfieldchoiceset_choices.html:11 +#: netbox/circuits/forms/bulk_edit.py:100 +#: netbox/circuits/forms/bulk_edit.py:275 +#: netbox/circuits/forms/filtersets.py:123 +#: netbox/circuits/forms/filtersets.py:331 netbox/dcim/forms/bulk_edit.py:222 +#: netbox/dcim/forms/bulk_edit.py:628 netbox/dcim/forms/bulk_edit.py:849 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1202 +#: netbox/dcim/forms/bulk_edit.py:1229 netbox/dcim/forms/bulk_edit.py:1773 +#: netbox/dcim/forms/bulk_import.py:1541 netbox/dcim/forms/filtersets.py:1276 +#: netbox/dcim/forms/filtersets.py:1606 netbox/dcim/forms/filtersets.py:1822 +#: netbox/dcim/forms/filtersets.py:1841 netbox/dcim/forms/filtersets.py:1865 +#: netbox/dcim/forms/filtersets.py:1884 netbox/dcim/tables/devices.py:806 +#: netbox/dcim/tables/devices.py:859 netbox/dcim/tables/devices.py:1132 +#: netbox/dcim/tables/devicetypes.py:214 netbox/dcim/tables/devicetypes.py:255 +#: netbox/dcim/tables/devicetypes.py:274 netbox/dcim/tables/racks.py:54 +#: netbox/extras/forms/bulk_edit.py:313 netbox/extras/tables/tables.py:558 +#: netbox/netbox/ui/attrs.py:232 +#: netbox/templates/extras/panels/customfieldchoiceset_choices.html:11 msgid "Color" msgstr "" -#: circuits/forms/bulk_edit.py:113 circuits/forms/bulk_edit.py:298 -#: circuits/forms/bulk_import.py:94 circuits/forms/bulk_import.py:220 -#: circuits/forms/filtersets.py:146 circuits/forms/filtersets.py:370 -#: circuits/tables/circuits.py:64 circuits/tables/circuits.py:197 -#: circuits/tables/virtual_circuits.py:58 core/forms/bulk_edit.py:18 -#: core/forms/filtersets.py:37 core/tables/change_logging.py:33 -#: core/tables/data.py:22 core/tables/jobs.py:22 dcim/forms/bulk_edit.py:816 -#: dcim/forms/bulk_edit.py:948 dcim/forms/bulk_edit.py:1014 -#: dcim/forms/bulk_edit.py:1033 dcim/forms/bulk_edit.py:1056 -#: dcim/forms/bulk_edit.py:1098 dcim/forms/bulk_edit.py:1146 -#: dcim/forms/bulk_edit.py:1197 dcim/forms/bulk_edit.py:1224 -#: dcim/forms/bulk_import.py:214 dcim/forms/bulk_import.py:300 -#: dcim/forms/bulk_import.py:829 dcim/forms/bulk_import.py:855 -#: dcim/forms/bulk_import.py:881 dcim/forms/bulk_import.py:902 -#: dcim/forms/bulk_import.py:988 dcim/forms/bulk_import.py:1117 -#: dcim/forms/bulk_import.py:1136 dcim/forms/bulk_import.py:1515 -#: dcim/forms/bulk_import.py:1765 dcim/forms/filtersets.py:1148 -#: dcim/forms/filtersets.py:1261 dcim/forms/filtersets.py:1394 -#: dcim/forms/filtersets.py:1485 dcim/forms/filtersets.py:1505 -#: dcim/forms/filtersets.py:1525 dcim/forms/filtersets.py:1545 -#: dcim/forms/filtersets.py:1565 dcim/forms/filtersets.py:1580 -#: dcim/forms/filtersets.py:1600 dcim/forms/filtersets.py:1624 -#: dcim/forms/filtersets.py:1663 dcim/forms/filtersets.py:1768 -#: dcim/forms/filtersets.py:1817 dcim/forms/filtersets.py:1836 -#: dcim/forms/filtersets.py:1860 dcim/forms/filtersets.py:1879 -#: dcim/forms/model_forms.py:876 dcim/forms/model_forms.py:882 -#: dcim/forms/object_import.py:85 dcim/forms/object_import.py:114 -#: dcim/forms/object_import.py:127 dcim/tables/devices.py:182 -#: dcim/tables/power.py:74 dcim/tables/racks.py:155 -#: extras/forms/bulk_import.py:48 extras/tables/tables.py:515 -#: extras/tables/tables.py:584 extras/ui/panels.py:128 extras/ui/panels.py:377 -#: netbox/tables/tables.py:358 templates/core/htmx/system_db_schema.html:70 -#: templates/dcim/panels/interface_connection.html:68 -#: templates/wireless/panels/wirelesslink_interface.html:16 -#: virtualization/forms/bulk_edit.py:54 virtualization/forms/bulk_import.py:44 -#: virtualization/forms/filtersets.py:66 virtualization/forms/model_forms.py:64 -#: virtualization/forms/model_forms.py:198 virtualization/tables/clusters.py:67 -#: virtualization/tables/virtualmachines.py:63 virtualization/ui/panels.py:40 -#: vpn/forms/bulk_edit.py:226 vpn/forms/bulk_import.py:268 -#: vpn/forms/filtersets.py:239 vpn/forms/model_forms.py:82 -#: vpn/forms/model_forms.py:117 vpn/forms/model_forms.py:229 -#: wireless/ui/panels.py:23 +#: netbox/circuits/forms/bulk_edit.py:113 +#: netbox/circuits/forms/bulk_edit.py:298 +#: netbox/circuits/forms/bulk_import.py:94 +#: netbox/circuits/forms/bulk_import.py:220 +#: netbox/circuits/forms/filtersets.py:146 +#: netbox/circuits/forms/filtersets.py:370 +#: netbox/circuits/tables/circuits.py:64 netbox/circuits/tables/circuits.py:197 +#: netbox/circuits/tables/virtual_circuits.py:58 +#: netbox/core/forms/bulk_edit.py:18 netbox/core/forms/filtersets.py:37 +#: netbox/core/tables/change_logging.py:33 netbox/core/tables/data.py:22 +#: netbox/core/tables/jobs.py:22 netbox/dcim/forms/bulk_edit.py:816 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_edit.py:1014 +#: netbox/dcim/forms/bulk_edit.py:1033 netbox/dcim/forms/bulk_edit.py:1056 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_edit.py:1146 +#: netbox/dcim/forms/bulk_edit.py:1197 netbox/dcim/forms/bulk_edit.py:1224 +#: netbox/dcim/forms/bulk_import.py:214 netbox/dcim/forms/bulk_import.py:300 +#: netbox/dcim/forms/bulk_import.py:829 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:881 netbox/dcim/forms/bulk_import.py:902 +#: netbox/dcim/forms/bulk_import.py:988 netbox/dcim/forms/bulk_import.py:1117 +#: netbox/dcim/forms/bulk_import.py:1136 netbox/dcim/forms/bulk_import.py:1515 +#: netbox/dcim/forms/bulk_import.py:1765 netbox/dcim/forms/filtersets.py:1148 +#: netbox/dcim/forms/filtersets.py:1261 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/filtersets.py:1485 netbox/dcim/forms/filtersets.py:1505 +#: netbox/dcim/forms/filtersets.py:1525 netbox/dcim/forms/filtersets.py:1545 +#: netbox/dcim/forms/filtersets.py:1565 netbox/dcim/forms/filtersets.py:1580 +#: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 +#: netbox/dcim/forms/filtersets.py:1663 netbox/dcim/forms/filtersets.py:1768 +#: netbox/dcim/forms/filtersets.py:1817 netbox/dcim/forms/filtersets.py:1836 +#: netbox/dcim/forms/filtersets.py:1860 netbox/dcim/forms/filtersets.py:1879 +#: netbox/dcim/forms/model_forms.py:876 netbox/dcim/forms/model_forms.py:882 +#: netbox/dcim/forms/object_import.py:85 netbox/dcim/forms/object_import.py:114 +#: netbox/dcim/forms/object_import.py:127 netbox/dcim/tables/devices.py:182 +#: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:155 +#: netbox/extras/forms/bulk_import.py:48 netbox/extras/tables/tables.py:515 +#: netbox/extras/tables/tables.py:584 netbox/extras/ui/panels.py:128 +#: netbox/extras/ui/panels.py:377 netbox/netbox/tables/tables.py:358 +#: netbox/templates/core/htmx/system_db_schema.html:70 +#: netbox/templates/dcim/panels/interface_connection.html:68 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:16 +#: netbox/virtualization/forms/bulk_edit.py:54 +#: netbox/virtualization/forms/bulk_import.py:44 +#: netbox/virtualization/forms/filtersets.py:66 +#: netbox/virtualization/forms/model_forms.py:64 +#: netbox/virtualization/forms/model_forms.py:198 +#: netbox/virtualization/tables/clusters.py:67 +#: netbox/virtualization/tables/virtualmachines.py:63 +#: netbox/virtualization/ui/panels.py:40 netbox/vpn/forms/bulk_edit.py:226 +#: netbox/vpn/forms/bulk_import.py:268 netbox/vpn/forms/filtersets.py:239 +#: netbox/vpn/forms/model_forms.py:82 netbox/vpn/forms/model_forms.py:117 +#: netbox/vpn/forms/model_forms.py:229 netbox/wireless/ui/panels.py:23 msgid "Type" msgstr "" -#: circuits/forms/bulk_edit.py:123 circuits/forms/bulk_edit.py:293 -#: circuits/forms/bulk_import.py:87 circuits/forms/bulk_import.py:213 -#: circuits/forms/filtersets.py:159 circuits/forms/filtersets.py:357 -#: circuits/forms/model_forms.py:146 circuits/forms/model_forms.py:355 +#: netbox/circuits/forms/bulk_edit.py:123 +#: netbox/circuits/forms/bulk_edit.py:293 +#: netbox/circuits/forms/bulk_import.py:87 +#: netbox/circuits/forms/bulk_import.py:213 +#: netbox/circuits/forms/filtersets.py:159 +#: netbox/circuits/forms/filtersets.py:357 +#: netbox/circuits/forms/model_forms.py:146 +#: netbox/circuits/forms/model_forms.py:355 msgid "Provider account" msgstr "" -#: circuits/forms/bulk_edit.py:131 circuits/forms/bulk_edit.py:303 -#: circuits/forms/bulk_import.py:100 circuits/forms/bulk_import.py:226 -#: circuits/forms/filtersets.py:170 circuits/forms/filtersets.py:373 -#: core/forms/filtersets.py:42 core/forms/filtersets.py:90 -#: core/tables/data.py:25 core/tables/jobs.py:30 core/tables/tasks.py:90 -#: dcim/forms/bulk_edit.py:115 dcim/forms/bulk_edit.py:189 -#: dcim/forms/bulk_edit.py:366 dcim/forms/bulk_edit.py:475 -#: dcim/forms/bulk_edit.py:719 dcim/forms/bulk_edit.py:778 -#: dcim/forms/bulk_edit.py:822 dcim/forms/bulk_edit.py:942 -#: dcim/forms/bulk_edit.py:1747 dcim/forms/bulk_edit.py:1791 -#: dcim/forms/bulk_import.py:105 dcim/forms/bulk_import.py:164 -#: dcim/forms/bulk_import.py:281 dcim/forms/bulk_import.py:390 -#: dcim/forms/bulk_import.py:621 dcim/forms/bulk_import.py:781 -#: dcim/forms/bulk_import.py:1258 dcim/forms/bulk_import.py:1503 -#: dcim/forms/bulk_import.py:1760 dcim/forms/bulk_import.py:1823 -#: dcim/forms/filtersets.py:210 dcim/forms/filtersets.py:270 -#: dcim/forms/filtersets.py:413 dcim/forms/filtersets.py:528 -#: dcim/forms/filtersets.py:934 dcim/forms/filtersets.py:1057 -#: dcim/forms/filtersets.py:1151 dcim/forms/filtersets.py:1266 -#: dcim/forms/filtersets.py:1389 dcim/forms/filtersets.py:1610 -#: dcim/forms/filtersets.py:2006 dcim/tables/devices.py:144 -#: dcim/tables/devices.py:543 dcim/tables/devices.py:915 -#: dcim/tables/devices.py:1080 dcim/tables/devices.py:1188 -#: dcim/tables/modules.py:106 dcim/tables/power.py:71 dcim/tables/racks.py:143 -#: dcim/tables/racks.py:248 dcim/tables/sites.py:62 dcim/tables/sites.py:106 -#: ipam/forms/bulk_edit.py:209 ipam/forms/bulk_edit.py:253 -#: ipam/forms/bulk_edit.py:300 ipam/forms/bulk_edit.py:441 -#: ipam/forms/bulk_import.py:205 ipam/forms/bulk_import.py:269 -#: ipam/forms/bulk_import.py:305 ipam/forms/bulk_import.py:536 -#: ipam/forms/filtersets.py:239 ipam/forms/filtersets.py:318 -#: ipam/forms/filtersets.py:401 ipam/forms/filtersets.py:600 -#: ipam/forms/model_forms.py:533 ipam/tables/ip.py:187 ipam/tables/ip.py:266 -#: ipam/tables/ip.py:319 ipam/tables/ip.py:394 ipam/tables/ip.py:421 -#: ipam/tables/vlans.py:102 templates/core/rq_task.html:81 -#: templates/core/system.html:20 -#: templates/extras/inc/script_list_content.html:35 -#: users/forms/filtersets.py:36 users/forms/model_forms.py:224 -#: virtualization/forms/bulk_edit.py:64 virtualization/forms/bulk_edit.py:117 -#: virtualization/forms/bulk_import.py:57 -#: virtualization/forms/bulk_import.py:113 -#: virtualization/forms/filtersets.py:94 virtualization/forms/filtersets.py:222 -#: virtualization/tables/clusters.py:75 -#: virtualization/tables/virtualmachines.py:67 vpn/forms/bulk_edit.py:33 -#: vpn/forms/bulk_edit.py:222 vpn/forms/bulk_import.py:36 -#: vpn/forms/bulk_import.py:263 vpn/forms/filtersets.py:57 -#: vpn/forms/filtersets.py:234 vpn/tables/l2vpn.py:27 vpn/tables/tunnels.py:49 -#: wireless/forms/bulk_edit.py:40 wireless/forms/bulk_edit.py:97 -#: wireless/forms/bulk_import.py:44 wireless/forms/bulk_import.py:131 -#: wireless/forms/filtersets.py:58 wireless/forms/filtersets.py:118 -#: wireless/tables/wirelesslan.py:45 wireless/tables/wirelesslink.py:19 +#: netbox/circuits/forms/bulk_edit.py:131 +#: netbox/circuits/forms/bulk_edit.py:303 +#: netbox/circuits/forms/bulk_import.py:100 +#: netbox/circuits/forms/bulk_import.py:226 +#: netbox/circuits/forms/filtersets.py:170 +#: netbox/circuits/forms/filtersets.py:373 netbox/core/forms/filtersets.py:42 +#: netbox/core/forms/filtersets.py:90 netbox/core/tables/data.py:25 +#: netbox/core/tables/jobs.py:30 netbox/core/tables/tasks.py:90 +#: netbox/dcim/forms/bulk_edit.py:115 netbox/dcim/forms/bulk_edit.py:189 +#: netbox/dcim/forms/bulk_edit.py:366 netbox/dcim/forms/bulk_edit.py:475 +#: netbox/dcim/forms/bulk_edit.py:719 netbox/dcim/forms/bulk_edit.py:778 +#: netbox/dcim/forms/bulk_edit.py:822 netbox/dcim/forms/bulk_edit.py:942 +#: netbox/dcim/forms/bulk_edit.py:1747 netbox/dcim/forms/bulk_edit.py:1791 +#: netbox/dcim/forms/bulk_import.py:105 netbox/dcim/forms/bulk_import.py:164 +#: netbox/dcim/forms/bulk_import.py:281 netbox/dcim/forms/bulk_import.py:390 +#: netbox/dcim/forms/bulk_import.py:621 netbox/dcim/forms/bulk_import.py:781 +#: netbox/dcim/forms/bulk_import.py:1258 netbox/dcim/forms/bulk_import.py:1503 +#: netbox/dcim/forms/bulk_import.py:1760 netbox/dcim/forms/bulk_import.py:1823 +#: netbox/dcim/forms/filtersets.py:210 netbox/dcim/forms/filtersets.py:270 +#: netbox/dcim/forms/filtersets.py:413 netbox/dcim/forms/filtersets.py:528 +#: netbox/dcim/forms/filtersets.py:934 netbox/dcim/forms/filtersets.py:1057 +#: netbox/dcim/forms/filtersets.py:1151 netbox/dcim/forms/filtersets.py:1266 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/filtersets.py:1610 +#: netbox/dcim/forms/filtersets.py:2006 netbox/dcim/tables/devices.py:144 +#: netbox/dcim/tables/devices.py:543 netbox/dcim/tables/devices.py:915 +#: netbox/dcim/tables/devices.py:1080 netbox/dcim/tables/devices.py:1188 +#: netbox/dcim/tables/modules.py:106 netbox/dcim/tables/power.py:71 +#: netbox/dcim/tables/racks.py:143 netbox/dcim/tables/racks.py:248 +#: netbox/dcim/tables/sites.py:62 netbox/dcim/tables/sites.py:106 +#: netbox/ipam/forms/bulk_edit.py:209 netbox/ipam/forms/bulk_edit.py:253 +#: netbox/ipam/forms/bulk_edit.py:300 netbox/ipam/forms/bulk_edit.py:441 +#: netbox/ipam/forms/bulk_import.py:205 netbox/ipam/forms/bulk_import.py:269 +#: netbox/ipam/forms/bulk_import.py:305 netbox/ipam/forms/bulk_import.py:536 +#: netbox/ipam/forms/filtersets.py:239 netbox/ipam/forms/filtersets.py:318 +#: netbox/ipam/forms/filtersets.py:401 netbox/ipam/forms/filtersets.py:600 +#: netbox/ipam/forms/model_forms.py:533 netbox/ipam/tables/ip.py:187 +#: netbox/ipam/tables/ip.py:266 netbox/ipam/tables/ip.py:319 +#: netbox/ipam/tables/ip.py:394 netbox/ipam/tables/ip.py:421 +#: netbox/ipam/tables/vlans.py:102 netbox/templates/core/rq_task.html:81 +#: netbox/templates/core/system.html:20 +#: netbox/templates/extras/inc/script_list_content.html:35 +#: netbox/users/forms/filtersets.py:36 netbox/users/forms/model_forms.py:215 +#: netbox/virtualization/forms/bulk_edit.py:64 +#: netbox/virtualization/forms/bulk_edit.py:117 +#: netbox/virtualization/forms/bulk_import.py:57 +#: netbox/virtualization/forms/bulk_import.py:113 +#: netbox/virtualization/forms/filtersets.py:94 +#: netbox/virtualization/forms/filtersets.py:222 +#: netbox/virtualization/tables/clusters.py:75 +#: netbox/virtualization/tables/virtualmachines.py:67 +#: netbox/vpn/forms/bulk_edit.py:33 netbox/vpn/forms/bulk_edit.py:222 +#: netbox/vpn/forms/bulk_import.py:36 netbox/vpn/forms/bulk_import.py:263 +#: netbox/vpn/forms/filtersets.py:57 netbox/vpn/forms/filtersets.py:234 +#: netbox/vpn/tables/l2vpn.py:27 netbox/vpn/tables/tunnels.py:49 +#: netbox/wireless/forms/bulk_edit.py:40 netbox/wireless/forms/bulk_edit.py:97 +#: netbox/wireless/forms/bulk_import.py:44 +#: netbox/wireless/forms/bulk_import.py:131 +#: netbox/wireless/forms/filtersets.py:58 +#: netbox/wireless/forms/filtersets.py:118 +#: netbox/wireless/tables/wirelesslan.py:45 +#: netbox/wireless/tables/wirelesslink.py:19 msgid "Status" msgstr "" -#: circuits/forms/bulk_edit.py:137 circuits/forms/bulk_edit.py:243 -#: circuits/forms/bulk_edit.py:309 circuits/forms/bulk_import.py:111 -#: circuits/forms/bulk_import.py:170 circuits/forms/bulk_import.py:231 -#: circuits/forms/filtersets.py:138 circuits/forms/filtersets.py:286 -#: circuits/forms/filtersets.py:342 dcim/forms/bulk_edit.py:131 -#: dcim/forms/bulk_edit.py:195 dcim/forms/bulk_edit.py:361 -#: dcim/forms/bulk_edit.py:486 dcim/forms/bulk_edit.py:709 -#: dcim/forms/bulk_edit.py:834 dcim/forms/bulk_edit.py:1796 -#: dcim/forms/bulk_import.py:124 dcim/forms/bulk_import.py:169 -#: dcim/forms/bulk_import.py:267 dcim/forms/bulk_import.py:395 -#: dcim/forms/bulk_import.py:595 dcim/forms/bulk_import.py:1521 -#: dcim/forms/bulk_import.py:1816 dcim/forms/filtersets.py:145 -#: dcim/forms/filtersets.py:204 dcim/forms/filtersets.py:237 -#: dcim/forms/filtersets.py:374 dcim/forms/filtersets.py:459 -#: dcim/forms/filtersets.py:480 dcim/forms/filtersets.py:856 -#: dcim/forms/filtersets.py:1048 dcim/forms/filtersets.py:1171 -#: dcim/forms/filtersets.py:1214 dcim/forms/filtersets.py:1349 -#: dcim/tables/power.py:85 extras/filtersets.py:819 -#: extras/forms/filtersets.py:412 extras/forms/filtersets.py:491 -#: ipam/forms/bulk_edit.py:49 ipam/forms/bulk_edit.py:68 -#: ipam/forms/bulk_edit.py:101 ipam/forms/bulk_edit.py:130 -#: ipam/forms/bulk_edit.py:149 ipam/forms/bulk_edit.py:204 -#: ipam/forms/bulk_edit.py:248 ipam/forms/bulk_edit.py:295 -#: ipam/forms/bulk_edit.py:379 ipam/forms/bulk_edit.py:436 -#: ipam/forms/bulk_import.py:45 ipam/forms/bulk_import.py:74 -#: ipam/forms/bulk_import.py:102 ipam/forms/bulk_import.py:122 -#: ipam/forms/bulk_import.py:149 ipam/forms/bulk_import.py:177 -#: ipam/forms/bulk_import.py:262 ipam/forms/bulk_import.py:298 -#: ipam/forms/bulk_import.py:495 ipam/forms/bulk_import.py:529 -#: ipam/forms/filtersets.py:50 ipam/forms/filtersets.py:71 -#: ipam/forms/filtersets.py:109 ipam/forms/filtersets.py:131 -#: ipam/forms/filtersets.py:155 ipam/forms/filtersets.py:201 -#: ipam/forms/filtersets.py:302 ipam/forms/filtersets.py:355 -#: ipam/forms/filtersets.py:464 ipam/forms/filtersets.py:567 -#: ipam/tables/ip.py:424 tenancy/forms/filtersets.py:55 -#: tenancy/forms/forms.py:26 tenancy/forms/forms.py:50 -#: tenancy/forms/model_forms.py:51 tenancy/tables/columns.py:50 -#: virtualization/forms/bulk_edit.py:70 virtualization/forms/bulk_edit.py:161 -#: virtualization/forms/bulk_import.py:69 -#: virtualization/forms/bulk_import.py:154 -#: virtualization/forms/filtersets.py:58 virtualization/forms/filtersets.py:160 -#: vpn/forms/bulk_edit.py:53 vpn/forms/bulk_edit.py:231 -#: vpn/forms/bulk_import.py:58 vpn/forms/bulk_import.py:257 -#: vpn/forms/filtersets.py:229 wireless/forms/bulk_edit.py:60 -#: wireless/forms/bulk_edit.py:102 wireless/forms/bulk_import.py:56 -#: wireless/forms/bulk_import.py:136 wireless/forms/filtersets.py:44 -#: wireless/forms/filtersets.py:110 +#: netbox/circuits/forms/bulk_edit.py:137 +#: netbox/circuits/forms/bulk_edit.py:243 +#: netbox/circuits/forms/bulk_edit.py:309 +#: netbox/circuits/forms/bulk_import.py:111 +#: netbox/circuits/forms/bulk_import.py:170 +#: netbox/circuits/forms/bulk_import.py:231 +#: netbox/circuits/forms/filtersets.py:138 +#: netbox/circuits/forms/filtersets.py:286 +#: netbox/circuits/forms/filtersets.py:342 netbox/dcim/forms/bulk_edit.py:131 +#: netbox/dcim/forms/bulk_edit.py:195 netbox/dcim/forms/bulk_edit.py:361 +#: netbox/dcim/forms/bulk_edit.py:486 netbox/dcim/forms/bulk_edit.py:709 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:1796 +#: netbox/dcim/forms/bulk_import.py:124 netbox/dcim/forms/bulk_import.py:169 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:395 +#: netbox/dcim/forms/bulk_import.py:595 netbox/dcim/forms/bulk_import.py:1521 +#: netbox/dcim/forms/bulk_import.py:1816 netbox/dcim/forms/filtersets.py:145 +#: netbox/dcim/forms/filtersets.py:204 netbox/dcim/forms/filtersets.py:237 +#: netbox/dcim/forms/filtersets.py:374 netbox/dcim/forms/filtersets.py:459 +#: netbox/dcim/forms/filtersets.py:480 netbox/dcim/forms/filtersets.py:856 +#: netbox/dcim/forms/filtersets.py:1048 netbox/dcim/forms/filtersets.py:1171 +#: netbox/dcim/forms/filtersets.py:1214 netbox/dcim/forms/filtersets.py:1349 +#: netbox/dcim/tables/power.py:85 netbox/extras/filtersets.py:819 +#: netbox/extras/forms/filtersets.py:412 netbox/extras/forms/filtersets.py:491 +#: netbox/ipam/forms/bulk_edit.py:49 netbox/ipam/forms/bulk_edit.py:68 +#: netbox/ipam/forms/bulk_edit.py:101 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/ipam/forms/bulk_edit.py:149 netbox/ipam/forms/bulk_edit.py:204 +#: netbox/ipam/forms/bulk_edit.py:248 netbox/ipam/forms/bulk_edit.py:295 +#: netbox/ipam/forms/bulk_edit.py:379 netbox/ipam/forms/bulk_edit.py:436 +#: netbox/ipam/forms/bulk_import.py:45 netbox/ipam/forms/bulk_import.py:74 +#: netbox/ipam/forms/bulk_import.py:102 netbox/ipam/forms/bulk_import.py:122 +#: netbox/ipam/forms/bulk_import.py:149 netbox/ipam/forms/bulk_import.py:177 +#: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:529 +#: netbox/ipam/forms/filtersets.py:50 netbox/ipam/forms/filtersets.py:71 +#: netbox/ipam/forms/filtersets.py:109 netbox/ipam/forms/filtersets.py:131 +#: netbox/ipam/forms/filtersets.py:155 netbox/ipam/forms/filtersets.py:201 +#: netbox/ipam/forms/filtersets.py:302 netbox/ipam/forms/filtersets.py:355 +#: netbox/ipam/forms/filtersets.py:464 netbox/ipam/forms/filtersets.py:567 +#: netbox/ipam/tables/ip.py:424 netbox/tenancy/forms/filtersets.py:55 +#: netbox/tenancy/forms/forms.py:26 netbox/tenancy/forms/forms.py:50 +#: netbox/tenancy/forms/model_forms.py:51 netbox/tenancy/tables/columns.py:50 +#: netbox/virtualization/forms/bulk_edit.py:70 +#: netbox/virtualization/forms/bulk_edit.py:161 +#: netbox/virtualization/forms/bulk_import.py:69 +#: netbox/virtualization/forms/bulk_import.py:154 +#: netbox/virtualization/forms/filtersets.py:58 +#: netbox/virtualization/forms/filtersets.py:160 +#: netbox/vpn/forms/bulk_edit.py:53 netbox/vpn/forms/bulk_edit.py:231 +#: netbox/vpn/forms/bulk_import.py:58 netbox/vpn/forms/bulk_import.py:257 +#: netbox/vpn/forms/filtersets.py:229 netbox/wireless/forms/bulk_edit.py:60 +#: netbox/wireless/forms/bulk_edit.py:102 +#: netbox/wireless/forms/bulk_import.py:56 +#: netbox/wireless/forms/bulk_import.py:136 +#: netbox/wireless/forms/filtersets.py:44 +#: netbox/wireless/forms/filtersets.py:110 msgid "Tenant" msgstr "" -#: circuits/forms/bulk_edit.py:142 circuits/forms/filtersets.py:199 +#: netbox/circuits/forms/bulk_edit.py:142 +#: netbox/circuits/forms/filtersets.py:199 msgid "Install date" msgstr "" -#: circuits/forms/bulk_edit.py:147 circuits/forms/filtersets.py:204 +#: netbox/circuits/forms/bulk_edit.py:147 +#: netbox/circuits/forms/filtersets.py:204 msgid "Termination date" msgstr "" -#: circuits/forms/bulk_edit.py:153 circuits/forms/filtersets.py:211 +#: netbox/circuits/forms/bulk_edit.py:153 +#: netbox/circuits/forms/filtersets.py:211 msgid "Commit rate (Kbps)" msgstr "" -#: circuits/forms/bulk_edit.py:159 circuits/forms/filtersets.py:217 -#: circuits/forms/model_forms.py:165 wireless/forms/bulk_edit.py:121 -#: wireless/forms/filtersets.py:137 wireless/forms/model_forms.py:166 +#: netbox/circuits/forms/bulk_edit.py:159 +#: netbox/circuits/forms/filtersets.py:217 +#: netbox/circuits/forms/model_forms.py:165 +#: netbox/wireless/forms/bulk_edit.py:121 +#: netbox/wireless/forms/filtersets.py:137 +#: netbox/wireless/forms/model_forms.py:166 msgid "Distance" msgstr "" -#: circuits/forms/bulk_edit.py:164 circuits/forms/bulk_import.py:105 -#: circuits/forms/bulk_import.py:108 circuits/forms/filtersets.py:221 -#: wireless/forms/bulk_edit.py:126 wireless/forms/bulk_import.py:155 -#: wireless/forms/bulk_import.py:158 wireless/forms/filtersets.py:141 +#: netbox/circuits/forms/bulk_edit.py:164 +#: netbox/circuits/forms/bulk_import.py:105 +#: netbox/circuits/forms/bulk_import.py:108 +#: netbox/circuits/forms/filtersets.py:221 +#: netbox/wireless/forms/bulk_edit.py:126 +#: netbox/wireless/forms/bulk_import.py:155 +#: netbox/wireless/forms/bulk_import.py:158 +#: netbox/wireless/forms/filtersets.py:141 msgid "Distance unit" msgstr "" -#: circuits/forms/bulk_edit.py:173 circuits/forms/model_forms.py:170 +#: netbox/circuits/forms/bulk_edit.py:173 +#: netbox/circuits/forms/model_forms.py:170 msgid "Service Parameters" msgstr "" -#: circuits/forms/bulk_edit.py:174 circuits/forms/filtersets.py:77 -#: circuits/forms/filtersets.py:97 circuits/forms/filtersets.py:117 -#: circuits/forms/filtersets.py:135 circuits/forms/filtersets.py:325 -#: circuits/forms/filtersets.py:341 core/forms/filtersets.py:78 -#: core/forms/filtersets.py:150 dcim/forms/bulk_edit.py:867 -#: dcim/forms/bulk_import.py:504 dcim/forms/filtersets.py:203 -#: dcim/forms/filtersets.py:236 dcim/forms/filtersets.py:1047 -#: dcim/forms/filtersets.py:1200 dcim/forms/filtersets.py:1212 -#: dcim/forms/filtersets.py:1348 dcim/forms/filtersets.py:1475 -#: dcim/forms/filtersets.py:1501 dcim/forms/filtersets.py:1515 -#: dcim/forms/filtersets.py:1541 dcim/forms/filtersets.py:1555 -#: dcim/forms/filtersets.py:1576 dcim/forms/filtersets.py:1590 -#: dcim/forms/filtersets.py:1620 dcim/forms/filtersets.py:1634 -#: dcim/forms/filtersets.py:1762 dcim/forms/filtersets.py:1806 -#: dcim/forms/filtersets.py:1832 dcim/forms/filtersets.py:1850 -#: dcim/forms/filtersets.py:1875 dcim/forms/filtersets.py:1893 -#: dcim/forms/filtersets.py:1917 dcim/forms/filtersets.py:1935 -#: dcim/forms/filtersets.py:1955 dcim/forms/filtersets.py:1971 -#: dcim/forms/filtersets.py:2017 dcim/forms/filtersets.py:2053 -#: dcim/tables/modules.py:25 dcim/views.py:1774 extras/forms/bulk_edit.py:98 -#: extras/forms/filtersets.py:48 extras/forms/filtersets.py:152 -#: extras/forms/filtersets.py:231 extras/forms/filtersets.py:248 -#: extras/forms/filtersets.py:280 extras/forms/filtersets.py:311 -#: extras/forms/filtersets.py:334 extras/forms/filtersets.py:366 -#: extras/forms/filtersets.py:572 ipam/forms/filtersets.py:108 -#: ipam/forms/filtersets.py:301 ipam/forms/filtersets.py:351 -#: ipam/forms/filtersets.py:428 ipam/forms/filtersets.py:526 -#: ipam/forms/filtersets.py:540 ipam/forms/filtersets.py:565 -#: ipam/forms/filtersets.py:637 ipam/forms/filtersets.py:656 -#: netbox/tables/tables.py:374 virtualization/forms/filtersets.py:56 -#: virtualization/forms/filtersets.py:114 -#: virtualization/forms/filtersets.py:158 -#: virtualization/forms/filtersets.py:265 -#: virtualization/forms/filtersets.py:323 vpn/forms/filtersets.py:228 -#: wireless/forms/bulk_edit.py:136 wireless/forms/filtersets.py:41 -#: wireless/forms/filtersets.py:108 +#: netbox/circuits/forms/bulk_edit.py:174 +#: netbox/circuits/forms/filtersets.py:77 +#: netbox/circuits/forms/filtersets.py:97 +#: netbox/circuits/forms/filtersets.py:117 +#: netbox/circuits/forms/filtersets.py:135 +#: netbox/circuits/forms/filtersets.py:325 +#: netbox/circuits/forms/filtersets.py:341 netbox/core/forms/filtersets.py:78 +#: netbox/core/forms/filtersets.py:150 netbox/dcim/forms/bulk_edit.py:867 +#: netbox/dcim/forms/bulk_import.py:504 netbox/dcim/forms/filtersets.py:203 +#: netbox/dcim/forms/filtersets.py:236 netbox/dcim/forms/filtersets.py:1047 +#: netbox/dcim/forms/filtersets.py:1200 netbox/dcim/forms/filtersets.py:1212 +#: netbox/dcim/forms/filtersets.py:1348 netbox/dcim/forms/filtersets.py:1475 +#: netbox/dcim/forms/filtersets.py:1501 netbox/dcim/forms/filtersets.py:1515 +#: netbox/dcim/forms/filtersets.py:1541 netbox/dcim/forms/filtersets.py:1555 +#: netbox/dcim/forms/filtersets.py:1576 netbox/dcim/forms/filtersets.py:1590 +#: netbox/dcim/forms/filtersets.py:1620 netbox/dcim/forms/filtersets.py:1634 +#: netbox/dcim/forms/filtersets.py:1762 netbox/dcim/forms/filtersets.py:1806 +#: netbox/dcim/forms/filtersets.py:1832 netbox/dcim/forms/filtersets.py:1850 +#: netbox/dcim/forms/filtersets.py:1875 netbox/dcim/forms/filtersets.py:1893 +#: netbox/dcim/forms/filtersets.py:1917 netbox/dcim/forms/filtersets.py:1935 +#: netbox/dcim/forms/filtersets.py:1955 netbox/dcim/forms/filtersets.py:1971 +#: netbox/dcim/forms/filtersets.py:2017 netbox/dcim/forms/filtersets.py:2053 +#: netbox/dcim/tables/modules.py:25 netbox/dcim/views.py:1774 +#: netbox/extras/forms/bulk_edit.py:98 netbox/extras/forms/filtersets.py:48 +#: netbox/extras/forms/filtersets.py:152 netbox/extras/forms/filtersets.py:231 +#: netbox/extras/forms/filtersets.py:248 netbox/extras/forms/filtersets.py:280 +#: netbox/extras/forms/filtersets.py:311 netbox/extras/forms/filtersets.py:334 +#: netbox/extras/forms/filtersets.py:366 netbox/extras/forms/filtersets.py:572 +#: netbox/ipam/forms/filtersets.py:108 netbox/ipam/forms/filtersets.py:301 +#: netbox/ipam/forms/filtersets.py:351 netbox/ipam/forms/filtersets.py:428 +#: netbox/ipam/forms/filtersets.py:526 netbox/ipam/forms/filtersets.py:540 +#: netbox/ipam/forms/filtersets.py:565 netbox/ipam/forms/filtersets.py:637 +#: netbox/ipam/forms/filtersets.py:656 netbox/netbox/tables/tables.py:374 +#: netbox/virtualization/forms/filtersets.py:56 +#: netbox/virtualization/forms/filtersets.py:114 +#: netbox/virtualization/forms/filtersets.py:158 +#: netbox/virtualization/forms/filtersets.py:265 +#: netbox/virtualization/forms/filtersets.py:323 +#: netbox/vpn/forms/filtersets.py:228 netbox/wireless/forms/bulk_edit.py:136 +#: netbox/wireless/forms/filtersets.py:41 +#: netbox/wireless/forms/filtersets.py:108 msgid "Attributes" msgstr "" -#: circuits/forms/bulk_edit.py:175 circuits/forms/bulk_edit.py:317 -#: circuits/forms/model_forms.py:171 circuits/forms/model_forms.py:267 -#: circuits/forms/model_forms.py:369 dcim/forms/model_forms.py:170 -#: dcim/forms/model_forms.py:226 dcim/forms/model_forms.py:330 -#: dcim/forms/model_forms.py:387 dcim/forms/model_forms.py:944 -#: dcim/forms/model_forms.py:1960 ipam/forms/bulk_edit.py:388 -#: ipam/forms/model_forms.py:71 ipam/forms/model_forms.py:88 -#: ipam/forms/model_forms.py:119 ipam/forms/model_forms.py:140 -#: ipam/forms/model_forms.py:170 ipam/forms/model_forms.py:234 -#: ipam/forms/model_forms.py:266 ipam/forms/model_forms.py:288 -#: ipam/forms/model_forms.py:346 ipam/forms/model_forms.py:495 -#: ipam/forms/model_forms.py:644 netbox/navigation/menu.py:27 -#: templates/dcim/device_edit.html:87 templates/dcim/htmx/cable_edit.html:76 -#: templates/ipam/vlan_edit.html:34 virtualization/forms/model_forms.py:78 -#: virtualization/forms/model_forms.py:266 vpn/forms/bulk_edit.py:66 -#: vpn/forms/filtersets.py:52 vpn/forms/model_forms.py:60 -#: vpn/forms/model_forms.py:145 vpn/forms/model_forms.py:409 -#: wireless/forms/model_forms.py:56 wireless/forms/model_forms.py:171 +#: netbox/circuits/forms/bulk_edit.py:175 +#: netbox/circuits/forms/bulk_edit.py:317 +#: netbox/circuits/forms/model_forms.py:171 +#: netbox/circuits/forms/model_forms.py:267 +#: netbox/circuits/forms/model_forms.py:369 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:226 +#: netbox/dcim/forms/model_forms.py:330 netbox/dcim/forms/model_forms.py:387 +#: netbox/dcim/forms/model_forms.py:944 netbox/dcim/forms/model_forms.py:1960 +#: netbox/ipam/forms/bulk_edit.py:388 netbox/ipam/forms/model_forms.py:71 +#: netbox/ipam/forms/model_forms.py:88 netbox/ipam/forms/model_forms.py:119 +#: netbox/ipam/forms/model_forms.py:140 netbox/ipam/forms/model_forms.py:170 +#: netbox/ipam/forms/model_forms.py:234 netbox/ipam/forms/model_forms.py:266 +#: netbox/ipam/forms/model_forms.py:288 netbox/ipam/forms/model_forms.py:346 +#: netbox/ipam/forms/model_forms.py:495 netbox/ipam/forms/model_forms.py:644 +#: netbox/netbox/navigation/menu.py:27 +#: netbox/templates/dcim/device_edit.html:87 +#: netbox/templates/dcim/htmx/cable_edit.html:76 +#: netbox/templates/ipam/vlan_edit.html:34 +#: netbox/virtualization/forms/model_forms.py:78 +#: netbox/virtualization/forms/model_forms.py:266 +#: netbox/vpn/forms/bulk_edit.py:66 netbox/vpn/forms/filtersets.py:52 +#: netbox/vpn/forms/model_forms.py:60 netbox/vpn/forms/model_forms.py:145 +#: netbox/vpn/forms/model_forms.py:409 netbox/wireless/forms/model_forms.py:56 +#: netbox/wireless/forms/model_forms.py:171 msgid "Tenancy" msgstr "" -#: circuits/forms/bulk_edit.py:184 circuits/forms/bulk_edit.py:332 -#: dcim/forms/bulk_create.py:37 dcim/forms/bulk_edit.py:802 -#: dcim/forms/bulk_edit.py:1038 dcim/forms/bulk_edit.py:1073 -#: dcim/forms/bulk_edit.py:1117 dcim/forms/bulk_edit.py:1161 -#: dcim/forms/bulk_edit.py:1206 dcim/forms/bulk_edit.py:1233 -#: dcim/forms/bulk_edit.py:1251 dcim/forms/bulk_edit.py:1274 -#: dcim/forms/bulk_edit.py:1297 extras/forms/bulk_edit.py:43 -#: extras/forms/bulk_edit.py:160 extras/forms/bulk_edit.py:193 -#: extras/forms/bulk_edit.py:221 extras/forms/bulk_edit.py:251 -#: extras/forms/bulk_edit.py:299 extras/forms/bulk_edit.py:317 -#: extras/forms/bulk_edit.py:362 extras/forms/bulk_edit.py:379 -#: extras/forms/bulk_edit.py:421 extras/forms/bulk_edit.py:446 -#: extras/tables/tables.py:97 ipam/tables/vlans.py:218 ipam/tables/vlans.py:245 -#: netbox/forms/bulk_edit.py:79 netbox/forms/bulk_edit.py:91 -#: netbox/forms/bulk_edit.py:103 netbox/ui/panels.py:219 -#: netbox/ui/panels.py:228 -#: templates/circuits/inc/circuit_termination_fields.html:85 -#: templates/core/plugin.html:80 templates/dcim/cablebundle.html:21 -#: templates/extras/dashboard/widget_add.html:14 -#: templates/extras/inc/script_list_content.html:33 -#: templates/generic/bulk_import.html:151 users/forms/bulk_edit.py:62 -#: users/forms/bulk_edit.py:80 users/forms/bulk_edit.py:115 -#: users/forms/bulk_edit.py:143 users/forms/bulk_edit.py:166 -#: virtualization/forms/bulk_edit.py:237 virtualization/forms/bulk_edit.py:362 +#: netbox/circuits/forms/bulk_edit.py:184 +#: netbox/circuits/forms/bulk_edit.py:332 netbox/dcim/forms/bulk_create.py:37 +#: netbox/dcim/forms/bulk_edit.py:802 netbox/dcim/forms/bulk_edit.py:1038 +#: netbox/dcim/forms/bulk_edit.py:1073 netbox/dcim/forms/bulk_edit.py:1117 +#: netbox/dcim/forms/bulk_edit.py:1161 netbox/dcim/forms/bulk_edit.py:1206 +#: netbox/dcim/forms/bulk_edit.py:1233 netbox/dcim/forms/bulk_edit.py:1251 +#: netbox/dcim/forms/bulk_edit.py:1274 netbox/dcim/forms/bulk_edit.py:1297 +#: netbox/extras/forms/bulk_edit.py:43 netbox/extras/forms/bulk_edit.py:160 +#: netbox/extras/forms/bulk_edit.py:193 netbox/extras/forms/bulk_edit.py:221 +#: netbox/extras/forms/bulk_edit.py:251 netbox/extras/forms/bulk_edit.py:299 +#: netbox/extras/forms/bulk_edit.py:317 netbox/extras/forms/bulk_edit.py:362 +#: netbox/extras/forms/bulk_edit.py:379 netbox/extras/forms/bulk_edit.py:421 +#: netbox/extras/forms/bulk_edit.py:446 netbox/extras/tables/tables.py:97 +#: netbox/ipam/tables/vlans.py:218 netbox/ipam/tables/vlans.py:245 +#: netbox/netbox/forms/bulk_edit.py:79 netbox/netbox/forms/bulk_edit.py:91 +#: netbox/netbox/forms/bulk_edit.py:103 netbox/netbox/ui/panels.py:219 +#: netbox/netbox/ui/panels.py:228 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:85 +#: netbox/templates/core/plugin.html:80 +#: netbox/templates/dcim/cablebundle.html:21 +#: netbox/templates/extras/dashboard/widget_add.html:14 +#: netbox/templates/extras/inc/script_list_content.html:33 +#: netbox/templates/generic/bulk_import.html:151 +#: netbox/users/forms/bulk_edit.py:62 netbox/users/forms/bulk_edit.py:80 +#: netbox/users/forms/bulk_edit.py:115 netbox/users/forms/bulk_edit.py:143 +#: netbox/users/forms/bulk_edit.py:166 +#: netbox/virtualization/forms/bulk_edit.py:241 +#: netbox/virtualization/forms/bulk_edit.py:366 msgid "Description" msgstr "" -#: circuits/forms/bulk_edit.py:192 circuits/forms/model_forms.py:199 -#: dcim/forms/bulk_import.py:1461 dcim/forms/bulk_import.py:1494 +#: netbox/circuits/forms/bulk_edit.py:192 +#: netbox/circuits/forms/model_forms.py:199 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/bulk_import.py:1494 msgid "Termination type" msgstr "" -#: circuits/forms/bulk_edit.py:195 circuits/forms/bulk_import.py:133 -#: circuits/forms/filtersets.py:234 circuits/forms/model_forms.py:202 -#: circuits/ui/panels.py:14 templates/circuits/inc/circuit_termination.html:6 -#: templates/circuits/panels/circuit_circuit_termination.html:6 -#: vpn/forms/bulk_import.py:99 vpn/forms/filtersets.py:87 +#: netbox/circuits/forms/bulk_edit.py:195 +#: netbox/circuits/forms/bulk_import.py:133 +#: netbox/circuits/forms/filtersets.py:234 +#: netbox/circuits/forms/model_forms.py:202 netbox/circuits/ui/panels.py:14 +#: netbox/templates/circuits/inc/circuit_termination.html:6 +#: netbox/templates/circuits/panels/circuit_circuit_termination.html:6 +#: netbox/vpn/forms/bulk_import.py:99 netbox/vpn/forms/filtersets.py:87 msgid "Termination" msgstr "" -#: circuits/forms/bulk_edit.py:203 +#: netbox/circuits/forms/bulk_edit.py:203 msgid "Port speed (Kbps)" msgstr "" -#: circuits/forms/bulk_edit.py:207 +#: netbox/circuits/forms/bulk_edit.py:207 msgid "Upstream speed (Kbps)" msgstr "" -#: circuits/forms/bulk_edit.py:210 dcim/forms/bulk_edit.py:978 -#: dcim/forms/bulk_edit.py:1354 dcim/forms/bulk_edit.py:1371 -#: dcim/forms/bulk_edit.py:1388 dcim/forms/bulk_edit.py:1409 -#: dcim/forms/bulk_edit.py:1504 dcim/forms/bulk_edit.py:1676 -#: dcim/forms/bulk_edit.py:1693 +#: netbox/circuits/forms/bulk_edit.py:210 netbox/dcim/forms/bulk_edit.py:978 +#: netbox/dcim/forms/bulk_edit.py:1354 netbox/dcim/forms/bulk_edit.py:1371 +#: netbox/dcim/forms/bulk_edit.py:1388 netbox/dcim/forms/bulk_edit.py:1409 +#: netbox/dcim/forms/bulk_edit.py:1504 netbox/dcim/forms/bulk_edit.py:1676 +#: netbox/dcim/forms/bulk_edit.py:1693 msgid "Mark connected" msgstr "" -#: circuits/forms/bulk_edit.py:220 circuits/forms/model_forms.py:213 -#: circuits/ui/panels.py:58 dcim/views.py:3564 dcim/views.py:3665 -#: templates/circuits/circuit_termination/attrs/connection.html:43 -#: templates/circuits/inc/circuit_termination_fields.html:55 -#: templates/dcim/panels/interface_connection.html:92 +#: netbox/circuits/forms/bulk_edit.py:220 +#: netbox/circuits/forms/model_forms.py:213 netbox/circuits/ui/panels.py:58 +#: netbox/dcim/views.py:3564 netbox/dcim/views.py:3665 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:43 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:55 +#: netbox/templates/dcim/panels/interface_connection.html:92 msgid "Circuit Termination" msgstr "" -#: circuits/forms/bulk_edit.py:222 circuits/forms/model_forms.py:215 +#: netbox/circuits/forms/bulk_edit.py:222 +#: netbox/circuits/forms/model_forms.py:215 msgid "Termination Details" msgstr "" -#: circuits/forms/bulk_edit.py:261 circuits/forms/bulk_import.py:188 -#: circuits/forms/filtersets.py:314 circuits/tables/circuits.py:205 -#: dcim/forms/model_forms.py:711 -#: templates/dcim/panels/virtual_chassis_members.html:11 -#: templates/dcim/virtualchassis_edit.html:68 -#: templates/ipam/inc/panels/fhrp_groups.html:26 -#: templates/ipam/panels/fhrp_groups.html:12 tenancy/forms/bulk_edit.py:141 -#: tenancy/forms/filtersets.py:139 +#: netbox/circuits/forms/bulk_edit.py:261 +#: netbox/circuits/forms/bulk_import.py:188 +#: netbox/circuits/forms/filtersets.py:314 +#: netbox/circuits/tables/circuits.py:205 netbox/dcim/forms/model_forms.py:711 +#: netbox/templates/dcim/panels/virtual_chassis_members.html:11 +#: netbox/templates/dcim/virtualchassis_edit.html:68 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:26 +#: netbox/templates/ipam/panels/fhrp_groups.html:12 +#: netbox/tenancy/forms/bulk_edit.py:141 netbox/tenancy/forms/filtersets.py:139 msgid "Priority" msgstr "" -#: circuits/forms/bulk_edit.py:288 circuits/forms/bulk_import.py:207 -#: circuits/forms/filtersets.py:167 circuits/forms/filtersets.py:272 -#: circuits/forms/filtersets.py:365 circuits/forms/filtersets.py:403 -#: circuits/forms/model_forms.py:350 circuits/tables/virtual_circuits.py:51 -#: circuits/tables/virtual_circuits.py:95 +#: netbox/circuits/forms/bulk_edit.py:288 +#: netbox/circuits/forms/bulk_import.py:207 +#: netbox/circuits/forms/filtersets.py:167 +#: netbox/circuits/forms/filtersets.py:272 +#: netbox/circuits/forms/filtersets.py:365 +#: netbox/circuits/forms/filtersets.py:403 +#: netbox/circuits/forms/model_forms.py:350 +#: netbox/circuits/tables/virtual_circuits.py:51 +#: netbox/circuits/tables/virtual_circuits.py:95 msgid "Provider network" msgstr "" -#: circuits/forms/bulk_edit.py:326 circuits/forms/bulk_import.py:253 -#: circuits/forms/filtersets.py:393 circuits/forms/model_forms.py:389 -#: dcim/forms/bulk_edit.py:372 dcim/forms/bulk_edit.py:1301 -#: dcim/forms/bulk_edit.py:1737 dcim/forms/bulk_import.py:286 -#: dcim/forms/bulk_import.py:1227 dcim/forms/filtersets.py:421 -#: dcim/forms/filtersets.py:912 dcim/forms/filtersets.py:1983 -#: dcim/forms/filtersets.py:2023 dcim/forms/model_forms.py:312 -#: dcim/forms/model_forms.py:1297 dcim/forms/model_forms.py:1780 -#: dcim/forms/object_import.py:198 dcim/tables/devices.py:173 -#: dcim/tables/devices.py:1064 dcim/tables/devicetypes.py:324 -#: dcim/tables/racks.py:146 extras/filtersets.py:759 -#: ipam/forms/bulk_edit.py:127 ipam/forms/bulk_edit.py:214 -#: ipam/forms/bulk_edit.py:258 ipam/forms/bulk_edit.py:305 -#: ipam/forms/bulk_edit.py:446 ipam/forms/bulk_import.py:142 -#: ipam/forms/bulk_import.py:210 ipam/forms/bulk_import.py:274 -#: ipam/forms/bulk_import.py:310 ipam/forms/bulk_import.py:541 -#: ipam/forms/filtersets.py:166 ipam/forms/filtersets.py:267 -#: ipam/forms/filtersets.py:326 ipam/forms/filtersets.py:406 -#: ipam/forms/filtersets.py:608 ipam/forms/model_forms.py:158 -#: ipam/forms/model_forms.py:196 ipam/forms/model_forms.py:222 -#: ipam/forms/model_forms.py:277 ipam/forms/model_forms.py:708 -#: ipam/tables/asn.py:75 ipam/tables/ip.py:213 ipam/tables/ip.py:270 -#: ipam/tables/ip.py:323 ipam/tables/vlans.py:106 -#: templates/dcim/inc/panels/inventory_items.html:20 -#: templates/dcim/panels/component_inventory_items.html:10 -#: templates/dcim/panels/interface_virtual_circuit.html:19 -#: templates/dcim/panels/interface_wireless.html:17 -#: templates/wireless/panels/wirelesslink_interface.html:20 -#: tenancy/forms/bulk_edit.py:136 tenancy/forms/filtersets.py:136 -#: tenancy/forms/model_forms.py:137 tenancy/tables/contacts.py:96 -#: virtualization/forms/bulk_edit.py:151 -#: virtualization/forms/bulk_import.py:145 -#: virtualization/forms/filtersets.py:219 -#: virtualization/forms/model_forms.py:237 -#: virtualization/tables/virtualmachines.py:85 vpn/forms/bulk_edit.py:75 -#: vpn/forms/bulk_import.py:80 vpn/forms/filtersets.py:95 -#: vpn/forms/model_forms.py:76 vpn/forms/model_forms.py:111 -#: vpn/tables/tunnels.py:81 +#: netbox/circuits/forms/bulk_edit.py:326 +#: netbox/circuits/forms/bulk_import.py:253 +#: netbox/circuits/forms/filtersets.py:393 +#: netbox/circuits/forms/model_forms.py:389 netbox/dcim/forms/bulk_edit.py:372 +#: netbox/dcim/forms/bulk_edit.py:1301 netbox/dcim/forms/bulk_edit.py:1737 +#: netbox/dcim/forms/bulk_import.py:286 netbox/dcim/forms/bulk_import.py:1227 +#: netbox/dcim/forms/filtersets.py:421 netbox/dcim/forms/filtersets.py:912 +#: netbox/dcim/forms/filtersets.py:1983 netbox/dcim/forms/filtersets.py:2023 +#: netbox/dcim/forms/model_forms.py:312 netbox/dcim/forms/model_forms.py:1297 +#: netbox/dcim/forms/model_forms.py:1780 netbox/dcim/forms/object_import.py:198 +#: netbox/dcim/tables/devices.py:173 netbox/dcim/tables/devices.py:1064 +#: netbox/dcim/tables/devicetypes.py:324 netbox/dcim/tables/racks.py:146 +#: netbox/extras/filtersets.py:759 netbox/ipam/forms/bulk_edit.py:127 +#: netbox/ipam/forms/bulk_edit.py:214 netbox/ipam/forms/bulk_edit.py:258 +#: netbox/ipam/forms/bulk_edit.py:305 netbox/ipam/forms/bulk_edit.py:446 +#: netbox/ipam/forms/bulk_import.py:142 netbox/ipam/forms/bulk_import.py:210 +#: netbox/ipam/forms/bulk_import.py:274 netbox/ipam/forms/bulk_import.py:310 +#: netbox/ipam/forms/bulk_import.py:541 netbox/ipam/forms/filtersets.py:166 +#: netbox/ipam/forms/filtersets.py:267 netbox/ipam/forms/filtersets.py:326 +#: netbox/ipam/forms/filtersets.py:406 netbox/ipam/forms/filtersets.py:608 +#: netbox/ipam/forms/model_forms.py:158 netbox/ipam/forms/model_forms.py:196 +#: netbox/ipam/forms/model_forms.py:222 netbox/ipam/forms/model_forms.py:277 +#: netbox/ipam/forms/model_forms.py:708 netbox/ipam/tables/asn.py:75 +#: netbox/ipam/tables/ip.py:213 netbox/ipam/tables/ip.py:270 +#: netbox/ipam/tables/ip.py:323 netbox/ipam/tables/vlans.py:106 +#: netbox/templates/dcim/inc/panels/inventory_items.html:20 +#: netbox/templates/dcim/panels/component_inventory_items.html:10 +#: netbox/templates/dcim/panels/interface_virtual_circuit.html:19 +#: netbox/templates/dcim/panels/interface_wireless.html:17 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:20 +#: netbox/tenancy/forms/bulk_edit.py:136 netbox/tenancy/forms/filtersets.py:136 +#: netbox/tenancy/forms/model_forms.py:137 netbox/tenancy/tables/contacts.py:96 +#: netbox/virtualization/forms/bulk_edit.py:151 +#: netbox/virtualization/forms/bulk_import.py:145 +#: netbox/virtualization/forms/filtersets.py:219 +#: netbox/virtualization/forms/model_forms.py:237 +#: netbox/virtualization/tables/virtualmachines.py:85 +#: netbox/vpn/forms/bulk_edit.py:75 netbox/vpn/forms/bulk_import.py:80 +#: netbox/vpn/forms/filtersets.py:95 netbox/vpn/forms/model_forms.py:76 +#: netbox/vpn/forms/model_forms.py:111 netbox/vpn/tables/tunnels.py:81 msgid "Role" msgstr "" -#: circuits/forms/bulk_import.py:46 circuits/forms/bulk_import.py:61 -#: circuits/forms/bulk_import.py:84 +#: netbox/circuits/forms/bulk_import.py:46 +#: netbox/circuits/forms/bulk_import.py:61 +#: netbox/circuits/forms/bulk_import.py:84 msgid "Assigned provider" msgstr "" -#: circuits/forms/bulk_import.py:90 +#: netbox/circuits/forms/bulk_import.py:90 msgid "Assigned provider account" msgstr "" -#: circuits/forms/bulk_import.py:97 +#: netbox/circuits/forms/bulk_import.py:97 msgid "Type of circuit" msgstr "" -#: circuits/forms/bulk_import.py:102 circuits/forms/bulk_import.py:228 -#: dcim/forms/bulk_import.py:107 dcim/forms/bulk_import.py:166 -#: dcim/forms/bulk_import.py:283 dcim/forms/bulk_import.py:392 -#: dcim/forms/bulk_import.py:623 dcim/forms/bulk_import.py:783 -#: dcim/forms/bulk_import.py:1260 dcim/forms/bulk_import.py:1762 -#: ipam/forms/bulk_import.py:207 ipam/forms/bulk_import.py:271 -#: ipam/forms/bulk_import.py:307 ipam/forms/bulk_import.py:538 -#: ipam/forms/bulk_import.py:551 virtualization/forms/bulk_import.py:59 -#: virtualization/forms/bulk_import.py:115 vpn/forms/bulk_import.py:38 -#: vpn/forms/bulk_import.py:265 wireless/forms/bulk_import.py:46 +#: netbox/circuits/forms/bulk_import.py:102 +#: netbox/circuits/forms/bulk_import.py:228 +#: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:166 +#: netbox/dcim/forms/bulk_import.py:283 netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:623 netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:1260 netbox/dcim/forms/bulk_import.py:1762 +#: netbox/ipam/forms/bulk_import.py:207 netbox/ipam/forms/bulk_import.py:271 +#: netbox/ipam/forms/bulk_import.py:307 netbox/ipam/forms/bulk_import.py:538 +#: netbox/ipam/forms/bulk_import.py:551 +#: netbox/virtualization/forms/bulk_import.py:59 +#: netbox/virtualization/forms/bulk_import.py:115 +#: netbox/vpn/forms/bulk_import.py:38 netbox/vpn/forms/bulk_import.py:265 +#: netbox/wireless/forms/bulk_import.py:46 msgid "Operational status" msgstr "" -#: circuits/forms/bulk_import.py:115 circuits/forms/bulk_import.py:174 -#: circuits/forms/bulk_import.py:235 dcim/forms/bulk_import.py:128 -#: dcim/forms/bulk_import.py:173 dcim/forms/bulk_import.py:399 -#: dcim/forms/bulk_import.py:599 dcim/forms/bulk_import.py:1525 -#: dcim/forms/bulk_import.py:1757 dcim/forms/bulk_import.py:1820 -#: ipam/forms/bulk_import.py:49 ipam/forms/bulk_import.py:78 -#: ipam/forms/bulk_import.py:106 ipam/forms/bulk_import.py:126 -#: ipam/forms/bulk_import.py:153 ipam/forms/bulk_import.py:181 -#: ipam/forms/bulk_import.py:266 ipam/forms/bulk_import.py:302 -#: ipam/forms/bulk_import.py:499 ipam/forms/bulk_import.py:533 -#: virtualization/forms/bulk_import.py:73 -#: virtualization/forms/bulk_import.py:158 vpn/forms/bulk_import.py:62 -#: wireless/forms/bulk_import.py:60 wireless/forms/bulk_import.py:140 +#: netbox/circuits/forms/bulk_import.py:115 +#: netbox/circuits/forms/bulk_import.py:174 +#: netbox/circuits/forms/bulk_import.py:235 +#: netbox/dcim/forms/bulk_import.py:128 netbox/dcim/forms/bulk_import.py:173 +#: netbox/dcim/forms/bulk_import.py:399 netbox/dcim/forms/bulk_import.py:599 +#: netbox/dcim/forms/bulk_import.py:1525 netbox/dcim/forms/bulk_import.py:1757 +#: netbox/dcim/forms/bulk_import.py:1820 netbox/ipam/forms/bulk_import.py:49 +#: netbox/ipam/forms/bulk_import.py:78 netbox/ipam/forms/bulk_import.py:106 +#: netbox/ipam/forms/bulk_import.py:126 netbox/ipam/forms/bulk_import.py:153 +#: netbox/ipam/forms/bulk_import.py:181 netbox/ipam/forms/bulk_import.py:266 +#: netbox/ipam/forms/bulk_import.py:302 netbox/ipam/forms/bulk_import.py:499 +#: netbox/ipam/forms/bulk_import.py:533 +#: netbox/virtualization/forms/bulk_import.py:73 +#: netbox/virtualization/forms/bulk_import.py:158 +#: netbox/vpn/forms/bulk_import.py:62 netbox/wireless/forms/bulk_import.py:60 +#: netbox/wireless/forms/bulk_import.py:140 msgid "Assigned tenant" msgstr "" -#: circuits/forms/bulk_import.py:139 +#: netbox/circuits/forms/bulk_import.py:139 msgid "Termination type (app & model)" msgstr "" -#: circuits/forms/bulk_import.py:151 circuits/forms/bulk_import.py:164 +#: netbox/circuits/forms/bulk_import.py:151 +#: netbox/circuits/forms/bulk_import.py:164 msgid "Termination ID" msgstr "" -#: circuits/forms/bulk_import.py:185 +#: netbox/circuits/forms/bulk_import.py:185 msgid "Circuit type (app & model)" msgstr "" -#: circuits/forms/bulk_import.py:210 +#: netbox/circuits/forms/bulk_import.py:210 msgid "The network to which this virtual circuit belongs" msgstr "" -#: circuits/forms/bulk_import.py:216 +#: netbox/circuits/forms/bulk_import.py:216 msgid "Assigned provider account (if any)" msgstr "" -#: circuits/forms/bulk_import.py:223 +#: netbox/circuits/forms/bulk_import.py:223 msgid "Type of virtual circuit" msgstr "" -#: circuits/forms/bulk_import.py:255 vpn/forms/bulk_import.py:82 +#: netbox/circuits/forms/bulk_import.py:255 netbox/vpn/forms/bulk_import.py:82 msgid "Operational role" msgstr "" -#: circuits/forms/bulk_import.py:258 circuits/forms/model_forms.py:392 -#: circuits/tables/virtual_circuits.py:109 circuits/ui/panels.py:150 -#: dcim/forms/bulk_import.py:1358 dcim/forms/model_forms.py:1371 -#: dcim/forms/model_forms.py:1640 dcim/forms/model_forms.py:1821 -#: dcim/forms/model_forms.py:1856 dcim/forms/model_forms.py:1981 -#: dcim/tables/connections.py:66 dcim/tables/devices.py:1231 dcim/views.py:3556 -#: dcim/views.py:3659 ipam/forms/bulk_import.py:330 -#: ipam/forms/model_forms.py:307 ipam/forms/model_forms.py:316 -#: ipam/tables/fhrp.py:61 ipam/tables/ip.py:328 ipam/tables/vlans.py:149 -#: templates/circuits/circuit_termination/attrs/connection.html:40 -#: templates/circuits/inc/circuit_termination_fields.html:52 -#: templates/dcim/panels/interface_connection.html:83 -#: templates/wireless/panels/wirelesslink_interface.html:12 -#: virtualization/forms/model_forms.py:449 vpn/forms/bulk_import.py:302 -#: vpn/forms/model_forms.py:434 vpn/forms/model_forms.py:443 -#: vpn/ui/panels.py:27 wireless/forms/model_forms.py:115 -#: wireless/forms/model_forms.py:157 +#: netbox/circuits/forms/bulk_import.py:258 +#: netbox/circuits/forms/model_forms.py:392 +#: netbox/circuits/tables/virtual_circuits.py:109 +#: netbox/circuits/ui/panels.py:150 netbox/dcim/forms/bulk_import.py:1358 +#: netbox/dcim/forms/model_forms.py:1371 netbox/dcim/forms/model_forms.py:1640 +#: netbox/dcim/forms/model_forms.py:1821 netbox/dcim/forms/model_forms.py:1856 +#: netbox/dcim/forms/model_forms.py:1981 netbox/dcim/tables/connections.py:66 +#: netbox/dcim/tables/devices.py:1231 netbox/dcim/views.py:3556 +#: netbox/dcim/views.py:3659 netbox/ipam/forms/bulk_import.py:330 +#: netbox/ipam/forms/model_forms.py:307 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/tables/fhrp.py:61 netbox/ipam/tables/ip.py:328 +#: netbox/ipam/tables/vlans.py:149 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:40 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:52 +#: netbox/templates/dcim/panels/interface_connection.html:83 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:12 +#: netbox/virtualization/forms/model_forms.py:449 +#: netbox/vpn/forms/bulk_import.py:302 netbox/vpn/forms/model_forms.py:434 +#: netbox/vpn/forms/model_forms.py:443 netbox/vpn/ui/panels.py:27 +#: netbox/wireless/forms/model_forms.py:115 +#: netbox/wireless/forms/model_forms.py:157 msgid "Interface" msgstr "" -#: circuits/forms/filtersets.py:41 circuits/forms/filtersets.py:137 -#: circuits/forms/filtersets.py:196 circuits/forms/filtersets.py:254 -#: circuits/tables/circuits.py:140 dcim/forms/bulk_edit.py:348 -#: dcim/forms/bulk_edit.py:462 dcim/forms/bulk_edit.py:701 -#: dcim/forms/bulk_edit.py:750 dcim/forms/bulk_edit.py:915 -#: dcim/forms/bulk_import.py:261 dcim/forms/bulk_import.py:371 -#: dcim/forms/bulk_import.py:662 dcim/forms/bulk_import.py:1706 -#: dcim/forms/bulk_import.py:1740 dcim/forms/filtersets.py:116 -#: dcim/forms/filtersets.py:369 dcim/forms/filtersets.py:404 -#: dcim/forms/filtersets.py:455 dcim/forms/filtersets.py:508 -#: dcim/forms/filtersets.py:853 dcim/forms/filtersets.py:897 -#: dcim/forms/filtersets.py:1075 dcim/forms/filtersets.py:1118 -#: dcim/forms/filtersets.py:1170 dcim/forms/filtersets.py:1209 -#: dcim/forms/filtersets.py:1233 dcim/forms/filtersets.py:1307 -#: dcim/forms/filtersets.py:1338 dcim/forms/filtersets.py:1347 -#: dcim/forms/filtersets.py:1476 dcim/forms/filtersets.py:1516 -#: dcim/forms/filtersets.py:1556 dcim/forms/filtersets.py:1591 -#: dcim/forms/filtersets.py:1639 dcim/forms/filtersets.py:1807 -#: dcim/forms/filtersets.py:1851 dcim/forms/filtersets.py:1894 -#: dcim/forms/filtersets.py:1936 dcim/forms/filtersets.py:1973 -#: dcim/forms/model_forms.py:225 dcim/forms/model_forms.py:299 -#: dcim/forms/model_forms.py:620 dcim/forms/model_forms.py:905 -#: dcim/tables/devices.py:161 dcim/tables/power.py:30 dcim/tables/racks.py:131 -#: dcim/tables/racks.py:227 extras/filtersets.py:743 -#: extras/forms/filtersets.py:409 ipam/forms/filtersets.py:261 -#: ipam/forms/filtersets.py:461 ipam/forms/filtersets.py:486 -#: ipam/forms/filtersets.py:564 templates/dcim/device_edit.html:32 -#: templates/dcim/inc/cable_termination.html:12 -#: virtualization/forms/filtersets.py:91 virtualization/forms/filtersets.py:154 -#: wireless/forms/filtersets.py:99 wireless/forms/model_forms.py:89 -#: wireless/forms/model_forms.py:131 +#: netbox/circuits/forms/filtersets.py:41 +#: netbox/circuits/forms/filtersets.py:137 +#: netbox/circuits/forms/filtersets.py:196 +#: netbox/circuits/forms/filtersets.py:254 +#: netbox/circuits/tables/circuits.py:140 netbox/dcim/forms/bulk_edit.py:348 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/bulk_edit.py:701 +#: netbox/dcim/forms/bulk_edit.py:750 netbox/dcim/forms/bulk_edit.py:915 +#: netbox/dcim/forms/bulk_import.py:261 netbox/dcim/forms/bulk_import.py:371 +#: netbox/dcim/forms/bulk_import.py:662 netbox/dcim/forms/bulk_import.py:1706 +#: netbox/dcim/forms/bulk_import.py:1740 netbox/dcim/forms/filtersets.py:116 +#: netbox/dcim/forms/filtersets.py:369 netbox/dcim/forms/filtersets.py:404 +#: netbox/dcim/forms/filtersets.py:455 netbox/dcim/forms/filtersets.py:508 +#: netbox/dcim/forms/filtersets.py:853 netbox/dcim/forms/filtersets.py:897 +#: netbox/dcim/forms/filtersets.py:1075 netbox/dcim/forms/filtersets.py:1118 +#: netbox/dcim/forms/filtersets.py:1170 netbox/dcim/forms/filtersets.py:1209 +#: netbox/dcim/forms/filtersets.py:1233 netbox/dcim/forms/filtersets.py:1307 +#: netbox/dcim/forms/filtersets.py:1338 netbox/dcim/forms/filtersets.py:1347 +#: netbox/dcim/forms/filtersets.py:1476 netbox/dcim/forms/filtersets.py:1516 +#: netbox/dcim/forms/filtersets.py:1556 netbox/dcim/forms/filtersets.py:1591 +#: netbox/dcim/forms/filtersets.py:1639 netbox/dcim/forms/filtersets.py:1807 +#: netbox/dcim/forms/filtersets.py:1851 netbox/dcim/forms/filtersets.py:1894 +#: netbox/dcim/forms/filtersets.py:1936 netbox/dcim/forms/filtersets.py:1973 +#: netbox/dcim/forms/model_forms.py:225 netbox/dcim/forms/model_forms.py:299 +#: netbox/dcim/forms/model_forms.py:620 netbox/dcim/forms/model_forms.py:905 +#: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:30 +#: netbox/dcim/tables/racks.py:131 netbox/dcim/tables/racks.py:227 +#: netbox/extras/filtersets.py:743 netbox/extras/forms/filtersets.py:409 +#: netbox/ipam/forms/filtersets.py:261 netbox/ipam/forms/filtersets.py:461 +#: netbox/ipam/forms/filtersets.py:486 netbox/ipam/forms/filtersets.py:564 +#: netbox/templates/dcim/device_edit.html:32 +#: netbox/templates/dcim/inc/cable_termination.html:12 +#: netbox/virtualization/forms/filtersets.py:91 +#: netbox/virtualization/forms/filtersets.py:154 +#: netbox/wireless/forms/filtersets.py:99 +#: netbox/wireless/forms/model_forms.py:89 +#: netbox/wireless/forms/model_forms.py:131 msgid "Location" msgstr "" -#: circuits/forms/filtersets.py:43 circuits/forms/filtersets.py:78 -#: circuits/forms/filtersets.py:98 circuits/forms/filtersets.py:118 -#: circuits/forms/filtersets.py:139 circuits/forms/filtersets.py:287 -#: circuits/forms/filtersets.py:326 circuits/forms/filtersets.py:343 -#: core/forms/filtersets.py:34 dcim/forms/filtersets.py:172 -#: dcim/forms/filtersets.py:188 dcim/forms/filtersets.py:205 -#: dcim/forms/filtersets.py:238 dcim/forms/filtersets.py:285 -#: dcim/forms/filtersets.py:294 dcim/forms/filtersets.py:349 -#: dcim/forms/filtersets.py:375 dcim/forms/filtersets.py:460 -#: dcim/forms/filtersets.py:481 dcim/forms/filtersets.py:552 -#: dcim/forms/filtersets.py:572 dcim/forms/filtersets.py:697 -#: dcim/forms/filtersets.py:716 dcim/forms/filtersets.py:803 -#: dcim/forms/filtersets.py:823 dcim/forms/filtersets.py:857 -#: dcim/forms/filtersets.py:1049 dcim/forms/filtersets.py:1080 -#: dcim/forms/filtersets.py:1172 dcim/forms/filtersets.py:1215 -#: dcim/forms/filtersets.py:1308 dcim/forms/filtersets.py:1350 -#: dcim/forms/filtersets.py:1482 dcim/forms/filtersets.py:1522 -#: dcim/forms/filtersets.py:1562 dcim/forms/filtersets.py:1597 -#: dcim/forms/filtersets.py:1646 dcim/forms/filtersets.py:1813 -#: dcim/forms/filtersets.py:1857 dcim/forms/filtersets.py:1899 -#: dcim/forms/filtersets.py:1941 dcim/forms/filtersets.py:1978 -#: dcim/forms/filtersets.py:2040 dcim/forms/filtersets.py:2055 -#: extras/forms/filtersets.py:52 extras/forms/filtersets.py:132 -#: extras/forms/filtersets.py:153 extras/forms/filtersets.py:186 -#: extras/forms/filtersets.py:249 extras/forms/filtersets.py:312 -#: extras/forms/filtersets.py:335 extras/forms/filtersets.py:367 -#: extras/forms/filtersets.py:386 extras/forms/filtersets.py:413 -#: extras/forms/filtersets.py:506 ipam/forms/filtersets.py:51 -#: ipam/forms/filtersets.py:72 ipam/forms/filtersets.py:92 -#: ipam/forms/filtersets.py:110 ipam/forms/filtersets.py:132 -#: ipam/forms/filtersets.py:156 ipam/forms/filtersets.py:185 -#: ipam/forms/filtersets.py:202 ipam/forms/filtersets.py:303 -#: ipam/forms/filtersets.py:356 ipam/forms/filtersets.py:430 -#: ipam/forms/filtersets.py:465 ipam/forms/filtersets.py:527 -#: ipam/forms/filtersets.py:568 ipam/forms/filtersets.py:638 -#: ipam/forms/filtersets.py:658 netbox/navigation/menu.py:430 -#: templates/dcim/device_edit.html:104 templates/dcim/htmx/cable_edit.html:84 -#: templates/dcim/virtualchassis_edit.html:39 -#: templates/generic/bulk_edit.html:65 templates/htmx/form.html:28 -#: templates/ipam/vlan_edit.html:70 tenancy/forms/filtersets.py:41 -#: tenancy/forms/filtersets.py:56 tenancy/forms/filtersets.py:77 -#: tenancy/forms/filtersets.py:91 tenancy/forms/filtersets.py:101 -#: virtualization/forms/filtersets.py:37 virtualization/forms/filtersets.py:47 -#: virtualization/forms/filtersets.py:59 virtualization/forms/filtersets.py:116 -#: virtualization/forms/filtersets.py:161 -#: virtualization/forms/filtersets.py:268 -#: virtualization/forms/filtersets.py:324 vpn/forms/filtersets.py:40 -#: vpn/forms/filtersets.py:53 vpn/forms/filtersets.py:109 -#: vpn/forms/filtersets.py:139 vpn/forms/filtersets.py:164 -#: vpn/forms/filtersets.py:184 vpn/forms/filtersets.py:204 -#: vpn/forms/filtersets.py:230 wireless/forms/filtersets.py:27 -#: wireless/forms/filtersets.py:45 wireless/forms/filtersets.py:111 +#: netbox/circuits/forms/filtersets.py:43 +#: netbox/circuits/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:98 +#: netbox/circuits/forms/filtersets.py:118 +#: netbox/circuits/forms/filtersets.py:139 +#: netbox/circuits/forms/filtersets.py:287 +#: netbox/circuits/forms/filtersets.py:326 +#: netbox/circuits/forms/filtersets.py:343 netbox/core/forms/filtersets.py:34 +#: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:188 +#: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:238 +#: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:294 +#: netbox/dcim/forms/filtersets.py:349 netbox/dcim/forms/filtersets.py:375 +#: netbox/dcim/forms/filtersets.py:460 netbox/dcim/forms/filtersets.py:481 +#: netbox/dcim/forms/filtersets.py:552 netbox/dcim/forms/filtersets.py:572 +#: netbox/dcim/forms/filtersets.py:697 netbox/dcim/forms/filtersets.py:716 +#: netbox/dcim/forms/filtersets.py:803 netbox/dcim/forms/filtersets.py:823 +#: netbox/dcim/forms/filtersets.py:857 netbox/dcim/forms/filtersets.py:1049 +#: netbox/dcim/forms/filtersets.py:1080 netbox/dcim/forms/filtersets.py:1172 +#: netbox/dcim/forms/filtersets.py:1215 netbox/dcim/forms/filtersets.py:1308 +#: netbox/dcim/forms/filtersets.py:1350 netbox/dcim/forms/filtersets.py:1482 +#: netbox/dcim/forms/filtersets.py:1522 netbox/dcim/forms/filtersets.py:1562 +#: netbox/dcim/forms/filtersets.py:1597 netbox/dcim/forms/filtersets.py:1646 +#: netbox/dcim/forms/filtersets.py:1813 netbox/dcim/forms/filtersets.py:1857 +#: netbox/dcim/forms/filtersets.py:1899 netbox/dcim/forms/filtersets.py:1941 +#: netbox/dcim/forms/filtersets.py:1978 netbox/dcim/forms/filtersets.py:2040 +#: netbox/dcim/forms/filtersets.py:2055 netbox/extras/forms/filtersets.py:52 +#: netbox/extras/forms/filtersets.py:132 netbox/extras/forms/filtersets.py:153 +#: netbox/extras/forms/filtersets.py:186 netbox/extras/forms/filtersets.py:249 +#: netbox/extras/forms/filtersets.py:312 netbox/extras/forms/filtersets.py:335 +#: netbox/extras/forms/filtersets.py:367 netbox/extras/forms/filtersets.py:386 +#: netbox/extras/forms/filtersets.py:413 netbox/extras/forms/filtersets.py:506 +#: netbox/ipam/forms/filtersets.py:51 netbox/ipam/forms/filtersets.py:72 +#: netbox/ipam/forms/filtersets.py:92 netbox/ipam/forms/filtersets.py:110 +#: netbox/ipam/forms/filtersets.py:132 netbox/ipam/forms/filtersets.py:156 +#: netbox/ipam/forms/filtersets.py:185 netbox/ipam/forms/filtersets.py:202 +#: netbox/ipam/forms/filtersets.py:303 netbox/ipam/forms/filtersets.py:356 +#: netbox/ipam/forms/filtersets.py:430 netbox/ipam/forms/filtersets.py:465 +#: netbox/ipam/forms/filtersets.py:527 netbox/ipam/forms/filtersets.py:568 +#: netbox/ipam/forms/filtersets.py:638 netbox/ipam/forms/filtersets.py:658 +#: netbox/netbox/navigation/menu.py:430 +#: netbox/templates/dcim/device_edit.html:104 +#: netbox/templates/dcim/htmx/cable_edit.html:84 +#: netbox/templates/dcim/virtualchassis_edit.html:39 +#: netbox/templates/generic/bulk_edit.html:65 +#: netbox/templates/htmx/form.html:28 netbox/templates/ipam/vlan_edit.html:70 +#: netbox/tenancy/forms/filtersets.py:41 netbox/tenancy/forms/filtersets.py:56 +#: netbox/tenancy/forms/filtersets.py:77 netbox/tenancy/forms/filtersets.py:91 +#: netbox/tenancy/forms/filtersets.py:101 +#: netbox/virtualization/forms/filtersets.py:37 +#: netbox/virtualization/forms/filtersets.py:47 +#: netbox/virtualization/forms/filtersets.py:59 +#: netbox/virtualization/forms/filtersets.py:116 +#: netbox/virtualization/forms/filtersets.py:161 +#: netbox/virtualization/forms/filtersets.py:268 +#: netbox/virtualization/forms/filtersets.py:324 +#: netbox/vpn/forms/filtersets.py:40 netbox/vpn/forms/filtersets.py:53 +#: netbox/vpn/forms/filtersets.py:109 netbox/vpn/forms/filtersets.py:139 +#: netbox/vpn/forms/filtersets.py:164 netbox/vpn/forms/filtersets.py:184 +#: netbox/vpn/forms/filtersets.py:204 netbox/vpn/forms/filtersets.py:230 +#: netbox/wireless/forms/filtersets.py:27 +#: netbox/wireless/forms/filtersets.py:45 +#: netbox/wireless/forms/filtersets.py:111 msgid "Ownership" msgstr "" -#: circuits/forms/filtersets.py:44 circuits/forms/filtersets.py:79 -#: circuits/forms/filtersets.py:140 dcim/forms/filtersets.py:173 -#: dcim/forms/filtersets.py:189 dcim/forms/filtersets.py:206 -#: dcim/forms/filtersets.py:239 dcim/forms/filtersets.py:376 -#: dcim/forms/filtersets.py:461 dcim/forms/filtersets.py:553 -#: dcim/forms/filtersets.py:858 dcim/forms/filtersets.py:1309 -#: ipam/forms/filtersets.py:111 ipam/forms/filtersets.py:203 -#: ipam/forms/filtersets.py:304 ipam/forms/filtersets.py:357 -#: ipam/forms/filtersets.py:659 netbox/navigation/menu.py:34 -#: netbox/navigation/menu.py:36 netbox/views/generic/feature_views.py:274 -#: tenancy/forms/filtersets.py:57 tenancy/tables/columns.py:56 -#: tenancy/tables/contacts.py:21 virtualization/forms/filtersets.py:48 -#: virtualization/forms/filtersets.py:60 virtualization/forms/filtersets.py:162 -#: vpn/forms/filtersets.py:41 vpn/forms/filtersets.py:54 -#: vpn/forms/filtersets.py:231 +#: netbox/circuits/forms/filtersets.py:44 +#: netbox/circuits/forms/filtersets.py:79 +#: netbox/circuits/forms/filtersets.py:140 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/filtersets.py:189 netbox/dcim/forms/filtersets.py:206 +#: netbox/dcim/forms/filtersets.py:239 netbox/dcim/forms/filtersets.py:376 +#: netbox/dcim/forms/filtersets.py:461 netbox/dcim/forms/filtersets.py:553 +#: netbox/dcim/forms/filtersets.py:858 netbox/dcim/forms/filtersets.py:1309 +#: netbox/ipam/forms/filtersets.py:111 netbox/ipam/forms/filtersets.py:203 +#: netbox/ipam/forms/filtersets.py:304 netbox/ipam/forms/filtersets.py:357 +#: netbox/ipam/forms/filtersets.py:659 netbox/netbox/navigation/menu.py:34 +#: netbox/netbox/navigation/menu.py:36 +#: netbox/netbox/views/generic/feature_views.py:274 +#: netbox/tenancy/forms/filtersets.py:57 netbox/tenancy/tables/columns.py:56 +#: netbox/tenancy/tables/contacts.py:21 +#: netbox/virtualization/forms/filtersets.py:48 +#: netbox/virtualization/forms/filtersets.py:60 +#: netbox/virtualization/forms/filtersets.py:162 +#: netbox/vpn/forms/filtersets.py:41 netbox/vpn/forms/filtersets.py:54 +#: netbox/vpn/forms/filtersets.py:231 msgid "Contacts" msgstr "" -#: circuits/forms/filtersets.py:49 circuits/forms/filtersets.py:177 -#: circuits/forms/filtersets.py:239 circuits/tables/circuits.py:135 -#: dcim/forms/bulk_edit.py:121 dcim/forms/bulk_edit.py:323 -#: dcim/forms/bulk_edit.py:890 dcim/forms/bulk_import.py:110 -#: dcim/forms/filtersets.py:94 dcim/forms/filtersets.py:171 -#: dcim/forms/filtersets.py:217 dcim/forms/filtersets.py:244 -#: dcim/forms/filtersets.py:382 dcim/forms/filtersets.py:486 -#: dcim/forms/filtersets.py:874 dcim/forms/filtersets.py:1096 -#: dcim/forms/filtersets.py:1177 dcim/forms/filtersets.py:1220 -#: dcim/forms/filtersets.py:1315 dcim/forms/filtersets.py:1355 -#: dcim/forms/filtersets.py:2097 dcim/forms/filtersets.py:2121 -#: dcim/forms/filtersets.py:2145 dcim/forms/model_forms.py:131 -#: dcim/forms/object_create.py:278 dcim/tables/devices.py:147 -#: dcim/tables/sites.py:65 extras/filtersets.py:710 ipam/forms/bulk_edit.py:409 -#: ipam/forms/filtersets.py:246 ipam/forms/filtersets.py:471 -#: ipam/forms/filtersets.py:574 ipam/ui/panels.py:196 -#: virtualization/forms/filtersets.py:71 virtualization/forms/filtersets.py:195 -#: virtualization/forms/model_forms.py:90 vpn/forms/filtersets.py:279 -#: wireless/forms/filtersets.py:79 +#: netbox/circuits/forms/filtersets.py:49 +#: netbox/circuits/forms/filtersets.py:177 +#: netbox/circuits/forms/filtersets.py:239 +#: netbox/circuits/tables/circuits.py:135 netbox/dcim/forms/bulk_edit.py:121 +#: netbox/dcim/forms/bulk_edit.py:323 netbox/dcim/forms/bulk_edit.py:890 +#: netbox/dcim/forms/bulk_import.py:110 netbox/dcim/forms/filtersets.py:94 +#: netbox/dcim/forms/filtersets.py:171 netbox/dcim/forms/filtersets.py:217 +#: netbox/dcim/forms/filtersets.py:244 netbox/dcim/forms/filtersets.py:382 +#: netbox/dcim/forms/filtersets.py:486 netbox/dcim/forms/filtersets.py:874 +#: netbox/dcim/forms/filtersets.py:1096 netbox/dcim/forms/filtersets.py:1177 +#: netbox/dcim/forms/filtersets.py:1220 netbox/dcim/forms/filtersets.py:1315 +#: netbox/dcim/forms/filtersets.py:1355 netbox/dcim/forms/filtersets.py:2097 +#: netbox/dcim/forms/filtersets.py:2121 netbox/dcim/forms/filtersets.py:2145 +#: netbox/dcim/forms/model_forms.py:131 netbox/dcim/forms/object_create.py:278 +#: netbox/dcim/tables/devices.py:147 netbox/dcim/tables/sites.py:65 +#: netbox/extras/filtersets.py:710 netbox/ipam/forms/bulk_edit.py:409 +#: netbox/ipam/forms/filtersets.py:246 netbox/ipam/forms/filtersets.py:471 +#: netbox/ipam/forms/filtersets.py:574 netbox/ipam/ui/panels.py:196 +#: netbox/virtualization/forms/filtersets.py:71 +#: netbox/virtualization/forms/filtersets.py:195 +#: netbox/virtualization/forms/model_forms.py:90 +#: netbox/vpn/forms/filtersets.py:279 netbox/wireless/forms/filtersets.py:79 msgid "Region" msgstr "" -#: circuits/forms/filtersets.py:54 circuits/forms/filtersets.py:182 -#: circuits/forms/filtersets.py:244 dcim/forms/bulk_edit.py:331 -#: dcim/forms/bulk_edit.py:898 dcim/forms/filtersets.py:99 -#: dcim/forms/filtersets.py:222 dcim/forms/filtersets.py:249 -#: dcim/forms/filtersets.py:395 dcim/forms/filtersets.py:491 -#: dcim/forms/filtersets.py:879 dcim/forms/filtersets.py:1101 -#: dcim/forms/filtersets.py:1182 dcim/forms/filtersets.py:1320 -#: dcim/forms/filtersets.py:1360 dcim/forms/object_create.py:286 -#: extras/filtersets.py:727 ipam/forms/bulk_edit.py:414 -#: ipam/forms/filtersets.py:171 ipam/forms/filtersets.py:251 -#: ipam/forms/filtersets.py:476 ipam/forms/filtersets.py:579 -#: virtualization/forms/filtersets.py:76 virtualization/forms/filtersets.py:200 -#: virtualization/forms/model_forms.py:96 wireless/forms/filtersets.py:84 +#: netbox/circuits/forms/filtersets.py:54 +#: netbox/circuits/forms/filtersets.py:182 +#: netbox/circuits/forms/filtersets.py:244 netbox/dcim/forms/bulk_edit.py:331 +#: netbox/dcim/forms/bulk_edit.py:898 netbox/dcim/forms/filtersets.py:99 +#: netbox/dcim/forms/filtersets.py:222 netbox/dcim/forms/filtersets.py:249 +#: netbox/dcim/forms/filtersets.py:395 netbox/dcim/forms/filtersets.py:491 +#: netbox/dcim/forms/filtersets.py:879 netbox/dcim/forms/filtersets.py:1101 +#: netbox/dcim/forms/filtersets.py:1182 netbox/dcim/forms/filtersets.py:1320 +#: netbox/dcim/forms/filtersets.py:1360 netbox/dcim/forms/object_create.py:286 +#: netbox/extras/filtersets.py:727 netbox/ipam/forms/bulk_edit.py:414 +#: netbox/ipam/forms/filtersets.py:171 netbox/ipam/forms/filtersets.py:251 +#: netbox/ipam/forms/filtersets.py:476 netbox/ipam/forms/filtersets.py:579 +#: netbox/virtualization/forms/filtersets.py:76 +#: netbox/virtualization/forms/filtersets.py:200 +#: netbox/virtualization/forms/model_forms.py:96 +#: netbox/wireless/forms/filtersets.py:84 msgid "Site group" msgstr "" -#: circuits/forms/filtersets.py:87 circuits/tables/circuits.py:61 -#: circuits/tables/providers.py:61 circuits/tables/virtual_circuits.py:55 -#: circuits/tables/virtual_circuits.py:100 +#: netbox/circuits/forms/filtersets.py:87 netbox/circuits/tables/circuits.py:61 +#: netbox/circuits/tables/providers.py:61 +#: netbox/circuits/tables/virtual_circuits.py:55 +#: netbox/circuits/tables/virtual_circuits.py:100 msgid "Account" msgstr "" -#: circuits/forms/filtersets.py:262 +#: netbox/circuits/forms/filtersets.py:262 msgid "Term Side" msgstr "" -#: circuits/forms/filtersets.py:296 dcim/forms/bulk_edit.py:1596 -#: extras/forms/model_forms.py:775 extras/ui/panels.py:446 -#: ipam/forms/filtersets.py:154 ipam/forms/filtersets.py:657 -#: ipam/forms/model_forms.py:353 ipam/ui/panels.py:122 -#: templates/ipam/vlan_edit.html:42 tenancy/forms/filtersets.py:116 -#: users/forms/model_forms.py:379 users/forms/model_forms.py:421 +#: netbox/circuits/forms/filtersets.py:296 netbox/dcim/forms/bulk_edit.py:1596 +#: netbox/extras/forms/model_forms.py:775 netbox/extras/ui/panels.py:446 +#: netbox/ipam/forms/filtersets.py:154 netbox/ipam/forms/filtersets.py:657 +#: netbox/ipam/forms/model_forms.py:353 netbox/ipam/ui/panels.py:122 +#: netbox/templates/ipam/vlan_edit.html:42 +#: netbox/tenancy/forms/filtersets.py:116 netbox/users/forms/model_forms.py:370 +#: netbox/users/forms/model_forms.py:412 msgid "Assignment" msgstr "" -#: circuits/forms/filtersets.py:311 circuits/forms/model_forms.py:279 -#: circuits/tables/circuits.py:187 dcim/forms/bulk_edit.py:126 -#: dcim/forms/bulk_edit.py:356 dcim/forms/bulk_import.py:117 -#: dcim/forms/model_forms.py:137 dcim/tables/racks.py:139 -#: dcim/tables/racks.py:232 dcim/tables/sites.py:69 -#: extras/forms/filtersets.py:612 ipam/filtersets.py:1049 -#: ipam/forms/bulk_edit.py:428 ipam/forms/bulk_import.py:522 -#: ipam/forms/model_forms.py:591 ipam/tables/fhrp.py:64 ipam/tables/vlans.py:98 -#: templates/dcim/panels/interface_wireless_lans.html:8 -#: templates/ipam/inc/panels/fhrp_groups.html:23 -#: templates/ipam/panels/fhrp_groups.html:9 tenancy/forms/bulk_edit.py:44 -#: tenancy/forms/bulk_import.py:46 tenancy/forms/filtersets.py:63 -#: tenancy/forms/filtersets.py:126 tenancy/forms/model_forms.py:45 -#: tenancy/forms/model_forms.py:122 tenancy/tables/tenants.py:39 -#: users/filtersets.py:77 users/filtersets.py:228 users/forms/bulk_edit.py:161 -#: users/forms/filtersets.py:35 users/forms/filtersets.py:41 -#: users/forms/filtersets.py:76 users/forms/filtersets.py:165 -#: users/forms/filtersets.py:171 users/forms/model_forms.py:552 -#: users/tables.py:186 virtualization/forms/bulk_edit.py:59 -#: virtualization/forms/bulk_import.py:50 -#: virtualization/forms/filtersets.py:102 -#: virtualization/forms/model_forms.py:69 virtualization/tables/clusters.py:71 -#: vpn/forms/bulk_edit.py:100 vpn/forms/bulk_import.py:157 -#: vpn/forms/filtersets.py:127 vpn/tables/crypto.py:31 vpn/tables/tunnels.py:45 -#: wireless/forms/bulk_edit.py:45 wireless/forms/bulk_import.py:37 -#: wireless/forms/filtersets.py:55 wireless/forms/model_forms.py:41 -#: wireless/tables/wirelesslan.py:41 +#: netbox/circuits/forms/filtersets.py:311 +#: netbox/circuits/forms/model_forms.py:279 +#: netbox/circuits/tables/circuits.py:187 netbox/dcim/forms/bulk_edit.py:126 +#: netbox/dcim/forms/bulk_edit.py:356 netbox/dcim/forms/bulk_import.py:117 +#: netbox/dcim/forms/model_forms.py:137 netbox/dcim/tables/racks.py:139 +#: netbox/dcim/tables/racks.py:232 netbox/dcim/tables/sites.py:69 +#: netbox/extras/forms/filtersets.py:612 netbox/ipam/filtersets.py:1049 +#: netbox/ipam/forms/bulk_edit.py:428 netbox/ipam/forms/bulk_import.py:522 +#: netbox/ipam/forms/model_forms.py:591 netbox/ipam/tables/fhrp.py:64 +#: netbox/ipam/tables/vlans.py:98 +#: netbox/templates/dcim/panels/interface_wireless_lans.html:8 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:23 +#: netbox/templates/ipam/panels/fhrp_groups.html:9 +#: netbox/tenancy/forms/bulk_edit.py:44 netbox/tenancy/forms/bulk_import.py:46 +#: netbox/tenancy/forms/filtersets.py:63 netbox/tenancy/forms/filtersets.py:126 +#: netbox/tenancy/forms/model_forms.py:45 +#: netbox/tenancy/forms/model_forms.py:122 netbox/tenancy/tables/tenants.py:39 +#: netbox/users/filtersets.py:77 netbox/users/filtersets.py:228 +#: netbox/users/forms/bulk_edit.py:161 netbox/users/forms/filtersets.py:35 +#: netbox/users/forms/filtersets.py:41 netbox/users/forms/filtersets.py:76 +#: netbox/users/forms/filtersets.py:165 netbox/users/forms/filtersets.py:171 +#: netbox/users/forms/model_forms.py:543 netbox/users/tables.py:186 +#: netbox/virtualization/forms/bulk_edit.py:59 +#: netbox/virtualization/forms/bulk_import.py:50 +#: netbox/virtualization/forms/filtersets.py:102 +#: netbox/virtualization/forms/model_forms.py:69 +#: netbox/virtualization/tables/clusters.py:71 +#: netbox/vpn/forms/bulk_edit.py:100 netbox/vpn/forms/bulk_import.py:157 +#: netbox/vpn/forms/filtersets.py:127 netbox/vpn/tables/crypto.py:31 +#: netbox/vpn/tables/tunnels.py:45 netbox/wireless/forms/bulk_edit.py:45 +#: netbox/wireless/forms/bulk_import.py:37 +#: netbox/wireless/forms/filtersets.py:55 +#: netbox/wireless/forms/model_forms.py:41 +#: netbox/wireless/tables/wirelesslan.py:41 msgid "Group" msgstr "" -#: circuits/forms/model_forms.py:53 dcim/forms/model_forms.py:149 +#: netbox/circuits/forms/model_forms.py:53 netbox/dcim/forms/model_forms.py:149 msgid "Add ASNs" msgstr "" -#: circuits/forms/model_forms.py:58 dcim/forms/model_forms.py:154 +#: netbox/circuits/forms/model_forms.py:58 netbox/dcim/forms/model_forms.py:154 msgid "Remove ASNs" msgstr "" -#: circuits/forms/model_forms.py:79 dcim/forms/model_forms.py:200 +#: netbox/circuits/forms/model_forms.py:79 netbox/dcim/forms/model_forms.py:200 #, python-brace-format msgid "{count} ASNs currently assigned" msgstr "" -#: circuits/forms/model_forms.py:266 +#: netbox/circuits/forms/model_forms.py:266 msgid "Circuit Group" msgstr "" -#: circuits/forms/model_forms.py:286 +#: netbox/circuits/forms/model_forms.py:286 msgid "Circuit type" msgstr "" -#: circuits/forms/model_forms.py:297 +#: netbox/circuits/forms/model_forms.py:297 msgid "Group Assignment" msgstr "" -#: circuits/models/base.py:18 dcim/models/cables.py:110 -#: dcim/models/device_component_templates.py:363 -#: dcim/models/device_component_templates.py:606 -#: dcim/models/device_component_templates.py:679 -#: dcim/models/device_components.py:648 dcim/models/device_components.py:1231 -#: dcim/models/device_components.py:1279 dcim/models/device_components.py:1462 -#: dcim/models/devices.py:395 dcim/models/racks.py:254 extras/models/tags.py:30 +#: netbox/circuits/models/base.py:18 netbox/dcim/models/cables.py:110 +#: netbox/dcim/models/device_component_templates.py:363 +#: netbox/dcim/models/device_component_templates.py:606 +#: netbox/dcim/models/device_component_templates.py:679 +#: netbox/dcim/models/device_components.py:648 +#: netbox/dcim/models/device_components.py:1231 +#: netbox/dcim/models/device_components.py:1279 +#: netbox/dcim/models/device_components.py:1462 +#: netbox/dcim/models/devices.py:395 netbox/dcim/models/racks.py:254 +#: netbox/extras/models/tags.py:30 msgid "color" msgstr "" -#: circuits/models/circuits.py:39 +#: netbox/circuits/models/circuits.py:39 msgid "circuit type" msgstr "" -#: circuits/models/circuits.py:40 +#: netbox/circuits/models/circuits.py:40 msgid "circuit types" msgstr "" -#: circuits/models/circuits.py:51 circuits/models/virtual_circuits.py:39 +#: netbox/circuits/models/circuits.py:51 +#: netbox/circuits/models/virtual_circuits.py:39 msgid "circuit ID" msgstr "" -#: circuits/models/circuits.py:52 circuits/models/virtual_circuits.py:40 +#: netbox/circuits/models/circuits.py:52 +#: netbox/circuits/models/virtual_circuits.py:40 msgid "Unique circuit ID" msgstr "" -#: circuits/models/circuits.py:72 circuits/models/virtual_circuits.py:60 -#: core/models/data.py:53 core/models/jobs.py:95 dcim/models/cables.py:86 -#: dcim/models/device_components.py:619 dcim/models/device_components.py:1501 -#: dcim/models/devices.py:599 dcim/models/devices.py:1261 -#: dcim/models/modules.py:230 dcim/models/power.py:95 dcim/models/racks.py:329 -#: dcim/models/racks.py:716 dcim/models/sites.py:163 dcim/models/sites.py:287 -#: ipam/models/ip.py:252 ipam/models/ip.py:554 ipam/models/ip.py:787 -#: ipam/models/vlans.py:227 virtualization/models/clusters.py:70 -#: virtualization/models/virtualmachines.py:169 vpn/models/l2vpn.py:36 -#: vpn/models/tunnels.py:38 wireless/models.py:99 wireless/models.py:156 +#: netbox/circuits/models/circuits.py:72 +#: netbox/circuits/models/virtual_circuits.py:60 netbox/core/models/data.py:53 +#: netbox/core/models/jobs.py:95 netbox/dcim/models/cables.py:86 +#: netbox/dcim/models/device_components.py:619 +#: netbox/dcim/models/device_components.py:1501 +#: netbox/dcim/models/devices.py:599 netbox/dcim/models/devices.py:1261 +#: netbox/dcim/models/modules.py:230 netbox/dcim/models/power.py:95 +#: netbox/dcim/models/racks.py:329 netbox/dcim/models/racks.py:716 +#: netbox/dcim/models/sites.py:163 netbox/dcim/models/sites.py:287 +#: netbox/ipam/models/ip.py:252 netbox/ipam/models/ip.py:554 +#: netbox/ipam/models/ip.py:787 netbox/ipam/models/vlans.py:227 +#: netbox/virtualization/models/clusters.py:70 +#: netbox/virtualization/models/virtualmachines.py:169 +#: netbox/vpn/models/l2vpn.py:36 netbox/vpn/models/tunnels.py:38 +#: netbox/wireless/models.py:99 netbox/wireless/models.py:156 msgid "status" msgstr "" -#: circuits/models/circuits.py:87 templates/core/plugin.html:20 +#: netbox/circuits/models/circuits.py:87 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "" -#: circuits/models/circuits.py:92 +#: netbox/circuits/models/circuits.py:92 msgid "terminates" msgstr "" -#: circuits/models/circuits.py:97 +#: netbox/circuits/models/circuits.py:97 msgid "commit rate (Kbps)" msgstr "" -#: circuits/models/circuits.py:98 +#: netbox/circuits/models/circuits.py:98 msgid "Committed rate" msgstr "" -#: circuits/models/circuits.py:150 +#: netbox/circuits/models/circuits.py:150 msgid "circuit" msgstr "" -#: circuits/models/circuits.py:151 +#: netbox/circuits/models/circuits.py:151 msgid "circuits" msgstr "" -#: circuits/models/circuits.py:180 +#: netbox/circuits/models/circuits.py:180 msgid "circuit group" msgstr "" -#: circuits/models/circuits.py:181 +#: netbox/circuits/models/circuits.py:181 msgid "circuit groups" msgstr "" -#: circuits/models/circuits.py:197 +#: netbox/circuits/models/circuits.py:197 msgid "member ID" msgstr "" -#: circuits/models/circuits.py:209 ipam/models/fhrp.py:99 -#: tenancy/models/contacts.py:150 +#: netbox/circuits/models/circuits.py:209 netbox/ipam/models/fhrp.py:99 +#: netbox/tenancy/models/contacts.py:150 msgid "priority" msgstr "" -#: circuits/models/circuits.py:230 +#: netbox/circuits/models/circuits.py:230 msgid "Circuit group assignment" msgstr "" -#: circuits/models/circuits.py:231 +#: netbox/circuits/models/circuits.py:231 msgid "Circuit group assignments" msgstr "" -#: circuits/models/circuits.py:258 +#: netbox/circuits/models/circuits.py:258 msgid "termination side" msgstr "" -#: circuits/models/circuits.py:276 +#: netbox/circuits/models/circuits.py:276 msgid "port speed (Kbps)" msgstr "" -#: circuits/models/circuits.py:279 +#: netbox/circuits/models/circuits.py:279 msgid "Physical circuit speed" msgstr "" -#: circuits/models/circuits.py:284 +#: netbox/circuits/models/circuits.py:284 msgid "upstream speed (Kbps)" msgstr "" -#: circuits/models/circuits.py:285 +#: netbox/circuits/models/circuits.py:285 msgid "Upstream speed, if different from port speed" msgstr "" -#: circuits/models/circuits.py:290 +#: netbox/circuits/models/circuits.py:290 msgid "cross-connect ID" msgstr "" -#: circuits/models/circuits.py:291 +#: netbox/circuits/models/circuits.py:291 msgid "ID of the local cross-connect" msgstr "" -#: circuits/models/circuits.py:296 +#: netbox/circuits/models/circuits.py:296 msgid "patch panel/port(s)" msgstr "" -#: circuits/models/circuits.py:297 +#: netbox/circuits/models/circuits.py:297 msgid "Patch panel ID and port number(s)" msgstr "" -#: circuits/models/circuits.py:300 circuits/models/virtual_circuits.py:149 -#: dcim/models/device_component_templates.py:69 -#: dcim/models/device_components.py:67 dcim/models/racks.py:733 -#: extras/models/configs.py:42 extras/models/configs.py:95 -#: extras/models/configs.py:286 extras/models/customfields.py:152 -#: extras/models/models.py:72 extras/models/models.py:181 -#: extras/models/models.py:428 extras/models/models.py:496 -#: extras/models/models.py:578 extras/models/models.py:707 -#: extras/models/notifications.py:132 extras/models/tags.py:34 -#: ipam/models/vlans.py:386 netbox/models/__init__.py:129 -#: netbox/models/__init__.py:168 netbox/models/__init__.py:218 -#: netbox/models/__init__.py:249 users/models/permissions.py:27 -#: users/models/tokens.py:46 users/models/users.py:41 -#: virtualization/models/virtualmachines.py:432 +#: netbox/circuits/models/circuits.py:300 +#: netbox/circuits/models/virtual_circuits.py:149 +#: netbox/dcim/models/device_component_templates.py:69 +#: netbox/dcim/models/device_components.py:67 netbox/dcim/models/racks.py:733 +#: netbox/extras/models/configs.py:42 netbox/extras/models/configs.py:95 +#: netbox/extras/models/configs.py:286 netbox/extras/models/customfields.py:152 +#: netbox/extras/models/models.py:72 netbox/extras/models/models.py:181 +#: netbox/extras/models/models.py:428 netbox/extras/models/models.py:496 +#: netbox/extras/models/models.py:578 netbox/extras/models/models.py:707 +#: netbox/extras/models/notifications.py:132 netbox/extras/models/tags.py:34 +#: netbox/ipam/models/vlans.py:386 netbox/netbox/models/__init__.py:149 +#: netbox/netbox/models/__init__.py:188 netbox/netbox/models/__init__.py:238 +#: netbox/netbox/models/__init__.py:269 netbox/users/models/permissions.py:27 +#: netbox/users/models/tokens.py:46 netbox/users/models/users.py:41 +#: netbox/virtualization/models/virtualmachines.py:432 msgid "description" msgstr "" -#: circuits/models/circuits.py:353 +#: netbox/circuits/models/circuits.py:353 msgid "circuit termination" msgstr "" -#: circuits/models/circuits.py:354 +#: netbox/circuits/models/circuits.py:354 msgid "circuit terminations" msgstr "" -#: circuits/models/circuits.py:373 +#: netbox/circuits/models/circuits.py:373 msgid "A circuit termination must attach to a terminating object." msgstr "" -#: circuits/models/providers.py:21 circuits/models/providers.py:63 -#: circuits/models/providers.py:98 core/models/data.py:40 -#: core/models/jobs.py:56 dcim/models/cables.py:53 -#: dcim/models/device_component_templates.py:55 -#: dcim/models/device_components.py:56 dcim/models/devices.py:543 -#: dcim/models/devices.py:1184 dcim/models/devices.py:1256 -#: dcim/models/modules.py:35 dcim/models/power.py:39 dcim/models/power.py:90 -#: dcim/models/racks.py:290 dcim/models/sites.py:151 -#: extras/models/configs.py:37 extras/models/configs.py:79 -#: extras/models/configs.py:282 extras/models/customfields.py:119 -#: extras/models/models.py:67 extras/models/models.py:176 -#: extras/models/models.py:318 extras/models/models.py:424 -#: extras/models/models.py:486 extras/models/models.py:574 -#: extras/models/models.py:702 extras/models/notifications.py:127 -#: extras/models/scripts.py:29 ipam/models/asns.py:18 ipam/models/fhrp.py:24 -#: ipam/models/services.py:51 ipam/models/services.py:80 -#: ipam/models/vlans.py:36 ipam/models/vlans.py:216 ipam/models/vlans.py:365 -#: ipam/models/vrfs.py:20 ipam/models/vrfs.py:78 netbox/models/__init__.py:160 -#: netbox/models/__init__.py:208 tenancy/models/contacts.py:85 -#: tenancy/models/tenants.py:19 tenancy/models/tenants.py:45 -#: users/models/owners.py:19 users/models/owners.py:38 -#: users/models/permissions.py:23 users/models/users.py:36 -#: virtualization/models/clusters.py:52 -#: virtualization/models/virtualmachines.py:40 -#: virtualization/models/virtualmachines.py:161 -#: virtualization/models/virtualmachines.py:427 -#: virtualization/models/virtualmachines.py:461 vpn/models/crypto.py:23 -#: vpn/models/crypto.py:69 vpn/models/crypto.py:128 vpn/models/crypto.py:180 -#: vpn/models/crypto.py:216 vpn/models/l2vpn.py:20 vpn/models/tunnels.py:32 -#: wireless/models.py:54 +#: netbox/circuits/models/providers.py:21 +#: netbox/circuits/models/providers.py:63 +#: netbox/circuits/models/providers.py:98 netbox/core/models/data.py:40 +#: netbox/core/models/jobs.py:56 netbox/dcim/models/cables.py:53 +#: netbox/dcim/models/device_component_templates.py:55 +#: netbox/dcim/models/device_components.py:56 netbox/dcim/models/devices.py:543 +#: netbox/dcim/models/devices.py:1184 netbox/dcim/models/devices.py:1256 +#: netbox/dcim/models/modules.py:35 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/power.py:90 netbox/dcim/models/racks.py:290 +#: netbox/dcim/models/sites.py:151 netbox/extras/models/configs.py:37 +#: netbox/extras/models/configs.py:79 netbox/extras/models/configs.py:282 +#: netbox/extras/models/customfields.py:119 netbox/extras/models/models.py:67 +#: netbox/extras/models/models.py:176 netbox/extras/models/models.py:318 +#: netbox/extras/models/models.py:424 netbox/extras/models/models.py:486 +#: netbox/extras/models/models.py:574 netbox/extras/models/models.py:702 +#: netbox/extras/models/notifications.py:127 netbox/extras/models/scripts.py:29 +#: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:24 +#: netbox/ipam/models/services.py:51 netbox/ipam/models/services.py:80 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:216 +#: netbox/ipam/models/vlans.py:365 netbox/ipam/models/vrfs.py:20 +#: netbox/ipam/models/vrfs.py:78 netbox/netbox/models/__init__.py:180 +#: netbox/netbox/models/__init__.py:228 netbox/tenancy/models/contacts.py:85 +#: netbox/tenancy/models/tenants.py:19 netbox/tenancy/models/tenants.py:45 +#: netbox/users/models/owners.py:19 netbox/users/models/owners.py:38 +#: netbox/users/models/permissions.py:23 netbox/users/models/users.py:36 +#: netbox/virtualization/models/clusters.py:52 +#: netbox/virtualization/models/virtualmachines.py:40 +#: netbox/virtualization/models/virtualmachines.py:161 +#: netbox/virtualization/models/virtualmachines.py:427 +#: netbox/virtualization/models/virtualmachines.py:461 +#: netbox/vpn/models/crypto.py:23 netbox/vpn/models/crypto.py:69 +#: netbox/vpn/models/crypto.py:128 netbox/vpn/models/crypto.py:180 +#: netbox/vpn/models/crypto.py:216 netbox/vpn/models/l2vpn.py:20 +#: netbox/vpn/models/tunnels.py:32 netbox/wireless/models.py:54 msgid "name" msgstr "" -#: circuits/models/providers.py:24 +#: netbox/circuits/models/providers.py:24 msgid "Full name of the provider" msgstr "" -#: circuits/models/providers.py:28 dcim/models/devices.py:89 -#: dcim/models/racks.py:166 dcim/models/sites.py:158 -#: extras/models/models.py:491 ipam/models/asns.py:24 ipam/models/vlans.py:41 -#: netbox/models/__init__.py:164 netbox/models/__init__.py:213 -#: tenancy/models/tenants.py:25 tenancy/models/tenants.py:50 -#: virtualization/models/virtualmachines.py:44 vpn/models/l2vpn.py:26 -#: wireless/models.py:60 +#: netbox/circuits/models/providers.py:28 netbox/dcim/models/devices.py:89 +#: netbox/dcim/models/racks.py:166 netbox/dcim/models/sites.py:158 +#: netbox/extras/models/models.py:491 netbox/ipam/models/asns.py:24 +#: netbox/ipam/models/vlans.py:41 netbox/netbox/models/__init__.py:184 +#: netbox/netbox/models/__init__.py:233 netbox/tenancy/models/tenants.py:25 +#: netbox/tenancy/models/tenants.py:50 +#: netbox/virtualization/models/virtualmachines.py:44 +#: netbox/vpn/models/l2vpn.py:26 netbox/wireless/models.py:60 msgid "slug" msgstr "" -#: circuits/models/providers.py:42 +#: netbox/circuits/models/providers.py:42 msgid "provider" msgstr "" -#: circuits/models/providers.py:43 +#: netbox/circuits/models/providers.py:43 msgid "providers" msgstr "" -#: circuits/models/providers.py:60 +#: netbox/circuits/models/providers.py:60 msgid "account ID" msgstr "" -#: circuits/models/providers.py:83 +#: netbox/circuits/models/providers.py:83 msgid "provider account" msgstr "" -#: circuits/models/providers.py:84 +#: netbox/circuits/models/providers.py:84 msgid "provider accounts" msgstr "" -#: circuits/models/providers.py:110 +#: netbox/circuits/models/providers.py:110 msgid "service ID" msgstr "" -#: circuits/models/providers.py:121 +#: netbox/circuits/models/providers.py:121 msgid "provider network" msgstr "" -#: circuits/models/providers.py:122 +#: netbox/circuits/models/providers.py:122 msgid "provider networks" msgstr "" -#: circuits/models/virtual_circuits.py:29 +#: netbox/circuits/models/virtual_circuits.py:29 msgid "virtual circuit type" msgstr "" -#: circuits/models/virtual_circuits.py:30 +#: netbox/circuits/models/virtual_circuits.py:30 msgid "virtual circuit types" msgstr "" -#: circuits/models/virtual_circuits.py:103 +#: netbox/circuits/models/virtual_circuits.py:103 msgid "virtual circuit" msgstr "" -#: circuits/models/virtual_circuits.py:104 +#: netbox/circuits/models/virtual_circuits.py:104 msgid "virtual circuits" msgstr "" -#: circuits/models/virtual_circuits.py:138 ipam/models/asns.py:146 -#: ipam/models/ip.py:209 ipam/models/ip.py:794 vpn/models/tunnels.py:109 +#: netbox/circuits/models/virtual_circuits.py:138 +#: netbox/ipam/models/asns.py:146 netbox/ipam/models/ip.py:209 +#: netbox/ipam/models/ip.py:794 netbox/vpn/models/tunnels.py:109 msgid "role" msgstr "" -#: circuits/models/virtual_circuits.py:159 +#: netbox/circuits/models/virtual_circuits.py:159 msgid "virtual circuit termination" msgstr "" -#: circuits/models/virtual_circuits.py:160 +#: netbox/circuits/models/virtual_circuits.py:160 msgid "virtual circuit terminations" msgstr "" -#: circuits/tables/circuits.py:29 circuits/tables/circuits.py:164 -#: circuits/tables/providers.py:18 circuits/tables/providers.py:64 -#: circuits/tables/providers.py:91 circuits/tables/virtual_circuits.py:18 -#: core/tables/data.py:18 core/tables/jobs.py:18 core/tables/plugins.py:46 -#: core/tables/tasks.py:12 core/tables/tasks.py:117 dcim/forms/filtersets.py:84 -#: dcim/forms/object_create.py:45 dcim/tables/cables.py:145 -#: dcim/tables/devices.py:139 dcim/tables/devices.py:297 -#: dcim/tables/devices.py:421 dcim/tables/devices.py:462 -#: dcim/tables/devices.py:510 dcim/tables/devices.py:564 -#: dcim/tables/devices.py:587 dcim/tables/devices.py:727 -#: dcim/tables/devices.py:749 dcim/tables/devices.py:830 -#: dcim/tables/devices.py:883 dcim/tables/devices.py:961 -#: dcim/tables/devices.py:1036 dcim/tables/devices.py:1104 -#: dcim/tables/devices.py:1123 dcim/tables/devices.py:1152 -#: dcim/tables/devices.py:1179 dcim/tables/devicetypes.py:32 -#: dcim/tables/devicetypes.py:229 dcim/tables/modules.py:18 -#: dcim/tables/power.py:22 dcim/tables/power.py:59 dcim/tables/racks.py:22 -#: dcim/tables/racks.py:45 dcim/tables/racks.py:127 dcim/tables/sites.py:58 -#: extras/forms/filtersets.py:239 extras/tables/tables.py:76 -#: extras/tables/tables.py:148 extras/tables/tables.py:185 -#: extras/tables/tables.py:214 extras/tables/tables.py:273 -#: extras/tables/tables.py:316 extras/tables/tables.py:350 -#: extras/tables/tables.py:467 extras/tables/tables.py:484 -#: extras/tables/tables.py:511 extras/tables/tables.py:554 -#: extras/tables/tables.py:602 extras/tables/tables.py:644 -#: extras/tables/tables.py:674 ipam/forms/bulk_edit.py:347 -#: ipam/forms/filtersets.py:433 ipam/forms/filtersets.py:531 -#: ipam/tables/asn.py:16 ipam/tables/ip.py:33 ipam/tables/ip.py:105 -#: ipam/tables/services.py:16 ipam/tables/services.py:38 -#: ipam/tables/vlans.py:33 ipam/tables/vlans.py:90 ipam/tables/vlans.py:209 -#: ipam/tables/vrfs.py:26 ipam/tables/vrfs.py:65 netbox/tables/tables.py:344 -#: netbox/ui/panels.py:218 netbox/ui/panels.py:227 -#: templates/core/htmx/system_db_schema.html:99 templates/core/plugin.html:54 -#: templates/core/rq_worker.html:43 templates/dcim/cablebundle.html:17 -#: templates/dcim/inc/interface_vlans_table.html:5 -#: templates/dcim/inc/panels/inventory_items.html:18 -#: templates/dcim/panels/component_inventory_items.html:8 -#: templates/dcim/panels/interface_connection.html:64 -#: templates/extras/inc/script_list_content.html:32 -#: tenancy/tables/contacts.py:38 tenancy/tables/contacts.py:53 -#: tenancy/tables/tenants.py:35 users/tables.py:92 users/tables.py:106 -#: users/tables.py:160 users/tables.py:182 -#: virtualization/forms/bulk_create.py:21 -#: virtualization/forms/object_create.py:15 -#: virtualization/forms/object_create.py:25 -#: virtualization/tables/clusters.py:17 virtualization/tables/clusters.py:40 -#: virtualization/tables/clusters.py:63 -#: virtualization/tables/virtualmachines.py:28 -#: virtualization/tables/virtualmachines.py:59 -#: virtualization/tables/virtualmachines.py:150 -#: virtualization/tables/virtualmachines.py:206 vpn/tables/crypto.py:18 -#: vpn/tables/crypto.py:54 vpn/tables/crypto.py:87 vpn/tables/crypto.py:120 -#: vpn/tables/crypto.py:146 vpn/tables/l2vpn.py:23 vpn/tables/tunnels.py:18 -#: vpn/tables/tunnels.py:41 wireless/tables/wirelesslan.py:78 +#: netbox/circuits/tables/circuits.py:29 netbox/circuits/tables/circuits.py:164 +#: netbox/circuits/tables/providers.py:18 +#: netbox/circuits/tables/providers.py:64 +#: netbox/circuits/tables/providers.py:91 +#: netbox/circuits/tables/virtual_circuits.py:18 netbox/core/tables/data.py:18 +#: netbox/core/tables/jobs.py:18 netbox/core/tables/plugins.py:46 +#: netbox/core/tables/tasks.py:12 netbox/core/tables/tasks.py:117 +#: netbox/dcim/forms/filtersets.py:84 netbox/dcim/forms/object_create.py:45 +#: netbox/dcim/tables/cables.py:145 netbox/dcim/tables/devices.py:139 +#: netbox/dcim/tables/devices.py:297 netbox/dcim/tables/devices.py:421 +#: netbox/dcim/tables/devices.py:462 netbox/dcim/tables/devices.py:510 +#: netbox/dcim/tables/devices.py:564 netbox/dcim/tables/devices.py:587 +#: netbox/dcim/tables/devices.py:727 netbox/dcim/tables/devices.py:749 +#: netbox/dcim/tables/devices.py:830 netbox/dcim/tables/devices.py:883 +#: netbox/dcim/tables/devices.py:961 netbox/dcim/tables/devices.py:1036 +#: netbox/dcim/tables/devices.py:1104 netbox/dcim/tables/devices.py:1123 +#: netbox/dcim/tables/devices.py:1152 netbox/dcim/tables/devices.py:1179 +#: netbox/dcim/tables/devicetypes.py:32 netbox/dcim/tables/devicetypes.py:229 +#: netbox/dcim/tables/modules.py:18 netbox/dcim/tables/power.py:22 +#: netbox/dcim/tables/power.py:59 netbox/dcim/tables/racks.py:22 +#: netbox/dcim/tables/racks.py:45 netbox/dcim/tables/racks.py:127 +#: netbox/dcim/tables/sites.py:58 netbox/extras/forms/filtersets.py:239 +#: netbox/extras/tables/tables.py:76 netbox/extras/tables/tables.py:148 +#: netbox/extras/tables/tables.py:185 netbox/extras/tables/tables.py:214 +#: netbox/extras/tables/tables.py:273 netbox/extras/tables/tables.py:316 +#: netbox/extras/tables/tables.py:350 netbox/extras/tables/tables.py:467 +#: netbox/extras/tables/tables.py:484 netbox/extras/tables/tables.py:511 +#: netbox/extras/tables/tables.py:554 netbox/extras/tables/tables.py:602 +#: netbox/extras/tables/tables.py:644 netbox/extras/tables/tables.py:674 +#: netbox/ipam/forms/bulk_edit.py:347 netbox/ipam/forms/filtersets.py:433 +#: netbox/ipam/forms/filtersets.py:531 netbox/ipam/tables/asn.py:16 +#: netbox/ipam/tables/ip.py:33 netbox/ipam/tables/ip.py:105 +#: netbox/ipam/tables/services.py:16 netbox/ipam/tables/services.py:38 +#: netbox/ipam/tables/vlans.py:33 netbox/ipam/tables/vlans.py:90 +#: netbox/ipam/tables/vlans.py:209 netbox/ipam/tables/vrfs.py:26 +#: netbox/ipam/tables/vrfs.py:65 netbox/netbox/tables/tables.py:344 +#: netbox/netbox/ui/panels.py:218 netbox/netbox/ui/panels.py:227 +#: netbox/templates/core/htmx/system_db_schema.html:99 +#: netbox/templates/core/plugin.html:54 netbox/templates/core/rq_worker.html:43 +#: netbox/templates/dcim/cablebundle.html:17 +#: netbox/templates/dcim/inc/interface_vlans_table.html:5 +#: netbox/templates/dcim/inc/panels/inventory_items.html:18 +#: netbox/templates/dcim/panels/component_inventory_items.html:8 +#: netbox/templates/dcim/panels/interface_connection.html:64 +#: netbox/templates/extras/inc/script_list_content.html:32 +#: netbox/tenancy/tables/contacts.py:38 netbox/tenancy/tables/contacts.py:53 +#: netbox/tenancy/tables/tenants.py:35 netbox/users/tables.py:92 +#: netbox/users/tables.py:106 netbox/users/tables.py:160 +#: netbox/users/tables.py:182 netbox/virtualization/forms/bulk_create.py:21 +#: netbox/virtualization/forms/object_create.py:15 +#: netbox/virtualization/forms/object_create.py:25 +#: netbox/virtualization/tables/clusters.py:17 +#: netbox/virtualization/tables/clusters.py:40 +#: netbox/virtualization/tables/clusters.py:63 +#: netbox/virtualization/tables/virtualmachines.py:28 +#: netbox/virtualization/tables/virtualmachines.py:59 +#: netbox/virtualization/tables/virtualmachines.py:150 +#: netbox/virtualization/tables/virtualmachines.py:206 +#: netbox/vpn/tables/crypto.py:18 netbox/vpn/tables/crypto.py:54 +#: netbox/vpn/tables/crypto.py:87 netbox/vpn/tables/crypto.py:120 +#: netbox/vpn/tables/crypto.py:146 netbox/vpn/tables/l2vpn.py:23 +#: netbox/vpn/tables/tunnels.py:18 netbox/vpn/tables/tunnels.py:41 +#: netbox/wireless/tables/wirelesslan.py:78 msgid "Name" msgstr "" -#: circuits/tables/circuits.py:38 circuits/tables/circuits.py:170 -#: circuits/tables/providers.py:43 circuits/tables/providers.py:74 -#: circuits/tables/virtual_circuits.py:27 netbox/navigation/menu.py:286 -#: netbox/navigation/menu.py:290 netbox/navigation/menu.py:292 +#: netbox/circuits/tables/circuits.py:38 netbox/circuits/tables/circuits.py:170 +#: netbox/circuits/tables/providers.py:43 +#: netbox/circuits/tables/providers.py:74 +#: netbox/circuits/tables/virtual_circuits.py:27 +#: netbox/netbox/navigation/menu.py:286 netbox/netbox/navigation/menu.py:290 +#: netbox/netbox/navigation/menu.py:292 msgid "Circuits" msgstr "" -#: circuits/tables/circuits.py:53 circuits/tables/virtual_circuits.py:42 -#: circuits/ui/panels.py:91 circuits/ui/panels.py:134 -#: templates/dcim/panels/interface_virtual_circuit.html:15 +#: netbox/circuits/tables/circuits.py:53 +#: netbox/circuits/tables/virtual_circuits.py:42 +#: netbox/circuits/ui/panels.py:91 netbox/circuits/ui/panels.py:134 +#: netbox/templates/dcim/panels/interface_virtual_circuit.html:15 msgid "Circuit ID" msgstr "" -#: circuits/tables/circuits.py:70 wireless/forms/model_forms.py:161 +#: netbox/circuits/tables/circuits.py:70 +#: netbox/wireless/forms/model_forms.py:161 msgid "Side A" msgstr "" -#: circuits/tables/circuits.py:75 +#: netbox/circuits/tables/circuits.py:75 msgid "Side Z" msgstr "" -#: circuits/tables/circuits.py:78 +#: netbox/circuits/tables/circuits.py:78 msgid "Commit Rate" msgstr "" -#: circuits/tables/circuits.py:85 dcim/forms/filtersets.py:2054 -#: tenancy/tables/contacts.py:67 tenancy/views.py:402 +#: netbox/circuits/tables/circuits.py:85 netbox/dcim/forms/filtersets.py:2054 +#: netbox/tenancy/tables/contacts.py:67 netbox/tenancy/views.py:402 msgid "Assignments" msgstr "" -#: circuits/tables/circuits.py:112 dcim/forms/connections.py:91 +#: netbox/circuits/tables/circuits.py:112 netbox/dcim/forms/connections.py:91 msgid "Side" msgstr "" -#: circuits/tables/circuits.py:115 +#: netbox/circuits/tables/circuits.py:115 msgid "Termination Type" msgstr "" -#: circuits/tables/circuits.py:118 +#: netbox/circuits/tables/circuits.py:118 msgid "Termination Point" msgstr "" -#: circuits/tables/circuits.py:130 dcim/forms/filtersets.py:187 -#: dcim/tables/devices.py:154 +#: netbox/circuits/tables/circuits.py:130 netbox/dcim/forms/filtersets.py:187 +#: netbox/dcim/tables/devices.py:154 msgid "Site Group" msgstr "" -#: circuits/tables/circuits.py:145 -#: templates/dcim/panels/interface_virtual_circuit.html:11 +#: netbox/circuits/tables/circuits.py:145 +#: netbox/templates/dcim/panels/interface_virtual_circuit.html:11 msgid "Provider Network" msgstr "" -#: circuits/tables/providers.py:23 +#: netbox/circuits/tables/providers.py:23 msgid "Accounts" msgstr "" -#: circuits/tables/providers.py:28 +#: netbox/circuits/tables/providers.py:28 msgid "Account Count" msgstr "" -#: circuits/tables/providers.py:37 dcim/tables/sites.py:79 +#: netbox/circuits/tables/providers.py:37 netbox/dcim/tables/sites.py:79 msgid "ASN Count" msgstr "" -#: circuits/tables/virtual_circuits.py:64 circuits/views.py:802 -#: vpn/tables/tunnels.py:59 vpn/views.py:139 vpn/views.py:694 +#: netbox/circuits/tables/virtual_circuits.py:64 netbox/circuits/views.py:802 +#: netbox/vpn/tables/tunnels.py:59 netbox/vpn/views.py:139 +#: netbox/vpn/views.py:694 msgid "Terminations" msgstr "" -#: circuits/tables/virtual_circuits.py:106 dcim/forms/bulk_edit.py:749 -#: dcim/forms/bulk_edit.py:1320 dcim/forms/bulk_edit.py:1732 -#: dcim/forms/bulk_edit.py:1786 dcim/forms/bulk_import.py:763 -#: dcim/forms/bulk_import.py:824 dcim/forms/bulk_import.py:850 -#: dcim/forms/bulk_import.py:876 dcim/forms/bulk_import.py:897 -#: dcim/forms/bulk_import.py:953 dcim/forms/bulk_import.py:1112 -#: dcim/forms/bulk_import.py:1131 dcim/forms/bulk_import.py:1150 -#: dcim/forms/bulk_import.py:1168 dcim/forms/bulk_import.py:1222 -#: dcim/forms/bulk_import.py:1344 dcim/forms/bulk_import.py:1810 -#: dcim/forms/connections.py:34 dcim/forms/filtersets.py:158 -#: dcim/forms/filtersets.py:1054 dcim/forms/filtersets.py:1091 -#: dcim/forms/filtersets.py:1258 dcim/forms/filtersets.py:1479 -#: dcim/forms/filtersets.py:1502 dcim/forms/filtersets.py:1519 -#: dcim/forms/filtersets.py:1542 dcim/forms/filtersets.py:1559 -#: dcim/forms/filtersets.py:1577 dcim/forms/filtersets.py:1594 -#: dcim/forms/filtersets.py:1621 dcim/forms/filtersets.py:1643 -#: dcim/forms/filtersets.py:1765 dcim/forms/filtersets.py:1810 -#: dcim/forms/filtersets.py:1833 dcim/forms/filtersets.py:1854 -#: dcim/forms/filtersets.py:1876 dcim/forms/filtersets.py:1897 -#: dcim/forms/filtersets.py:1918 dcim/forms/filtersets.py:1939 -#: dcim/forms/filtersets.py:1956 dcim/forms/filtersets.py:1976 -#: dcim/forms/filtersets.py:2018 dcim/forms/filtersets.py:2113 -#: dcim/forms/filtersets.py:2137 dcim/forms/filtersets.py:2161 -#: dcim/forms/model_forms.py:793 dcim/forms/model_forms.py:1024 -#: dcim/forms/model_forms.py:1438 dcim/forms/model_forms.py:1932 -#: dcim/forms/model_forms.py:2005 dcim/forms/object_create.py:207 -#: dcim/tables/connections.py:23 dcim/tables/connections.py:42 -#: dcim/tables/connections.py:61 dcim/tables/devices.py:293 -#: dcim/tables/devices.py:399 dcim/tables/devices.py:440 -#: dcim/tables/devices.py:482 dcim/tables/devices.py:532 -#: dcim/tables/devices.py:649 dcim/tables/devices.py:799 -#: dcim/tables/devices.py:852 dcim/tables/devices.py:905 -#: dcim/tables/devices.py:983 dcim/tables/devices.py:1057 -#: dcim/tables/devices.py:1183 dcim/tables/modules.py:84 -#: extras/forms/filtersets.py:410 ipam/forms/bulk_import.py:316 -#: ipam/forms/filtersets.py:664 ipam/forms/model_forms.py:349 -#: ipam/tables/vlans.py:160 templates/dcim/device_edit.html:12 -#: templates/dcim/panels/interface_connection.html:60 -#: templates/dcim/panels/virtual_chassis_members.html:8 -#: templates/dcim/virtualchassis_edit.html:63 -#: templates/wireless/panels/wirelesslink_interface.html:8 -#: virtualization/filtersets.py:212 virtualization/forms/bulk_edit.py:142 -#: virtualization/forms/bulk_import.py:138 -#: virtualization/forms/filtersets.py:190 -#: virtualization/forms/model_forms.py:223 -#: virtualization/tables/virtualmachines.py:81 vpn/choices.py:52 -#: vpn/forms/bulk_import.py:85 vpn/forms/bulk_import.py:288 -#: vpn/forms/filtersets.py:297 vpn/forms/model_forms.py:88 -#: vpn/forms/model_forms.py:123 vpn/forms/model_forms.py:234 -#: vpn/forms/model_forms.py:451 wireless/forms/model_forms.py:101 -#: wireless/forms/model_forms.py:143 wireless/tables/wirelesslan.py:74 +#: netbox/circuits/tables/virtual_circuits.py:106 +#: netbox/dcim/forms/bulk_edit.py:749 netbox/dcim/forms/bulk_edit.py:1320 +#: netbox/dcim/forms/bulk_edit.py:1732 netbox/dcim/forms/bulk_edit.py:1786 +#: netbox/dcim/forms/bulk_import.py:763 netbox/dcim/forms/bulk_import.py:824 +#: netbox/dcim/forms/bulk_import.py:850 netbox/dcim/forms/bulk_import.py:876 +#: netbox/dcim/forms/bulk_import.py:897 netbox/dcim/forms/bulk_import.py:953 +#: netbox/dcim/forms/bulk_import.py:1112 netbox/dcim/forms/bulk_import.py:1131 +#: netbox/dcim/forms/bulk_import.py:1150 netbox/dcim/forms/bulk_import.py:1168 +#: netbox/dcim/forms/bulk_import.py:1222 netbox/dcim/forms/bulk_import.py:1344 +#: netbox/dcim/forms/bulk_import.py:1810 netbox/dcim/forms/connections.py:34 +#: netbox/dcim/forms/filtersets.py:158 netbox/dcim/forms/filtersets.py:1054 +#: netbox/dcim/forms/filtersets.py:1091 netbox/dcim/forms/filtersets.py:1258 +#: netbox/dcim/forms/filtersets.py:1479 netbox/dcim/forms/filtersets.py:1502 +#: netbox/dcim/forms/filtersets.py:1519 netbox/dcim/forms/filtersets.py:1542 +#: netbox/dcim/forms/filtersets.py:1559 netbox/dcim/forms/filtersets.py:1577 +#: netbox/dcim/forms/filtersets.py:1594 netbox/dcim/forms/filtersets.py:1621 +#: netbox/dcim/forms/filtersets.py:1643 netbox/dcim/forms/filtersets.py:1765 +#: netbox/dcim/forms/filtersets.py:1810 netbox/dcim/forms/filtersets.py:1833 +#: netbox/dcim/forms/filtersets.py:1854 netbox/dcim/forms/filtersets.py:1876 +#: netbox/dcim/forms/filtersets.py:1897 netbox/dcim/forms/filtersets.py:1918 +#: netbox/dcim/forms/filtersets.py:1939 netbox/dcim/forms/filtersets.py:1956 +#: netbox/dcim/forms/filtersets.py:1976 netbox/dcim/forms/filtersets.py:2018 +#: netbox/dcim/forms/filtersets.py:2113 netbox/dcim/forms/filtersets.py:2137 +#: netbox/dcim/forms/filtersets.py:2161 netbox/dcim/forms/model_forms.py:793 +#: netbox/dcim/forms/model_forms.py:1024 netbox/dcim/forms/model_forms.py:1438 +#: netbox/dcim/forms/model_forms.py:1932 netbox/dcim/forms/model_forms.py:2005 +#: netbox/dcim/forms/object_create.py:207 netbox/dcim/tables/connections.py:23 +#: netbox/dcim/tables/connections.py:42 netbox/dcim/tables/connections.py:61 +#: netbox/dcim/tables/devices.py:293 netbox/dcim/tables/devices.py:399 +#: netbox/dcim/tables/devices.py:440 netbox/dcim/tables/devices.py:482 +#: netbox/dcim/tables/devices.py:532 netbox/dcim/tables/devices.py:649 +#: netbox/dcim/tables/devices.py:799 netbox/dcim/tables/devices.py:852 +#: netbox/dcim/tables/devices.py:905 netbox/dcim/tables/devices.py:983 +#: netbox/dcim/tables/devices.py:1057 netbox/dcim/tables/devices.py:1183 +#: netbox/dcim/tables/modules.py:84 netbox/extras/forms/filtersets.py:410 +#: netbox/ipam/forms/bulk_import.py:316 netbox/ipam/forms/filtersets.py:664 +#: netbox/ipam/forms/model_forms.py:349 netbox/ipam/tables/vlans.py:160 +#: netbox/templates/dcim/device_edit.html:12 +#: netbox/templates/dcim/panels/interface_connection.html:60 +#: netbox/templates/dcim/panels/virtual_chassis_members.html:8 +#: netbox/templates/dcim/virtualchassis_edit.html:63 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:8 +#: netbox/virtualization/filtersets.py:212 +#: netbox/virtualization/forms/bulk_edit.py:142 +#: netbox/virtualization/forms/bulk_import.py:138 +#: netbox/virtualization/forms/filtersets.py:190 +#: netbox/virtualization/forms/model_forms.py:223 +#: netbox/virtualization/tables/virtualmachines.py:81 netbox/vpn/choices.py:52 +#: netbox/vpn/forms/bulk_import.py:85 netbox/vpn/forms/bulk_import.py:288 +#: netbox/vpn/forms/filtersets.py:297 netbox/vpn/forms/model_forms.py:88 +#: netbox/vpn/forms/model_forms.py:123 netbox/vpn/forms/model_forms.py:234 +#: netbox/vpn/forms/model_forms.py:451 netbox/wireless/forms/model_forms.py:101 +#: netbox/wireless/forms/model_forms.py:143 +#: netbox/wireless/tables/wirelesslan.py:74 msgid "Device" msgstr "" -#: circuits/ui/panels.py:33 netbox/navigation/menu.py:309 +#: netbox/circuits/ui/panels.py:33 netbox/netbox/navigation/menu.py:309 msgid "Group Assignments" msgstr "" -#: circuits/ui/panels.py:42 ipam/ui/panels.py:36 -#: templates/ipam/inc/panels/fhrp_groups.html:15 +#: netbox/circuits/ui/panels.py:42 netbox/ipam/ui/panels.py:36 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:15 msgid "Assign Group" msgstr "" -#: circuits/ui/panels.py:61 -#: templates/circuits/inc/circuit_termination_fields.html:5 +#: netbox/circuits/ui/panels.py:61 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:5 msgid "Termination point" msgstr "" -#: circuits/ui/panels.py:65 dcim/forms/filtersets.py:1481 -#: dcim/forms/filtersets.py:1521 dcim/forms/filtersets.py:1561 -#: dcim/forms/filtersets.py:1596 dcim/forms/filtersets.py:1645 -#: dcim/tables/devices.py:381 dcim/tables/devices.py:693 dcim/ui/panels.py:394 -#: dcim/ui/panels.py:530 ipam/tables/vlans.py:178 -#: templates/circuits/inc/circuit_termination_fields.html:16 +#: netbox/circuits/ui/panels.py:65 netbox/dcim/forms/filtersets.py:1481 +#: netbox/dcim/forms/filtersets.py:1521 netbox/dcim/forms/filtersets.py:1561 +#: netbox/dcim/forms/filtersets.py:1596 netbox/dcim/forms/filtersets.py:1645 +#: netbox/dcim/tables/devices.py:381 netbox/dcim/tables/devices.py:693 +#: netbox/dcim/ui/panels.py:394 netbox/dcim/ui/panels.py:530 +#: netbox/ipam/tables/vlans.py:178 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:16 msgid "Connection" msgstr "" -#: circuits/ui/panels.py:70 dcim/forms/bulk_edit.py:1480 -#: dcim/forms/bulk_import.py:835 dcim/forms/bulk_import.py:861 -#: dcim/forms/filtersets.py:1490 dcim/forms/filtersets.py:1530 -#: dcim/forms/filtersets.py:1668 dcim/tables/devices.py:662 -#: dcim/ui/panels.py:488 -#: templates/circuits/inc/circuit_termination_fields.html:64 +#: netbox/circuits/ui/panels.py:70 netbox/dcim/forms/bulk_edit.py:1480 +#: netbox/dcim/forms/bulk_import.py:835 netbox/dcim/forms/bulk_import.py:861 +#: netbox/dcim/forms/filtersets.py:1490 netbox/dcim/forms/filtersets.py:1530 +#: netbox/dcim/forms/filtersets.py:1668 netbox/dcim/tables/devices.py:662 +#: netbox/dcim/ui/panels.py:488 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:64 msgid "Speed" msgstr "" -#: circuits/ui/panels.py:72 -#: templates/circuits/inc/circuit_termination_fields.html:77 +#: netbox/circuits/ui/panels.py:72 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:77 msgid "Cross-Connect" msgstr "" -#: circuits/ui/panels.py:73 -#: templates/circuits/inc/circuit_termination_fields.html:81 +#: netbox/circuits/ui/panels.py:73 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:81 msgid "Patch Panel/Port" msgstr "" -#: core/api/views.py:51 +#: netbox/core/api/views.py:51 msgid "This user does not have permission to synchronize this data source." msgstr "" -#: core/apps.py:35 +#: netbox/core/apps.py:35 msgid "Object created" msgstr "" -#: core/apps.py:36 +#: netbox/core/apps.py:36 msgid "Object updated" msgstr "" -#: core/apps.py:37 +#: netbox/core/apps.py:37 msgid "Object deleted" msgstr "" -#: core/apps.py:38 +#: netbox/core/apps.py:38 msgid "Job started" msgstr "" -#: core/apps.py:39 +#: netbox/core/apps.py:39 msgid "Job completed" msgstr "" -#: core/apps.py:40 +#: netbox/core/apps.py:40 msgid "Job failed" msgstr "" -#: core/apps.py:41 +#: netbox/core/apps.py:41 msgid "Job errored" msgstr "" -#: core/choices.py:18 +#: netbox/core/choices.py:18 msgid "New" msgstr "" -#: core/choices.py:19 core/constants.py:19 core/tables/tasks.py:16 -#: templates/core/rq_task.html:77 +#: netbox/core/choices.py:19 netbox/core/constants.py:19 +#: netbox/core/tables/tasks.py:16 netbox/templates/core/rq_task.html:77 msgid "Queued" msgstr "" -#: core/choices.py:20 +#: netbox/core/choices.py:20 msgid "Syncing" msgstr "" -#: core/choices.py:21 core/choices.py:57 core/tables/jobs.py:45 +#: netbox/core/choices.py:21 netbox/core/choices.py:57 +#: netbox/core/tables/jobs.py:45 msgid "Completed" msgstr "" -#: core/choices.py:22 core/choices.py:59 core/constants.py:21 -#: core/tables/tasks.py:35 dcim/choices.py:206 dcim/choices.py:259 -#: dcim/choices.py:2020 dcim/choices.py:2110 virtualization/choices.py:48 +#: netbox/core/choices.py:22 netbox/core/choices.py:59 +#: netbox/core/constants.py:21 netbox/core/tables/tasks.py:35 +#: netbox/dcim/choices.py:206 netbox/dcim/choices.py:259 +#: netbox/dcim/choices.py:2020 netbox/dcim/choices.py:2110 +#: netbox/virtualization/choices.py:48 msgid "Failed" msgstr "" -#: core/choices.py:35 netbox/navigation/menu.py:370 -#: netbox/navigation/menu.py:374 templates/extras/script/base.html:14 -#: templates/extras/script_list.html:7 templates/extras/script_list.html:12 -#: templates/extras/script_result.html:17 +#: netbox/core/choices.py:35 netbox/netbox/navigation/menu.py:370 +#: netbox/netbox/navigation/menu.py:374 +#: netbox/templates/extras/script/base.html:14 +#: netbox/templates/extras/script_list.html:7 +#: netbox/templates/extras/script_list.html:12 +#: netbox/templates/extras/script_result.html:17 msgid "Scripts" msgstr "" -#: core/choices.py:36 templates/extras/report/base.html:13 +#: netbox/core/choices.py:36 netbox/templates/extras/report/base.html:13 msgid "Reports" msgstr "" -#: core/choices.py:54 dcim/choices.py:154 +#: netbox/core/choices.py:54 netbox/dcim/choices.py:154 msgid "Pending" msgstr "" -#: core/choices.py:55 core/constants.py:24 core/tables/jobs.py:36 -#: core/tables/tasks.py:39 +#: netbox/core/choices.py:55 netbox/core/constants.py:24 +#: netbox/core/tables/jobs.py:36 netbox/core/tables/tasks.py:39 msgid "Scheduled" msgstr "" -#: core/choices.py:56 +#: netbox/core/choices.py:56 msgid "Running" msgstr "" -#: core/choices.py:58 +#: netbox/core/choices.py:58 msgid "Errored" msgstr "" -#: core/choices.py:81 extras/choices.py:66 +#: netbox/core/choices.py:81 netbox/extras/choices.py:66 msgid "Always" msgstr "" -#: core/choices.py:82 +#: netbox/core/choices.py:82 msgid "On failure" msgstr "" -#: core/choices.py:83 templates/extras/inc/script_list_content.html:63 +#: netbox/core/choices.py:83 +#: netbox/templates/extras/inc/script_list_content.html:63 msgid "Never" msgstr "" -#: core/choices.py:94 +#: netbox/core/choices.py:94 msgid "Minutely" msgstr "" -#: core/choices.py:95 +#: netbox/core/choices.py:95 msgid "Hourly" msgstr "" -#: core/choices.py:96 +#: netbox/core/choices.py:96 msgid "12 hours" msgstr "" -#: core/choices.py:97 +#: netbox/core/choices.py:97 msgid "Daily" msgstr "" -#: core/choices.py:98 +#: netbox/core/choices.py:98 msgid "Weekly" msgstr "" -#: core/choices.py:99 +#: netbox/core/choices.py:99 msgid "30 days" msgstr "" -#: core/choices.py:114 core/tables/jobs.py:33 core/tables/tasks.py:80 -#: extras/tables/tables.py:441 extras/tables/tables.py:752 -#: templates/core/configrevision.html:23 -#: templates/core/configrevision_restore.html:12 templates/core/rq_task.html:16 -#: templates/core/rq_task.html:73 templates/core/rq_worker.html:14 -#: templates/extras/htmx/script_result.html:12 templates/generic/object.html:65 -#: templates/htmx/quick_add_created.html:7 users/tables.py:37 +#: netbox/core/choices.py:114 netbox/core/tables/jobs.py:33 +#: netbox/core/tables/tasks.py:80 netbox/extras/tables/tables.py:441 +#: netbox/extras/tables/tables.py:752 +#: netbox/templates/core/configrevision.html:23 +#: netbox/templates/core/configrevision_restore.html:12 +#: netbox/templates/core/rq_task.html:16 netbox/templates/core/rq_task.html:73 +#: netbox/templates/core/rq_worker.html:14 +#: netbox/templates/extras/htmx/script_result.html:12 +#: netbox/templates/generic/object.html:65 +#: netbox/templates/htmx/quick_add_created.html:7 netbox/users/tables.py:37 msgid "Created" msgstr "" -#: core/choices.py:115 core/tables/plugins.py:69 +#: netbox/core/choices.py:115 netbox/core/tables/plugins.py:69 msgid "Updated" msgstr "" -#: core/choices.py:116 +#: netbox/core/choices.py:116 msgid "Deleted" msgstr "" -#: core/constants.py:20 core/tables/tasks.py:31 +#: netbox/core/constants.py:20 netbox/core/tables/tasks.py:31 msgid "Finished" msgstr "" -#: core/constants.py:22 core/tables/jobs.py:42 -#: templates/extras/htmx/script_result.html:8 +#: netbox/core/constants.py:22 netbox/core/tables/jobs.py:42 +#: netbox/templates/extras/htmx/script_result.html:8 msgid "Started" msgstr "" -#: core/constants.py:23 core/tables/tasks.py:27 +#: netbox/core/constants.py:23 netbox/core/tables/tasks.py:27 msgid "Deferred" msgstr "" -#: core/constants.py:25 +#: netbox/core/constants.py:25 msgid "Stopped" msgstr "" -#: core/constants.py:26 +#: netbox/core/constants.py:26 msgid "Cancelled" msgstr "" -#: core/constants.py:30 extras/choices.py:197 extras/forms/bulk_edit.py:403 -#: extras/forms/filtersets.py:549 extras/tables/tables.py:707 +#: netbox/core/constants.py:30 netbox/extras/choices.py:197 +#: netbox/extras/forms/bulk_edit.py:403 netbox/extras/forms/filtersets.py:549 +#: netbox/extras/tables/tables.py:707 msgid "Debug" msgstr "" -#: core/constants.py:31 extras/choices.py:177 extras/choices.py:198 +#: netbox/core/constants.py:31 netbox/extras/choices.py:177 +#: netbox/extras/choices.py:198 msgid "Info" msgstr "" -#: core/constants.py:32 extras/choices.py:179 extras/choices.py:200 +#: netbox/core/constants.py:32 netbox/extras/choices.py:179 +#: netbox/extras/choices.py:200 msgid "Warning" msgstr "" -#: core/constants.py:33 netbox/tables/columns.py:589 +#: netbox/core/constants.py:33 netbox/netbox/tables/columns.py:589 msgid "Error" msgstr "" -#: core/data_backends.py:46 core/tables/plugins.py:54 -#: templates/core/plugin.html:88 -#: templates/dcim/panels/interface_wireless.html:10 +#: netbox/core/data_backends.py:46 netbox/core/tables/plugins.py:54 +#: netbox/templates/core/plugin.html:88 +#: netbox/templates/dcim/panels/interface_wireless.html:10 msgid "Local" msgstr "" -#: core/data_backends.py:64 core/tables/change_logging.py:21 -#: templates/account/profile.html:13 users/tables.py:64 +#: netbox/core/data_backends.py:64 netbox/core/tables/change_logging.py:21 +#: netbox/templates/account/profile.html:13 netbox/users/tables.py:64 msgid "Username" msgstr "" -#: core/data_backends.py:66 core/data_backends.py:72 +#: netbox/core/data_backends.py:66 netbox/core/data_backends.py:72 msgid "Only used for cloning with HTTP(S)" msgstr "" -#: core/data_backends.py:70 templates/account/base.html:23 -#: templates/account/password.html:12 users/forms/model_forms.py:200 +#: netbox/core/data_backends.py:70 netbox/templates/account/base.html:23 +#: netbox/templates/account/password.html:12 +#: netbox/users/forms/model_forms.py:191 msgid "Password" msgstr "" -#: core/data_backends.py:76 +#: netbox/core/data_backends.py:76 msgid "Branch" msgstr "" -#: core/data_backends.py:136 +#: netbox/core/data_backends.py:136 #, python-brace-format msgid "Fetching remote data failed ({name}): {error}" msgstr "" -#: core/data_backends.py:149 +#: netbox/core/data_backends.py:149 msgid "AWS access key ID" msgstr "" -#: core/data_backends.py:153 +#: netbox/core/data_backends.py:153 msgid "AWS secret access key" msgstr "" -#: core/filtersets.py:65 extras/filtersets.py:295 extras/filtersets.py:665 -#: extras/filtersets.py:841 extras/filtersets.py:872 +#: netbox/core/filtersets.py:65 netbox/extras/filtersets.py:295 +#: netbox/extras/filtersets.py:665 netbox/extras/filtersets.py:841 +#: netbox/extras/filtersets.py:872 msgid "Data source (ID)" msgstr "" -#: core/filtersets.py:72 +#: netbox/core/filtersets.py:72 msgid "Data source (name)" msgstr "" -#: core/filtersets.py:200 dcim/filtersets.py:598 extras/filtersets.py:336 -#: extras/filtersets.py:392 extras/filtersets.py:440 extras/filtersets.py:464 -#: extras/filtersets.py:532 users/filtersets.py:31 users/filtersets.py:308 +#: netbox/core/filtersets.py:200 netbox/dcim/filtersets.py:598 +#: netbox/extras/filtersets.py:336 netbox/extras/filtersets.py:392 +#: netbox/extras/filtersets.py:440 netbox/extras/filtersets.py:464 +#: netbox/extras/filtersets.py:532 netbox/users/filtersets.py:31 +#: netbox/users/filtersets.py:308 msgid "User (ID)" msgstr "" -#: core/filtersets.py:207 +#: netbox/core/filtersets.py:207 msgid "User name" msgstr "" -#: core/forms/bulk_edit.py:25 core/forms/filtersets.py:47 -#: core/tables/data.py:28 dcim/choices.py:2068 dcim/forms/bulk_edit.py:1151 -#: dcim/forms/bulk_edit.py:1255 dcim/forms/bulk_edit.py:1278 -#: dcim/forms/bulk_edit.py:1442 dcim/forms/filtersets.py:1680 -#: dcim/forms/filtersets.py:1773 dcim/forms/filtersets.py:1906 -#: dcim/forms/filtersets.py:1925 dcim/forms/filtersets.py:1944 -#: dcim/forms/filtersets.py:1959 dcim/tables/devices.py:592 -#: dcim/tables/devices.py:912 dcim/tables/devices.py:967 -#: dcim/tables/devices.py:990 dcim/tables/devices.py:1040 -#: dcim/tables/devicetypes.py:233 dcim/tables/devicetypes.py:293 -#: dcim/tables/devicetypes.py:307 extras/forms/bulk_edit.py:134 -#: extras/forms/bulk_edit.py:202 extras/forms/bulk_edit.py:230 -#: extras/forms/bulk_edit.py:289 extras/forms/filtersets.py:161 -#: extras/forms/filtersets.py:257 extras/forms/filtersets.py:288 -#: extras/forms/filtersets.py:353 extras/tables/tables.py:192 -#: extras/tables/tables.py:323 extras/tables/tables.py:360 -#: extras/tables/tables.py:526 netbox/preferences.py:46 -#: netbox/preferences.py:71 users/forms/bulk_edit.py:87 -#: users/forms/bulk_edit.py:105 users/forms/filtersets.py:67 -#: users/forms/filtersets.py:133 users/tables.py:30 users/tables.py:113 -#: virtualization/forms/bulk_edit.py:226 virtualization/forms/filtersets.py:285 +#: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:47 +#: netbox/core/tables/data.py:28 netbox/dcim/choices.py:2068 +#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1278 netbox/dcim/forms/bulk_edit.py:1442 +#: netbox/dcim/forms/filtersets.py:1680 netbox/dcim/forms/filtersets.py:1773 +#: netbox/dcim/forms/filtersets.py:1906 netbox/dcim/forms/filtersets.py:1925 +#: netbox/dcim/forms/filtersets.py:1944 netbox/dcim/forms/filtersets.py:1959 +#: netbox/dcim/tables/devices.py:592 netbox/dcim/tables/devices.py:912 +#: netbox/dcim/tables/devices.py:967 netbox/dcim/tables/devices.py:990 +#: netbox/dcim/tables/devices.py:1040 netbox/dcim/tables/devicetypes.py:233 +#: netbox/dcim/tables/devicetypes.py:293 netbox/dcim/tables/devicetypes.py:307 +#: netbox/extras/forms/bulk_edit.py:134 netbox/extras/forms/bulk_edit.py:202 +#: netbox/extras/forms/bulk_edit.py:230 netbox/extras/forms/bulk_edit.py:289 +#: netbox/extras/forms/filtersets.py:161 netbox/extras/forms/filtersets.py:257 +#: netbox/extras/forms/filtersets.py:288 netbox/extras/forms/filtersets.py:353 +#: netbox/extras/tables/tables.py:192 netbox/extras/tables/tables.py:323 +#: netbox/extras/tables/tables.py:360 netbox/extras/tables/tables.py:526 +#: netbox/netbox/preferences.py:46 netbox/netbox/preferences.py:71 +#: netbox/users/forms/bulk_edit.py:87 netbox/users/forms/bulk_edit.py:105 +#: netbox/users/forms/filtersets.py:67 netbox/users/forms/filtersets.py:133 +#: netbox/users/tables.py:30 netbox/users/tables.py:113 +#: netbox/virtualization/forms/bulk_edit.py:230 +#: netbox/virtualization/forms/filtersets.py:285 msgid "Enabled" msgstr "" -#: core/forms/bulk_edit.py:30 core/forms/filtersets.py:54 -#: core/tables/data.py:31 core/ui/panels.py:12 +#: netbox/core/forms/bulk_edit.py:30 netbox/core/forms/filtersets.py:54 +#: netbox/core/tables/data.py:31 netbox/core/ui/panels.py:12 msgid "Sync interval" msgstr "" -#: core/forms/bulk_edit.py:33 extras/forms/model_forms.py:388 -#: extras/views.py:394 vpn/forms/filtersets.py:107 vpn/forms/filtersets.py:138 -#: vpn/forms/filtersets.py:163 vpn/forms/filtersets.py:183 -#: vpn/forms/model_forms.py:299 vpn/forms/model_forms.py:320 -#: vpn/forms/model_forms.py:336 vpn/forms/model_forms.py:357 -#: vpn/forms/model_forms.py:379 +#: netbox/core/forms/bulk_edit.py:33 netbox/extras/forms/model_forms.py:388 +#: netbox/extras/views.py:394 netbox/vpn/forms/filtersets.py:107 +#: netbox/vpn/forms/filtersets.py:138 netbox/vpn/forms/filtersets.py:163 +#: netbox/vpn/forms/filtersets.py:183 netbox/vpn/forms/model_forms.py:299 +#: netbox/vpn/forms/model_forms.py:320 netbox/vpn/forms/model_forms.py:336 +#: netbox/vpn/forms/model_forms.py:357 netbox/vpn/forms/model_forms.py:379 msgid "Parameters" msgstr "" -#: core/forms/bulk_edit.py:37 core/ui/panels.py:22 +#: netbox/core/forms/bulk_edit.py:37 netbox/core/ui/panels.py:22 msgid "Ignore rules" msgstr "" -#: core/forms/filtersets.py:33 core/forms/model_forms.py:100 -#: core/ui/panels.py:7 extras/forms/model_forms.py:349 -#: extras/forms/model_forms.py:682 extras/forms/model_forms.py:771 -#: extras/forms/model_forms.py:824 extras/tables/tables.py:234 -#: extras/tables/tables.py:606 extras/tables/tables.py:636 -#: extras/tables/tables.py:678 templates/core/inc/datafile_panel.html:7 -#: templates/extras/object_render_config.html:19 +#: netbox/core/forms/filtersets.py:33 netbox/core/forms/model_forms.py:100 +#: netbox/core/ui/panels.py:7 netbox/extras/forms/model_forms.py:349 +#: netbox/extras/forms/model_forms.py:682 +#: netbox/extras/forms/model_forms.py:771 +#: netbox/extras/forms/model_forms.py:824 netbox/extras/tables/tables.py:234 +#: netbox/extras/tables/tables.py:606 netbox/extras/tables/tables.py:636 +#: netbox/extras/tables/tables.py:678 +#: netbox/templates/core/inc/datafile_panel.html:7 +#: netbox/templates/extras/object_render_config.html:19 msgid "Data Source" msgstr "" -#: core/forms/filtersets.py:65 core/forms/mixins.py:21 extras/ui/panels.py:492 +#: netbox/core/forms/filtersets.py:65 netbox/core/forms/mixins.py:21 +#: netbox/extras/ui/panels.py:492 msgid "File" msgstr "" -#: core/forms/filtersets.py:70 core/forms/mixins.py:16 -#: extras/forms/bulk_import.py:201 extras/forms/filtersets.py:191 -#: extras/forms/filtersets.py:391 extras/forms/filtersets.py:423 -#: extras/forms/filtersets.py:511 +#: netbox/core/forms/filtersets.py:70 netbox/core/forms/mixins.py:16 +#: netbox/extras/forms/bulk_import.py:201 netbox/extras/forms/filtersets.py:191 +#: netbox/extras/forms/filtersets.py:391 netbox/extras/forms/filtersets.py:423 +#: netbox/extras/forms/filtersets.py:511 msgid "Data source" msgstr "" -#: core/forms/filtersets.py:81 extras/forms/filtersets.py:571 +#: netbox/core/forms/filtersets.py:81 netbox/extras/forms/filtersets.py:571 msgid "Creation" msgstr "" -#: core/forms/filtersets.py:85 core/forms/filtersets.py:175 -#: extras/forms/filtersets.py:592 extras/tables/tables.py:287 -#: extras/tables/tables.py:354 extras/tables/tables.py:380 -#: extras/tables/tables.py:399 extras/tables/tables.py:432 -#: extras/tables/tables.py:757 tenancy/tables/contacts.py:84 -#: vpn/tables/l2vpn.py:59 +#: netbox/core/forms/filtersets.py:85 netbox/core/forms/filtersets.py:175 +#: netbox/extras/forms/filtersets.py:592 netbox/extras/tables/tables.py:287 +#: netbox/extras/tables/tables.py:354 netbox/extras/tables/tables.py:380 +#: netbox/extras/tables/tables.py:399 netbox/extras/tables/tables.py:432 +#: netbox/extras/tables/tables.py:757 netbox/tenancy/tables/contacts.py:84 +#: netbox/vpn/tables/l2vpn.py:59 msgid "Object Type" msgstr "" -#: core/forms/filtersets.py:95 core/tables/jobs.py:48 core/ui/panels.py:65 -#: templates/core/rq_task.html:61 +#: netbox/core/forms/filtersets.py:95 netbox/core/tables/jobs.py:48 +#: netbox/core/ui/panels.py:65 netbox/templates/core/rq_task.html:61 msgid "Queue" msgstr "" -#: core/forms/filtersets.py:99 +#: netbox/core/forms/filtersets.py:99 msgid "Created after" msgstr "" -#: core/forms/filtersets.py:104 +#: netbox/core/forms/filtersets.py:104 msgid "Created before" msgstr "" -#: core/forms/filtersets.py:109 +#: netbox/core/forms/filtersets.py:109 msgid "Scheduled after" msgstr "" -#: core/forms/filtersets.py:114 +#: netbox/core/forms/filtersets.py:114 msgid "Scheduled before" msgstr "" -#: core/forms/filtersets.py:119 +#: netbox/core/forms/filtersets.py:119 msgid "Started after" msgstr "" -#: core/forms/filtersets.py:124 +#: netbox/core/forms/filtersets.py:124 msgid "Started before" msgstr "" -#: core/forms/filtersets.py:129 +#: netbox/core/forms/filtersets.py:129 msgid "Completed after" msgstr "" -#: core/forms/filtersets.py:134 +#: netbox/core/forms/filtersets.py:134 msgid "Completed before" msgstr "" -#: core/forms/filtersets.py:141 core/forms/filtersets.py:170 -#: core/ui/panels.py:73 dcim/forms/bulk_edit.py:481 -#: dcim/forms/filtersets.py:535 dcim/forms/model_forms.py:381 -#: extras/forms/filtersets.py:587 extras/forms/filtersets.py:607 -#: extras/tables/tables.py:407 extras/tables/tables.py:448 -#: templates/inc/user_menu.html:31 users/filtersets.py:135 -#: users/filtersets.py:217 users/forms/filtersets.py:81 -#: users/forms/filtersets.py:126 users/forms/model_forms.py:182 -#: users/forms/model_forms.py:222 users/tables.py:22 +#: netbox/core/forms/filtersets.py:141 netbox/core/forms/filtersets.py:170 +#: netbox/core/ui/panels.py:73 netbox/dcim/forms/bulk_edit.py:481 +#: netbox/dcim/forms/filtersets.py:535 netbox/dcim/forms/model_forms.py:381 +#: netbox/extras/forms/filtersets.py:587 netbox/extras/forms/filtersets.py:607 +#: netbox/extras/tables/tables.py:407 netbox/extras/tables/tables.py:448 +#: netbox/templates/inc/user_menu.html:31 netbox/users/filtersets.py:135 +#: netbox/users/filtersets.py:217 netbox/users/forms/filtersets.py:81 +#: netbox/users/forms/filtersets.py:126 netbox/users/forms/model_forms.py:173 +#: netbox/users/forms/model_forms.py:213 netbox/users/tables.py:22 msgid "User" msgstr "" -#: core/forms/filtersets.py:149 core/tables/change_logging.py:16 -#: core/tables/jobs.py:74 extras/tables/tables.py:795 -#: extras/tables/tables.py:850 +#: netbox/core/forms/filtersets.py:149 netbox/core/tables/change_logging.py:16 +#: netbox/core/tables/jobs.py:74 netbox/extras/tables/tables.py:795 +#: netbox/extras/tables/tables.py:850 msgid "Time" msgstr "" -#: core/forms/filtersets.py:154 extras/forms/filtersets.py:576 +#: netbox/core/forms/filtersets.py:154 netbox/extras/forms/filtersets.py:576 msgid "After" msgstr "" -#: core/forms/filtersets.py:159 extras/forms/filtersets.py:581 +#: netbox/core/forms/filtersets.py:159 netbox/extras/forms/filtersets.py:581 msgid "Before" msgstr "" -#: core/forms/filtersets.py:163 core/tables/change_logging.py:30 -#: extras/forms/model_forms.py:559 extras/ui/panels.py:375 +#: netbox/core/forms/filtersets.py:163 netbox/core/tables/change_logging.py:30 +#: netbox/extras/forms/model_forms.py:559 netbox/extras/ui/panels.py:375 msgid "Action" msgstr "" -#: core/forms/model_forms.py:55 core/tables/data.py:57 -#: templates/extras/report/base.html:33 templates/extras/script/base.html:32 +#: netbox/core/forms/model_forms.py:55 netbox/core/tables/data.py:57 +#: netbox/templates/extras/report/base.html:33 +#: netbox/templates/extras/script/base.html:32 msgid "Source" msgstr "" -#: core/forms/model_forms.py:57 templates/core/datasource.html:10 -#: templates/core/datasource.html:16 utilities/templatetags/buttons.py:156 +#: netbox/core/forms/model_forms.py:57 netbox/templates/core/datasource.html:10 +#: netbox/templates/core/datasource.html:16 +#: netbox/utilities/templatetags/buttons.py:156 msgid "Sync" msgstr "" -#: core/forms/model_forms.py:61 +#: netbox/core/forms/model_forms.py:61 msgid "Backend Parameters" msgstr "" -#: core/forms/model_forms.py:99 +#: netbox/core/forms/model_forms.py:99 msgid "File Upload" msgstr "" -#: core/forms/model_forms.py:111 +#: netbox/core/forms/model_forms.py:111 msgid "Cannot upload a file and sync from an existing file" msgstr "" -#: core/forms/model_forms.py:113 +#: netbox/core/forms/model_forms.py:113 msgid "Must upload a file or select a data file to sync" msgstr "" -#: core/forms/model_forms.py:156 templates/dcim/rack_elevation_list.html:6 +#: netbox/core/forms/model_forms.py:156 +#: netbox/templates/dcim/rack_elevation_list.html:6 msgid "Rack Elevations" msgstr "" -#: core/forms/model_forms.py:160 dcim/choices.py:1939 -#: dcim/forms/bulk_edit.py:990 dcim/forms/bulk_edit.py:1396 -#: dcim/forms/bulk_edit.py:1417 dcim/tables/racks.py:172 -#: netbox/navigation/menu.py:324 netbox/navigation/menu.py:328 +#: netbox/core/forms/model_forms.py:160 netbox/dcim/choices.py:1939 +#: netbox/dcim/forms/bulk_edit.py:990 netbox/dcim/forms/bulk_edit.py:1396 +#: netbox/dcim/forms/bulk_edit.py:1417 netbox/dcim/tables/racks.py:172 +#: netbox/netbox/navigation/menu.py:324 netbox/netbox/navigation/menu.py:328 msgid "Power" msgstr "" -#: core/forms/model_forms.py:162 netbox/navigation/menu.py:171 -#: templates/core/inc/config_data.html:37 +#: netbox/core/forms/model_forms.py:162 netbox/netbox/navigation/menu.py:171 +#: netbox/templates/core/inc/config_data.html:37 msgid "IPAM" msgstr "" -#: core/forms/model_forms.py:163 netbox/navigation/menu.py:249 -#: templates/core/inc/config_data.html:50 vpn/forms/bulk_edit.py:65 -#: vpn/forms/filtersets.py:51 vpn/forms/model_forms.py:59 -#: vpn/forms/model_forms.py:144 +#: netbox/core/forms/model_forms.py:163 netbox/netbox/navigation/menu.py:249 +#: netbox/templates/core/inc/config_data.html:50 +#: netbox/vpn/forms/bulk_edit.py:65 netbox/vpn/forms/filtersets.py:51 +#: netbox/vpn/forms/model_forms.py:59 netbox/vpn/forms/model_forms.py:144 msgid "Security" msgstr "" -#: core/forms/model_forms.py:164 templates/core/inc/config_data.html:59 +#: netbox/core/forms/model_forms.py:164 +#: netbox/templates/core/inc/config_data.html:59 msgid "Banners" msgstr "" -#: core/forms/model_forms.py:165 templates/core/inc/config_data.html:80 +#: netbox/core/forms/model_forms.py:165 +#: netbox/templates/core/inc/config_data.html:80 msgid "Pagination" msgstr "" -#: core/forms/model_forms.py:166 extras/forms/bulk_edit.py:102 -#: extras/forms/filtersets.py:51 extras/forms/model_forms.py:132 -#: extras/forms/model_forms.py:145 extras/forms/model_forms.py:156 -#: templates/core/inc/config_data.html:93 +#: netbox/core/forms/model_forms.py:166 netbox/extras/forms/bulk_edit.py:102 +#: netbox/extras/forms/filtersets.py:51 netbox/extras/forms/model_forms.py:132 +#: netbox/extras/forms/model_forms.py:145 +#: netbox/extras/forms/model_forms.py:156 +#: netbox/templates/core/inc/config_data.html:93 msgid "Validation" msgstr "" -#: core/forms/model_forms.py:167 templates/account/preferences.html:6 +#: netbox/core/forms/model_forms.py:167 +#: netbox/templates/account/preferences.html:6 msgid "User Preferences" msgstr "" -#: core/forms/model_forms.py:168 netbox/navigation/menu.py:410 -#: templates/core/objectchange.html:7 templates/core/objectchange_list.html:4 +#: netbox/core/forms/model_forms.py:168 netbox/netbox/navigation/menu.py:410 +#: netbox/templates/core/objectchange.html:7 +#: netbox/templates/core/objectchange_list.html:4 msgid "Change Log" msgstr "" -#: core/forms/model_forms.py:171 dcim/forms/filtersets.py:867 -#: templates/core/inc/config_data.html:140 users/forms/model_forms.py:77 +#: netbox/core/forms/model_forms.py:171 netbox/dcim/forms/filtersets.py:867 +#: netbox/templates/core/inc/config_data.html:140 +#: netbox/users/forms/model_forms.py:77 msgid "Miscellaneous" msgstr "" -#: core/forms/model_forms.py:173 +#: netbox/core/forms/model_forms.py:173 msgid "Config Revision" msgstr "" -#: core/forms/model_forms.py:212 +#: netbox/core/forms/model_forms.py:212 msgid "This parameter has been defined statically and cannot be modified." msgstr "" -#: core/forms/model_forms.py:220 +#: netbox/core/forms/model_forms.py:220 #, python-brace-format msgid "Current value: {value}" msgstr "" -#: core/forms/model_forms.py:222 +#: netbox/core/forms/model_forms.py:222 msgid " (default)" msgstr "" -#: core/models/change_logging.py:28 +#: netbox/core/models/change_logging.py:28 msgid "time" msgstr "" -#: core/models/change_logging.py:41 +#: netbox/core/models/change_logging.py:41 msgid "user name" msgstr "" -#: core/models/change_logging.py:46 +#: netbox/core/models/change_logging.py:46 msgid "request ID" msgstr "" -#: core/models/change_logging.py:51 +#: netbox/core/models/change_logging.py:51 msgid "action" msgstr "" -#: core/models/change_logging.py:85 +#: netbox/core/models/change_logging.py:85 msgid "message" msgstr "" -#: core/models/change_logging.py:91 +#: netbox/core/models/change_logging.py:91 msgid "pre-change data" msgstr "" -#: core/models/change_logging.py:97 +#: netbox/core/models/change_logging.py:97 msgid "post-change data" msgstr "" -#: core/models/change_logging.py:111 +#: netbox/core/models/change_logging.py:111 msgid "object change" msgstr "" -#: core/models/change_logging.py:112 +#: netbox/core/models/change_logging.py:112 msgid "object changes" msgstr "" -#: core/models/change_logging.py:128 +#: netbox/core/models/change_logging.py:128 #, python-brace-format msgid "Change logging is not supported for this object type ({type})." msgstr "" -#: core/models/config.py:22 core/models/data.py:290 core/models/files.py:30 -#: core/models/jobs.py:60 extras/models/models.py:864 -#: extras/models/notifications.py:39 extras/models/notifications.py:196 -#: netbox/models/features.py:63 users/models/tokens.py:51 +#: netbox/core/models/config.py:22 netbox/core/models/data.py:290 +#: netbox/core/models/files.py:30 netbox/core/models/jobs.py:60 +#: netbox/extras/models/models.py:864 netbox/extras/models/notifications.py:39 +#: netbox/extras/models/notifications.py:196 +#: netbox/netbox/models/features.py:63 netbox/users/models/tokens.py:51 msgid "created" msgstr "" -#: core/models/config.py:26 +#: netbox/core/models/config.py:26 msgid "comment" msgstr "" -#: core/models/config.py:33 +#: netbox/core/models/config.py:33 msgid "configuration data" msgstr "" -#: core/models/config.py:43 +#: netbox/core/models/config.py:43 msgid "config revision" msgstr "" -#: core/models/config.py:44 +#: netbox/core/models/config.py:44 msgid "config revisions" msgstr "" -#: core/models/config.py:55 +#: netbox/core/models/config.py:55 msgid "Default configuration" msgstr "" -#: core/models/config.py:57 +#: netbox/core/models/config.py:57 msgid "Current configuration" msgstr "" -#: core/models/config.py:58 +#: netbox/core/models/config.py:58 #, python-brace-format msgid "Config revision #{id}" msgstr "" -#: core/models/data.py:45 dcim/models/cables.py:79 -#: dcim/models/device_component_templates.py:220 -#: dcim/models/device_component_templates.py:255 -#: dcim/models/device_component_templates.py:291 -#: dcim/models/device_component_templates.py:356 -#: dcim/models/device_component_templates.py:447 -#: dcim/models/device_component_templates.py:601 -#: dcim/models/device_component_templates.py:674 -#: dcim/models/device_components.py:425 dcim/models/device_components.py:452 -#: dcim/models/device_components.py:483 dcim/models/device_components.py:625 -#: dcim/models/device_components.py:843 dcim/models/device_components.py:1226 -#: dcim/models/device_components.py:1274 dcim/models/power.py:101 -#: extras/models/customfields.py:105 extras/models/search.py:42 -#: virtualization/models/clusters.py:57 -#: virtualization/models/virtualmachines.py:121 vpn/models/l2vpn.py:31 +#: netbox/core/models/data.py:45 netbox/dcim/models/cables.py:79 +#: netbox/dcim/models/device_component_templates.py:220 +#: netbox/dcim/models/device_component_templates.py:255 +#: netbox/dcim/models/device_component_templates.py:291 +#: netbox/dcim/models/device_component_templates.py:356 +#: netbox/dcim/models/device_component_templates.py:447 +#: netbox/dcim/models/device_component_templates.py:601 +#: netbox/dcim/models/device_component_templates.py:674 +#: netbox/dcim/models/device_components.py:425 +#: netbox/dcim/models/device_components.py:452 +#: netbox/dcim/models/device_components.py:483 +#: netbox/dcim/models/device_components.py:625 +#: netbox/dcim/models/device_components.py:843 +#: netbox/dcim/models/device_components.py:1226 +#: netbox/dcim/models/device_components.py:1274 netbox/dcim/models/power.py:101 +#: netbox/extras/models/customfields.py:105 netbox/extras/models/search.py:42 +#: netbox/virtualization/models/clusters.py:57 +#: netbox/virtualization/models/virtualmachines.py:121 +#: netbox/vpn/models/l2vpn.py:31 msgid "type" msgstr "" -#: core/models/data.py:50 core/ui/panels.py:17 extras/choices.py:37 -#: extras/models/models.py:187 extras/tables/tables.py:860 -#: templates/core/plugin.html:66 +#: netbox/core/models/data.py:50 netbox/core/ui/panels.py:17 +#: netbox/extras/choices.py:37 netbox/extras/models/models.py:187 +#: netbox/extras/tables/tables.py:860 netbox/templates/core/plugin.html:66 msgid "URL" msgstr "" -#: core/models/data.py:60 dcim/models/device_component_templates.py:452 -#: dcim/models/device_component_templates.py:744 -#: dcim/models/device_component_templates.py:779 -#: dcim/models/device_components.py:680 dcim/models/device_components.py:1336 -#: dcim/models/device_components.py:1401 extras/models/models.py:81 -#: extras/models/models.py:323 extras/models/models.py:511 -#: extras/models/models.py:593 users/models/permissions.py:32 -#: users/models/tokens.py:65 +#: netbox/core/models/data.py:60 +#: netbox/dcim/models/device_component_templates.py:452 +#: netbox/dcim/models/device_component_templates.py:744 +#: netbox/dcim/models/device_component_templates.py:779 +#: netbox/dcim/models/device_components.py:680 +#: netbox/dcim/models/device_components.py:1336 +#: netbox/dcim/models/device_components.py:1401 +#: netbox/extras/models/models.py:81 netbox/extras/models/models.py:323 +#: netbox/extras/models/models.py:511 netbox/extras/models/models.py:593 +#: netbox/users/models/permissions.py:32 netbox/users/models/tokens.py:65 msgid "enabled" msgstr "" -#: core/models/data.py:64 +#: netbox/core/models/data.py:64 msgid "sync interval" msgstr "" -#: core/models/data.py:70 +#: netbox/core/models/data.py:70 msgid "ignore rules" msgstr "" -#: core/models/data.py:72 +#: netbox/core/models/data.py:72 msgid "Patterns (one per line) matching files or paths to ignore when syncing" msgstr "" -#: core/models/data.py:75 extras/models/models.py:519 +#: netbox/core/models/data.py:75 netbox/extras/models/models.py:519 msgid "parameters" msgstr "" -#: core/models/data.py:80 +#: netbox/core/models/data.py:80 msgid "last synced" msgstr "" -#: core/models/data.py:88 +#: netbox/core/models/data.py:88 msgid "data source" msgstr "" -#: core/models/data.py:89 +#: netbox/core/models/data.py:89 msgid "data sources" msgstr "" -#: core/models/data.py:130 +#: netbox/core/models/data.py:130 #, python-brace-format msgid "Unknown backend type: {type}" msgstr "" -#: core/models/data.py:136 +#: netbox/core/models/data.py:136 #, python-brace-format msgid "URLs for local sources must start with {scheme} (or specify no scheme)" msgstr "" -#: core/models/data.py:187 +#: netbox/core/models/data.py:187 msgid "Cannot initiate sync; syncing already in progress." msgstr "" -#: core/models/data.py:200 +#: netbox/core/models/data.py:200 msgid "" "There was an error initializing the backend. A dependency needs to be " "installed: " msgstr "" -#: core/models/data.py:294 core/models/files.py:34 netbox/models/features.py:69 +#: netbox/core/models/data.py:294 netbox/core/models/files.py:34 +#: netbox/netbox/models/features.py:69 msgid "last updated" msgstr "" -#: core/models/data.py:304 dcim/models/cables.py:713 +#: netbox/core/models/data.py:304 netbox/dcim/models/cables.py:713 msgid "path" msgstr "" -#: core/models/data.py:307 +#: netbox/core/models/data.py:307 msgid "File path relative to the data source's root" msgstr "" -#: core/models/data.py:311 ipam/models/ip.py:535 -#: virtualization/models/virtualmachines.py:570 +#: netbox/core/models/data.py:311 netbox/ipam/models/ip.py:535 +#: netbox/virtualization/models/virtualmachines.py:570 msgid "size" msgstr "" -#: core/models/data.py:314 +#: netbox/core/models/data.py:314 msgid "hash" msgstr "" -#: core/models/data.py:318 +#: netbox/core/models/data.py:318 msgid "Length must be 64 hexadecimal characters." msgstr "" -#: core/models/data.py:320 +#: netbox/core/models/data.py:320 msgid "SHA256 hash of the file data" msgstr "" -#: core/models/data.py:334 +#: netbox/core/models/data.py:334 msgid "data file" msgstr "" -#: core/models/data.py:335 +#: netbox/core/models/data.py:335 msgid "data files" msgstr "" -#: core/models/data.py:408 +#: netbox/core/models/data.py:408 msgid "auto sync record" msgstr "" -#: core/models/data.py:409 +#: netbox/core/models/data.py:409 msgid "auto sync records" msgstr "" -#: core/models/files.py:40 +#: netbox/core/models/files.py:40 msgid "file root" msgstr "" -#: core/models/files.py:45 +#: netbox/core/models/files.py:45 msgid "file path" msgstr "" -#: core/models/files.py:47 +#: netbox/core/models/files.py:47 msgid "File path relative to the designated root path" msgstr "" -#: core/models/files.py:61 +#: netbox/core/models/files.py:61 msgid "managed file" msgstr "" -#: core/models/files.py:62 +#: netbox/core/models/files.py:62 msgid "managed files" msgstr "" -#: core/models/files.py:109 +#: netbox/core/models/files.py:109 #, python-brace-format msgid "A {model} with this file path already exists ({path})." msgstr "" -#: core/models/jobs.py:64 +#: netbox/core/models/jobs.py:64 msgid "scheduled" msgstr "" -#: core/models/jobs.py:69 +#: netbox/core/models/jobs.py:69 msgid "interval" msgstr "" -#: core/models/jobs.py:75 +#: netbox/core/models/jobs.py:75 msgid "Recurrence interval (in minutes)" msgstr "" -#: core/models/jobs.py:78 +#: netbox/core/models/jobs.py:78 msgid "started" msgstr "" -#: core/models/jobs.py:83 +#: netbox/core/models/jobs.py:83 msgid "completed" msgstr "" -#: core/models/jobs.py:101 extras/models/models.py:112 +#: netbox/core/models/jobs.py:101 netbox/extras/models/models.py:112 msgid "data" msgstr "" -#: core/models/jobs.py:107 +#: netbox/core/models/jobs.py:107 msgid "error" msgstr "" -#: core/models/jobs.py:112 +#: netbox/core/models/jobs.py:112 msgid "job ID" msgstr "" -#: core/models/jobs.py:116 +#: netbox/core/models/jobs.py:116 msgid "queue name" msgstr "" -#: core/models/jobs.py:119 +#: netbox/core/models/jobs.py:119 msgid "Name of the queue in which this job was enqueued" msgstr "" -#: core/models/jobs.py:122 extras/models/notifications.py:86 +#: netbox/core/models/jobs.py:122 netbox/extras/models/notifications.py:86 msgid "notifications" msgstr "" -#: core/models/jobs.py:128 +#: netbox/core/models/jobs.py:128 msgid "log entries" msgstr "" -#: core/models/jobs.py:145 +#: netbox/core/models/jobs.py:145 msgid "job" msgstr "" -#: core/models/jobs.py:146 +#: netbox/core/models/jobs.py:146 msgid "jobs" msgstr "" -#: core/models/jobs.py:176 +#: netbox/core/models/jobs.py:176 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "" -#: core/models/jobs.py:234 +#: netbox/core/models/jobs.py:234 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" -#: core/models/jobs.py:298 +#: netbox/core/models/jobs.py:298 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" -#: core/models/object_types.py:204 +#: netbox/core/models/object_types.py:204 msgid "object type" msgstr "" -#: core/models/object_types.py:205 extras/models/models.py:63 +#: netbox/core/models/object_types.py:205 netbox/extras/models/models.py:63 msgid "object types" msgstr "" -#: core/object_actions.py:15 +#: netbox/core/object_actions.py:15 msgid "Sync Data" msgstr "" -#: core/signals.py:178 +#: netbox/core/signals.py:178 #, python-brace-format msgid "Deletion is prevented by a protection rule: {message}" msgstr "" -#: core/tables/change_logging.py:26 templates/account/profile.html:17 +#: netbox/core/tables/change_logging.py:26 +#: netbox/templates/account/profile.html:17 msgid "Full Name" msgstr "" -#: core/tables/change_logging.py:38 core/tables/jobs.py:25 core/ui/panels.py:83 -#: extras/choices.py:41 extras/tables/tables.py:290 extras/tables/tables.py:383 -#: extras/tables/tables.py:402 extras/tables/tables.py:435 -#: extras/tables/tables.py:518 extras/tables/tables.py:589 -#: extras/tables/tables.py:762 extras/tables/tables.py:803 -#: extras/tables/tables.py:857 extras/ui/panels.py:378 extras/ui/panels.py:507 -#: netbox/tables/tables.py:362 tenancy/tables/contacts.py:87 -#: vpn/tables/l2vpn.py:64 +#: netbox/core/tables/change_logging.py:38 netbox/core/tables/jobs.py:25 +#: netbox/core/ui/panels.py:83 netbox/extras/choices.py:41 +#: netbox/extras/tables/tables.py:290 netbox/extras/tables/tables.py:383 +#: netbox/extras/tables/tables.py:402 netbox/extras/tables/tables.py:435 +#: netbox/extras/tables/tables.py:518 netbox/extras/tables/tables.py:589 +#: netbox/extras/tables/tables.py:762 netbox/extras/tables/tables.py:803 +#: netbox/extras/tables/tables.py:857 netbox/extras/ui/panels.py:378 +#: netbox/extras/ui/panels.py:507 netbox/netbox/tables/tables.py:362 +#: netbox/tenancy/tables/contacts.py:87 netbox/vpn/tables/l2vpn.py:64 msgid "Object" msgstr "" -#: core/tables/change_logging.py:43 core/ui/panels.py:89 +#: netbox/core/tables/change_logging.py:43 netbox/core/ui/panels.py:89 msgid "Request ID" msgstr "" -#: core/tables/change_logging.py:46 core/tables/jobs.py:81 -#: extras/tables/tables.py:806 extras/tables/tables.py:863 +#: netbox/core/tables/change_logging.py:46 netbox/core/tables/jobs.py:81 +#: netbox/extras/tables/tables.py:806 netbox/extras/tables/tables.py:863 msgid "Message" msgstr "" -#: core/tables/config.py:21 users/forms/filtersets.py:48 users/tables.py:72 +#: netbox/core/tables/config.py:21 netbox/users/forms/filtersets.py:48 +#: netbox/users/tables.py:72 msgid "Is Active" msgstr "" -#: core/tables/data.py:34 +#: netbox/core/tables/data.py:34 msgid "Last Synced" msgstr "" -#: core/tables/data.py:37 +#: netbox/core/tables/data.py:37 msgid "Files" msgstr "" -#: core/tables/data.py:61 +#: netbox/core/tables/data.py:61 msgid "Path" msgstr "" -#: core/tables/data.py:65 templates/extras/inc/result_pending.html:7 -#: templates/generic/object.html:70 +#: netbox/core/tables/data.py:65 +#: netbox/templates/extras/inc/result_pending.html:7 +#: netbox/templates/generic/object.html:70 msgid "Last updated" msgstr "" -#: core/tables/jobs.py:14 core/tables/tasks.py:77 -#: dcim/tables/devicetypes.py:168 extras/tables/tables.py:264 -#: extras/tables/tables.py:579 extras/tables/tables.py:828 -#: netbox/tables/tables.py:252 templates/dcim/virtualchassis_edit.html:64 -#: utilities/forms/forms.py:119 wireless/tables/wirelesslink.py:16 +#: netbox/core/tables/jobs.py:14 netbox/core/tables/tasks.py:77 +#: netbox/dcim/tables/devicetypes.py:168 netbox/extras/tables/tables.py:264 +#: netbox/extras/tables/tables.py:579 netbox/extras/tables/tables.py:828 +#: netbox/netbox/tables/tables.py:252 +#: netbox/templates/dcim/virtualchassis_edit.html:64 +#: netbox/utilities/forms/forms.py:119 +#: netbox/wireless/tables/wirelesslink.py:16 msgid "ID" msgstr "" -#: core/tables/jobs.py:39 +#: netbox/core/tables/jobs.py:39 msgid "Interval" msgstr "" -#: core/tables/jobs.py:51 core/views.py:271 +#: netbox/core/tables/jobs.py:51 netbox/core/views.py:271 msgid "Log Entries" msgstr "" -#: core/tables/jobs.py:78 extras/tables/tables.py:800 -#: extras/tables/tables.py:854 +#: netbox/core/tables/jobs.py:78 netbox/extras/tables/tables.py:800 +#: netbox/extras/tables/tables.py:854 msgid "Level" msgstr "" -#: core/tables/jobs.py:85 +#: netbox/core/tables/jobs.py:85 msgid "No log entries" msgstr "" -#: core/tables/plugins.py:16 vpn/forms/bulk_edit.py:123 -#: vpn/forms/bulk_import.py:171 vpn/tables/crypto.py:58 +#: netbox/core/tables/plugins.py:16 netbox/vpn/forms/bulk_edit.py:123 +#: netbox/vpn/forms/bulk_import.py:171 netbox/vpn/tables/crypto.py:58 msgid "Version" msgstr "" -#: core/tables/plugins.py:21 +#: netbox/core/tables/plugins.py:21 msgid "Last Updated" msgstr "" -#: core/tables/plugins.py:25 +#: netbox/core/tables/plugins.py:25 msgid "Minimum NetBox Version" msgstr "" -#: core/tables/plugins.py:29 +#: netbox/core/tables/plugins.py:29 msgid "Maximum NetBox Version" msgstr "" -#: core/tables/plugins.py:33 core/tables/plugins.py:80 +#: netbox/core/tables/plugins.py:33 netbox/core/tables/plugins.py:80 msgid "No plugin data found" msgstr "" -#: core/tables/plugins.py:50 templates/core/plugin.html:62 +#: netbox/core/tables/plugins.py:50 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "" -#: core/tables/plugins.py:63 templates/core/plugin.html:84 +#: netbox/core/tables/plugins.py:63 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "" -#: core/tables/plugins.py:66 +#: netbox/core/tables/plugins.py:66 msgid "Published" msgstr "" -#: core/tables/plugins.py:72 +#: netbox/core/tables/plugins.py:72 msgid "Installed Version" msgstr "" -#: core/tables/plugins.py:76 +#: netbox/core/tables/plugins.py:76 msgid "Latest Version" msgstr "" -#: core/tables/tasks.py:19 +#: netbox/core/tables/tasks.py:19 msgid "Oldest Task" msgstr "" -#: core/tables/tasks.py:43 templates/core/rq_worker_list.html:39 +#: netbox/core/tables/tasks.py:43 netbox/templates/core/rq_worker_list.html:39 msgid "Workers" msgstr "" -#: core/tables/tasks.py:47 vpn/tables/tunnels.py:87 +#: netbox/core/tables/tasks.py:47 netbox/vpn/tables/tunnels.py:87 msgid "Host" msgstr "" -#: core/tables/tasks.py:51 ipam/forms/filtersets.py:646 +#: netbox/core/tables/tasks.py:51 netbox/ipam/forms/filtersets.py:646 msgid "Port" msgstr "" -#: core/tables/tasks.py:55 +#: netbox/core/tables/tasks.py:55 msgid "DB" msgstr "" -#: core/tables/tasks.py:59 +#: netbox/core/tables/tasks.py:59 msgid "Scheduler PID" msgstr "" -#: core/tables/tasks.py:63 +#: netbox/core/tables/tasks.py:63 msgid "No queues found" msgstr "" -#: core/tables/tasks.py:83 +#: netbox/core/tables/tasks.py:83 msgid "Enqueued" msgstr "" -#: core/tables/tasks.py:86 +#: netbox/core/tables/tasks.py:86 msgid "Ended" msgstr "" -#: core/tables/tasks.py:95 templates/core/rq_task.html:85 +#: netbox/core/tables/tasks.py:95 netbox/templates/core/rq_task.html:85 msgid "Callable" msgstr "" -#: core/tables/tasks.py:99 +#: netbox/core/tables/tasks.py:99 msgid "No tasks found" msgstr "" -#: core/tables/tasks.py:120 templates/core/rq_worker.html:47 +#: netbox/core/tables/tasks.py:120 netbox/templates/core/rq_worker.html:47 msgid "State" msgstr "" -#: core/tables/tasks.py:123 templates/core/rq_worker.html:51 +#: netbox/core/tables/tasks.py:123 netbox/templates/core/rq_worker.html:51 msgid "Birth" msgstr "" -#: core/tables/tasks.py:126 templates/core/rq_worker.html:59 +#: netbox/core/tables/tasks.py:126 netbox/templates/core/rq_worker.html:59 msgid "PID" msgstr "" -#: core/tables/tasks.py:130 +#: netbox/core/tables/tasks.py:130 msgid "No workers found" msgstr "" -#: core/ui/panels.py:13 +#: netbox/core/ui/panels.py:13 msgid "Last synced" msgstr "" -#: core/ui/panels.py:29 +#: netbox/core/ui/panels.py:29 msgid "Backend" msgstr "" -#: core/ui/panels.py:33 extras/tables/tables.py:238 extras/tables/tables.py:610 -#: extras/tables/tables.py:640 extras/tables/tables.py:682 -#: templates/core/inc/datafile_panel.html:4 -#: templates/core/inc/datafile_panel.html:17 -#: templates/extras/object_render_config.html:23 -#: templates/generic/bulk_import.html:35 +#: netbox/core/ui/panels.py:33 netbox/extras/tables/tables.py:238 +#: netbox/extras/tables/tables.py:610 netbox/extras/tables/tables.py:640 +#: netbox/extras/tables/tables.py:682 +#: netbox/templates/core/inc/datafile_panel.html:4 +#: netbox/templates/core/inc/datafile_panel.html:17 +#: netbox/templates/extras/object_render_config.html:23 +#: netbox/templates/generic/bulk_import.html:35 msgid "Data File" msgstr "" -#: core/ui/panels.py:38 +#: netbox/core/ui/panels.py:38 msgid "SHA256 hash" msgstr "" -#: core/ui/panels.py:43 +#: netbox/core/ui/panels.py:43 msgid "Content" msgstr "" -#: core/ui/panels.py:47 templates/core/rq_task.html:12 -#: templates/core/rq_task.html:49 templates/core/rq_task.html:58 +#: netbox/core/ui/panels.py:47 netbox/templates/core/rq_task.html:12 +#: netbox/templates/core/rq_task.html:49 netbox/templates/core/rq_task.html:58 msgid "Job" msgstr "" -#: core/ui/panels.py:50 core/ui/panels.py:79 extras/forms/bulk_import.py:53 -#: extras/forms/filtersets.py:234 extras/forms/filtersets.py:340 -#: extras/forms/model_forms.py:407 extras/forms/model_forms.py:467 -#: extras/forms/model_forms.py:504 tenancy/forms/filtersets.py:121 +#: netbox/core/ui/panels.py:50 netbox/core/ui/panels.py:79 +#: netbox/extras/forms/bulk_import.py:53 netbox/extras/forms/filtersets.py:234 +#: netbox/extras/forms/filtersets.py:340 netbox/extras/forms/model_forms.py:407 +#: netbox/extras/forms/model_forms.py:467 +#: netbox/extras/forms/model_forms.py:504 +#: netbox/tenancy/forms/filtersets.py:121 msgid "Object type" msgstr "" -#: core/ui/panels.py:56 +#: netbox/core/ui/panels.py:56 msgid "Created by" msgstr "" -#: core/ui/panels.py:60 +#: netbox/core/ui/panels.py:60 msgid "Scheduling" msgstr "" -#: core/ui/panels.py:69 users/ui/panels.py:58 +#: netbox/core/ui/panels.py:69 netbox/users/ui/panels.py:58 msgid "Change" msgstr "" -#: core/utils.py:87 core/utils.py:153 core/views.py:556 +#: netbox/core/utils.py:87 netbox/core/utils.py:153 netbox/core/views.py:556 #, python-brace-format msgid "Job {job_id} not found" msgstr "" -#: core/utils.py:105 core/utils.py:121 +#: netbox/core/utils.py:105 netbox/core/utils.py:121 #, python-brace-format msgid "Job {id} not found." msgstr "" -#: core/views.py:135 +#: netbox/core/views.py:135 #, python-brace-format msgid "Queued job #{id} to sync {datasource}" msgstr "" -#: core/views.py:253 extras/forms/filtersets.py:184 -#: extras/forms/filtersets.py:385 extras/forms/filtersets.py:408 -#: extras/forms/filtersets.py:504 extras/forms/model_forms.py:765 -#: extras/ui/panels.py:381 +#: netbox/core/views.py:253 netbox/extras/forms/filtersets.py:184 +#: netbox/extras/forms/filtersets.py:385 netbox/extras/forms/filtersets.py:408 +#: netbox/extras/forms/filtersets.py:504 netbox/extras/forms/model_forms.py:765 +#: netbox/extras/ui/panels.py:381 msgid "Data" msgstr "" -#: core/views.py:264 templates/extras/htmx/script_result.html:43 +#: netbox/core/views.py:264 netbox/templates/extras/htmx/script_result.html:43 msgid "Log" msgstr "" -#: core/views.py:492 +#: netbox/core/views.py:492 #, python-brace-format msgid "Restored configuration revision #{id}" msgstr "" -#: core/views.py:595 +#: netbox/core/views.py:595 #, python-brace-format msgid "Job {id} has been deleted." msgstr "" -#: core/views.py:597 +#: netbox/core/views.py:597 #, python-brace-format msgid "Error deleting job {id}: {error}" msgstr "" -#: core/views.py:606 +#: netbox/core/views.py:606 #, python-brace-format msgid "Job {id} has been re-enqueued." msgstr "" -#: core/views.py:615 +#: netbox/core/views.py:615 #, python-brace-format msgid "Job {id} has been enqueued." msgstr "" -#: core/views.py:624 +#: netbox/core/views.py:624 #, python-brace-format msgid "Job {id} has been stopped." msgstr "" -#: core/views.py:626 +#: netbox/core/views.py:626 #, python-brace-format msgid "Failed to stop job {id}" msgstr "" -#: core/views.py:840 +#: netbox/core/views.py:840 msgid "Plugins catalog could not be loaded" msgstr "" -#: core/views.py:876 +#: netbox/core/views.py:876 #, python-brace-format msgid "Plugin {name} not found" msgstr "" -#: dcim/api/serializers_/device_components.py:300 +#: netbox/dcim/api/serializers_/device_components.py:300 msgid "Interface mode does not support q-in-q service vlan" msgstr "" -#: dcim/api/serializers_/device_components.py:307 +#: netbox/dcim/api/serializers_/device_components.py:307 msgid "Interface mode does not support untagged vlan" msgstr "" -#: dcim/api/serializers_/device_components.py:312 -#: dcim/api/serializers_/device_components.py:317 +#: netbox/dcim/api/serializers_/device_components.py:312 +#: netbox/dcim/api/serializers_/device_components.py:317 msgid "Interface mode does not support tagged vlans" msgstr "" -#: dcim/api/serializers_/devices.py:55 dcim/api/serializers_/devicetypes.py:28 +#: netbox/dcim/api/serializers_/devices.py:55 +#: netbox/dcim/api/serializers_/devicetypes.py:28 msgid "Position (U)" msgstr "" -#: dcim/api/serializers_/devices.py:178 dcim/forms/bulk_import.py:786 -#: dcim/forms/model_forms.py:818 +#: netbox/dcim/api/serializers_/devices.py:178 +#: netbox/dcim/forms/bulk_import.py:786 netbox/dcim/forms/model_forms.py:818 msgid "Replicate components" msgstr "" -#: dcim/api/serializers_/devices.py:179 +#: netbox/dcim/api/serializers_/devices.py:179 msgid "" "Automatically populate components associated with this module type (default: " "true)" msgstr "" -#: dcim/api/serializers_/devices.py:185 dcim/forms/bulk_import.py:791 -#: dcim/forms/model_forms.py:824 +#: netbox/dcim/api/serializers_/devices.py:185 +#: netbox/dcim/forms/bulk_import.py:791 netbox/dcim/forms/model_forms.py:824 msgid "Adopt components" msgstr "" -#: dcim/api/serializers_/devices.py:186 dcim/forms/bulk_import.py:793 -#: dcim/forms/model_forms.py:827 +#: netbox/dcim/api/serializers_/devices.py:186 +#: netbox/dcim/forms/bulk_import.py:793 netbox/dcim/forms/model_forms.py:827 msgid "Adopt already existing components" msgstr "" -#: dcim/api/serializers_/devices.py:252 dcim/forms/common.py:114 +#: netbox/dcim/api/serializers_/devices.py:252 netbox/dcim/forms/common.py:114 msgid "" "Cannot install module with placeholder values in a module bay with no " "position defined." msgstr "" -#: dcim/api/serializers_/devices.py:263 dcim/forms/common.py:126 +#: netbox/dcim/api/serializers_/devices.py:263 netbox/dcim/forms/common.py:126 #, python-brace-format msgid "Cannot adopt {model} {name} as it already belongs to a module" msgstr "" -#: dcim/api/serializers_/devices.py:271 dcim/forms/common.py:135 +#: netbox/dcim/api/serializers_/devices.py:271 netbox/dcim/forms/common.py:135 #, python-brace-format msgid "A {model} named {name} already exists" msgstr "" -#: dcim/api/serializers_/racks.py:135 dcim/ui/panels.py:49 +#: netbox/dcim/api/serializers_/racks.py:135 netbox/dcim/ui/panels.py:49 msgid "Facility ID" msgstr "" -#: dcim/cable_profiles.py:36 +#: netbox/dcim/cable_profiles.py:36 #, python-brace-format msgid "" "A side of cable has {count} terminations but only {max} are permitted for " "profile {profile}" msgstr "" -#: dcim/cable_profiles.py:46 +#: netbox/dcim/cable_profiles.py:46 #, python-brace-format msgid "" "B side of cable has {count} terminations but only {max} are permitted for " "profile {profile}" msgstr "" -#: dcim/choices.py:21 virtualization/choices.py:21 +#: netbox/dcim/choices.py:21 netbox/virtualization/choices.py:21 msgid "Staging" msgstr "" -#: dcim/choices.py:23 dcim/choices.py:208 dcim/choices.py:260 -#: dcim/choices.py:1962 dcim/choices.py:2111 virtualization/choices.py:23 -#: virtualization/choices.py:49 vpn/choices.py:282 +#: netbox/dcim/choices.py:23 netbox/dcim/choices.py:208 +#: netbox/dcim/choices.py:260 netbox/dcim/choices.py:1962 +#: netbox/dcim/choices.py:2111 netbox/virtualization/choices.py:23 +#: netbox/virtualization/choices.py:49 netbox/vpn/choices.py:282 msgid "Decommissioning" msgstr "" -#: dcim/choices.py:24 +#: netbox/dcim/choices.py:24 msgid "Retired" msgstr "" -#: dcim/choices.py:65 +#: netbox/dcim/choices.py:65 msgid "2-post frame" msgstr "" -#: dcim/choices.py:66 +#: netbox/dcim/choices.py:66 msgid "4-post frame" msgstr "" -#: dcim/choices.py:67 +#: netbox/dcim/choices.py:67 msgid "4-post cabinet" msgstr "" -#: dcim/choices.py:68 +#: netbox/dcim/choices.py:68 msgid "Wall-mounted frame" msgstr "" -#: dcim/choices.py:69 +#: netbox/dcim/choices.py:69 msgid "Wall-mounted frame (vertical)" msgstr "" -#: dcim/choices.py:70 +#: netbox/dcim/choices.py:70 msgid "Wall-mounted cabinet" msgstr "" -#: dcim/choices.py:71 +#: netbox/dcim/choices.py:71 msgid "Wall-mounted cabinet (vertical)" msgstr "" -#: dcim/choices.py:83 dcim/choices.py:84 dcim/choices.py:85 dcim/choices.py:86 +#: netbox/dcim/choices.py:83 netbox/dcim/choices.py:84 +#: netbox/dcim/choices.py:85 netbox/dcim/choices.py:86 #, python-brace-format msgid "{n} inches" msgstr "" -#: dcim/choices.py:100 ipam/choices.py:32 ipam/choices.py:50 ipam/choices.py:70 -#: ipam/choices.py:155 wireless/choices.py:26 +#: netbox/dcim/choices.py:100 netbox/ipam/choices.py:32 +#: netbox/ipam/choices.py:50 netbox/ipam/choices.py:70 +#: netbox/ipam/choices.py:155 netbox/wireless/choices.py:26 msgid "Reserved" msgstr "" -#: dcim/choices.py:101 templates/dcim/panels/power_utilization.html:11 -#: utilities/templates/widgets/splitmultiselect.html:5 +#: netbox/dcim/choices.py:101 +#: netbox/templates/dcim/panels/power_utilization.html:11 +#: netbox/utilities/templates/widgets/splitmultiselect.html:5 msgid "Available" msgstr "" -#: dcim/choices.py:104 ipam/choices.py:33 ipam/choices.py:51 ipam/choices.py:71 -#: ipam/choices.py:156 wireless/choices.py:28 +#: netbox/dcim/choices.py:104 netbox/ipam/choices.py:33 +#: netbox/ipam/choices.py:51 netbox/ipam/choices.py:71 +#: netbox/ipam/choices.py:156 netbox/wireless/choices.py:28 msgid "Deprecated" msgstr "" -#: dcim/choices.py:114 templates/dcim/inc/panels/racktype_dimensions.html:51 +#: netbox/dcim/choices.py:114 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:51 msgid "Millimeters" msgstr "" -#: dcim/choices.py:115 dcim/choices.py:1984 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1984 msgid "Inches" msgstr "" -#: dcim/choices.py:137 dcim/choices.py:227 dcim/choices.py:275 +#: netbox/dcim/choices.py:137 netbox/dcim/choices.py:227 +#: netbox/dcim/choices.py:275 msgid "Front to rear" msgstr "" -#: dcim/choices.py:138 dcim/choices.py:228 dcim/choices.py:276 +#: netbox/dcim/choices.py:138 netbox/dcim/choices.py:228 +#: netbox/dcim/choices.py:276 msgid "Rear to front" msgstr "" -#: dcim/choices.py:156 +#: netbox/dcim/choices.py:156 msgid "Stale" msgstr "" -#: dcim/choices.py:170 dcim/forms/bulk_edit.py:87 dcim/forms/bulk_edit.py:101 -#: dcim/forms/bulk_edit.py:181 dcim/forms/bulk_edit.py:623 -#: dcim/forms/bulk_edit.py:651 dcim/forms/bulk_edit.py:1447 -#: dcim/forms/bulk_import.py:77 dcim/forms/bulk_import.py:91 -#: dcim/forms/bulk_import.py:154 dcim/forms/bulk_import.py:530 -#: dcim/forms/bulk_import.py:556 dcim/forms/bulk_import.py:682 -#: dcim/forms/bulk_import.py:958 dcim/forms/bulk_import.py:1239 -#: dcim/forms/filtersets.py:267 dcim/forms/filtersets.py:813 -#: dcim/forms/filtersets.py:829 dcim/forms/model_forms.py:95 -#: dcim/forms/model_forms.py:113 dcim/forms/model_forms.py:216 -#: dcim/forms/model_forms.py:559 dcim/forms/model_forms.py:580 -#: dcim/forms/model_forms.py:1289 dcim/forms/model_forms.py:1772 -#: dcim/forms/object_import.py:193 dcim/tables/devices.py:722 -#: dcim/tables/devices.py:757 dcim/tables/devices.py:994 -#: dcim/tables/devices.py:1084 dcim/tables/devices.py:1237 -#: ipam/forms/bulk_import.py:608 ipam/forms/model_forms.py:788 -#: ipam/tables/fhrp.py:56 ipam/tables/ip.py:334 ipam/tables/services.py:42 -#: netbox/tables/tables.py:348 netbox/ui/panels.py:226 -#: tenancy/forms/bulk_edit.py:33 tenancy/forms/bulk_edit.py:62 -#: tenancy/forms/bulk_import.py:31 tenancy/forms/bulk_import.py:64 -#: tenancy/forms/model_forms.py:26 tenancy/forms/model_forms.py:67 -#: virtualization/forms/bulk_edit.py:216 -#: virtualization/forms/bulk_import.py:191 -#: virtualization/tables/virtualmachines.py:173 vpn/ui/panels.py:25 -#: wireless/forms/bulk_edit.py:26 wireless/forms/bulk_import.py:23 -#: wireless/forms/model_forms.py:23 +#: netbox/dcim/choices.py:170 netbox/dcim/forms/bulk_edit.py:87 +#: netbox/dcim/forms/bulk_edit.py:101 netbox/dcim/forms/bulk_edit.py:181 +#: netbox/dcim/forms/bulk_edit.py:623 netbox/dcim/forms/bulk_edit.py:651 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/bulk_import.py:77 +#: netbox/dcim/forms/bulk_import.py:91 netbox/dcim/forms/bulk_import.py:154 +#: netbox/dcim/forms/bulk_import.py:530 netbox/dcim/forms/bulk_import.py:556 +#: netbox/dcim/forms/bulk_import.py:682 netbox/dcim/forms/bulk_import.py:958 +#: netbox/dcim/forms/bulk_import.py:1239 netbox/dcim/forms/filtersets.py:267 +#: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:829 +#: netbox/dcim/forms/model_forms.py:95 netbox/dcim/forms/model_forms.py:113 +#: netbox/dcim/forms/model_forms.py:216 netbox/dcim/forms/model_forms.py:559 +#: netbox/dcim/forms/model_forms.py:580 netbox/dcim/forms/model_forms.py:1289 +#: netbox/dcim/forms/model_forms.py:1772 netbox/dcim/forms/object_import.py:193 +#: netbox/dcim/tables/devices.py:722 netbox/dcim/tables/devices.py:757 +#: netbox/dcim/tables/devices.py:994 netbox/dcim/tables/devices.py:1084 +#: netbox/dcim/tables/devices.py:1237 netbox/ipam/forms/bulk_import.py:608 +#: netbox/ipam/forms/model_forms.py:788 netbox/ipam/tables/fhrp.py:56 +#: netbox/ipam/tables/ip.py:334 netbox/ipam/tables/services.py:42 +#: netbox/netbox/tables/tables.py:348 netbox/netbox/ui/panels.py:226 +#: netbox/tenancy/forms/bulk_edit.py:33 netbox/tenancy/forms/bulk_edit.py:62 +#: netbox/tenancy/forms/bulk_import.py:31 +#: netbox/tenancy/forms/bulk_import.py:64 +#: netbox/tenancy/forms/model_forms.py:26 +#: netbox/tenancy/forms/model_forms.py:67 +#: netbox/virtualization/forms/bulk_edit.py:220 +#: netbox/virtualization/forms/bulk_import.py:191 +#: netbox/virtualization/tables/virtualmachines.py:173 +#: netbox/vpn/ui/panels.py:25 netbox/wireless/forms/bulk_edit.py:26 +#: netbox/wireless/forms/bulk_import.py:23 +#: netbox/wireless/forms/model_forms.py:23 msgid "Parent" msgstr "" -#: dcim/choices.py:171 +#: netbox/dcim/choices.py:171 msgid "Child" msgstr "" -#: dcim/choices.py:185 templates/dcim/panels/device_rack_elevations.html:15 -#: templates/dcim/panels/rack_elevations.html:12 -#: templates/dcim/panels/rack_reservation_elevations.html:5 -#: templates/dcim/rack_elevation_list.html:20 +#: netbox/dcim/choices.py:185 +#: netbox/templates/dcim/panels/device_rack_elevations.html:15 +#: netbox/templates/dcim/panels/rack_elevations.html:12 +#: netbox/templates/dcim/panels/rack_reservation_elevations.html:5 +#: netbox/templates/dcim/rack_elevation_list.html:20 msgid "Front" msgstr "" -#: dcim/choices.py:186 templates/dcim/panels/device_rack_elevations.html:21 -#: templates/dcim/panels/rack_elevations.html:18 -#: templates/dcim/panels/rack_reservation_elevations.html:11 -#: templates/dcim/rack_elevation_list.html:21 +#: netbox/dcim/choices.py:186 +#: netbox/templates/dcim/panels/device_rack_elevations.html:21 +#: netbox/templates/dcim/panels/rack_elevations.html:18 +#: netbox/templates/dcim/panels/rack_reservation_elevations.html:11 +#: netbox/templates/dcim/rack_elevation_list.html:21 msgid "Rear" msgstr "" -#: dcim/choices.py:205 dcim/choices.py:258 dcim/choices.py:2109 -#: virtualization/choices.py:47 +#: netbox/dcim/choices.py:205 netbox/dcim/choices.py:258 +#: netbox/dcim/choices.py:2109 netbox/virtualization/choices.py:47 msgid "Staged" msgstr "" -#: dcim/choices.py:207 +#: netbox/dcim/choices.py:207 msgid "Inventory" msgstr "" -#: dcim/choices.py:229 dcim/choices.py:277 +#: netbox/dcim/choices.py:229 netbox/dcim/choices.py:277 msgid "Left to right" msgstr "" -#: dcim/choices.py:230 dcim/choices.py:278 +#: netbox/dcim/choices.py:230 netbox/dcim/choices.py:278 msgid "Right to left" msgstr "" -#: dcim/choices.py:231 dcim/choices.py:279 +#: netbox/dcim/choices.py:231 netbox/dcim/choices.py:279 msgid "Side to rear" msgstr "" -#: dcim/choices.py:232 +#: netbox/dcim/choices.py:232 msgid "Rear to side" msgstr "" -#: dcim/choices.py:233 +#: netbox/dcim/choices.py:233 msgid "Bottom to top" msgstr "" -#: dcim/choices.py:234 +#: netbox/dcim/choices.py:234 msgid "Top to bottom" msgstr "" -#: dcim/choices.py:235 dcim/choices.py:280 dcim/choices.py:1592 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:280 +#: netbox/dcim/choices.py:1592 msgid "Passive" msgstr "" -#: dcim/choices.py:236 +#: netbox/dcim/choices.py:236 msgid "Mixed" msgstr "" -#: dcim/choices.py:508 dcim/choices.py:761 +#: netbox/dcim/choices.py:508 netbox/dcim/choices.py:761 msgid "NEMA (Non-locking)" msgstr "" -#: dcim/choices.py:530 dcim/choices.py:783 +#: netbox/dcim/choices.py:530 netbox/dcim/choices.py:783 msgid "NEMA (Locking)" msgstr "" -#: dcim/choices.py:554 dcim/choices.py:807 +#: netbox/dcim/choices.py:554 netbox/dcim/choices.py:807 msgid "California Style" msgstr "" -#: dcim/choices.py:562 +#: netbox/dcim/choices.py:562 msgid "International/ITA" msgstr "" -#: dcim/choices.py:598 dcim/choices.py:843 +#: netbox/dcim/choices.py:598 netbox/dcim/choices.py:843 msgid "Proprietary" msgstr "" -#: dcim/choices.py:606 dcim/choices.py:853 dcim/choices.py:1501 -#: dcim/choices.py:1503 dcim/choices.py:1742 dcim/choices.py:1744 -#: netbox/navigation/menu.py:219 +#: netbox/dcim/choices.py:606 netbox/dcim/choices.py:853 +#: netbox/dcim/choices.py:1501 netbox/dcim/choices.py:1503 +#: netbox/dcim/choices.py:1742 netbox/dcim/choices.py:1744 +#: netbox/netbox/navigation/menu.py:219 msgid "Other" msgstr "" -#: dcim/choices.py:815 +#: netbox/dcim/choices.py:815 msgid "ITA/International" msgstr "" -#: dcim/choices.py:883 +#: netbox/dcim/choices.py:883 msgid "Physical" msgstr "" -#: dcim/choices.py:884 dcim/choices.py:1163 +#: netbox/dcim/choices.py:884 netbox/dcim/choices.py:1163 msgid "Virtual" msgstr "" -#: dcim/choices.py:885 dcim/choices.py:1378 dcim/forms/bulk_edit.py:1602 -#: dcim/forms/filtersets.py:1638 dcim/forms/filtersets.py:1764 -#: dcim/forms/model_forms.py:1188 dcim/forms/model_forms.py:1652 -#: dcim/ui/panels.py:556 netbox/navigation/menu.py:157 -#: netbox/navigation/menu.py:161 +#: netbox/dcim/choices.py:885 netbox/dcim/choices.py:1378 +#: netbox/dcim/forms/bulk_edit.py:1602 netbox/dcim/forms/filtersets.py:1638 +#: netbox/dcim/forms/filtersets.py:1764 netbox/dcim/forms/model_forms.py:1188 +#: netbox/dcim/forms/model_forms.py:1652 netbox/dcim/ui/panels.py:556 +#: netbox/netbox/navigation/menu.py:157 netbox/netbox/navigation/menu.py:161 msgid "Wireless" msgstr "" -#: dcim/choices.py:1161 +#: netbox/dcim/choices.py:1161 msgid "Virtual interfaces" msgstr "" -#: dcim/choices.py:1164 dcim/forms/bulk_edit.py:1455 -#: dcim/forms/bulk_import.py:965 dcim/forms/model_forms.py:1170 -#: dcim/tables/devices.py:761 virtualization/forms/bulk_edit.py:221 -#: virtualization/forms/bulk_import.py:198 -#: virtualization/tables/virtualmachines.py:177 +#: netbox/dcim/choices.py:1164 netbox/dcim/forms/bulk_edit.py:1455 +#: netbox/dcim/forms/bulk_import.py:965 netbox/dcim/forms/model_forms.py:1170 +#: netbox/dcim/tables/devices.py:761 +#: netbox/virtualization/forms/bulk_edit.py:225 +#: netbox/virtualization/forms/bulk_import.py:198 +#: netbox/virtualization/tables/virtualmachines.py:177 msgid "Bridge" msgstr "" -#: dcim/choices.py:1165 +#: netbox/dcim/choices.py:1165 msgid "Link Aggregation Group (LAG)" msgstr "" -#: dcim/choices.py:1169 +#: netbox/dcim/choices.py:1169 msgid "FastEthernet (100 Mbps)" msgstr "" -#: dcim/choices.py:1178 +#: netbox/dcim/choices.py:1178 msgid "GigabitEthernet (1 Gbps)" msgstr "" -#: dcim/choices.py:1196 +#: netbox/dcim/choices.py:1196 msgid "2.5/5 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1203 +#: netbox/dcim/choices.py:1203 msgid "10 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1219 +#: netbox/dcim/choices.py:1219 msgid "25 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1229 +#: netbox/dcim/choices.py:1229 msgid "40 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1240 +#: netbox/dcim/choices.py:1240 msgid "50 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1250 +#: netbox/dcim/choices.py:1250 msgid "100 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1271 +#: netbox/dcim/choices.py:1271 msgid "200 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1285 +#: netbox/dcim/choices.py:1285 msgid "400 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1303 +#: netbox/dcim/choices.py:1303 msgid "800 Gbps Ethernet" msgstr "" -#: dcim/choices.py:1312 +#: netbox/dcim/choices.py:1312 msgid "1.6 Tbps Ethernet" msgstr "" -#: dcim/choices.py:1320 +#: netbox/dcim/choices.py:1320 msgid "Pluggable transceivers" msgstr "" -#: dcim/choices.py:1361 +#: netbox/dcim/choices.py:1361 msgid "Backplane Ethernet" msgstr "" -#: dcim/choices.py:1394 +#: netbox/dcim/choices.py:1394 msgid "Cellular" msgstr "" -#: dcim/choices.py:1446 dcim/forms/filtersets.py:442 -#: dcim/forms/filtersets.py:944 dcim/forms/filtersets.py:1156 -#: dcim/forms/filtersets.py:1991 templates/dcim/virtualchassis_edit.html:66 +#: netbox/dcim/choices.py:1446 netbox/dcim/forms/filtersets.py:442 +#: netbox/dcim/forms/filtersets.py:944 netbox/dcim/forms/filtersets.py:1156 +#: netbox/dcim/forms/filtersets.py:1991 +#: netbox/templates/dcim/virtualchassis_edit.html:66 msgid "Serial" msgstr "" -#: dcim/choices.py:1461 +#: netbox/dcim/choices.py:1461 msgid "Coaxial" msgstr "" -#: dcim/choices.py:1482 +#: netbox/dcim/choices.py:1482 msgid "Stacking" msgstr "" -#: dcim/choices.py:1537 +#: netbox/dcim/choices.py:1537 msgid "Half" msgstr "" -#: dcim/choices.py:1538 +#: netbox/dcim/choices.py:1538 msgid "Full" msgstr "" -#: dcim/choices.py:1539 netbox/preferences.py:32 wireless/choices.py:480 +#: netbox/dcim/choices.py:1539 netbox/netbox/preferences.py:32 +#: netbox/wireless/choices.py:480 msgid "Auto" msgstr "" -#: dcim/choices.py:1551 +#: netbox/dcim/choices.py:1551 msgid "Access" msgstr "" -#: dcim/choices.py:1552 ipam/tables/vlans.py:152 -#: templates/dcim/inc/interface_vlans_table.html:7 +#: netbox/dcim/choices.py:1552 netbox/ipam/tables/vlans.py:152 +#: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "" -#: dcim/choices.py:1553 +#: netbox/dcim/choices.py:1553 msgid "Tagged (All)" msgstr "" -#: dcim/choices.py:1554 templates/ipam/vlan_edit.html:26 +#: netbox/dcim/choices.py:1554 netbox/templates/ipam/vlan_edit.html:26 msgid "Q-in-Q (802.1ad)" msgstr "" -#: dcim/choices.py:1583 +#: netbox/dcim/choices.py:1583 msgid "IEEE Standard" msgstr "" -#: dcim/choices.py:1594 +#: netbox/dcim/choices.py:1594 msgid "Passive 24V (2-pair)" msgstr "" -#: dcim/choices.py:1595 +#: netbox/dcim/choices.py:1595 msgid "Passive 24V (4-pair)" msgstr "" -#: dcim/choices.py:1596 +#: netbox/dcim/choices.py:1596 msgid "Passive 48V (2-pair)" msgstr "" -#: dcim/choices.py:1597 +#: netbox/dcim/choices.py:1597 msgid "Passive 48V (4-pair)" msgstr "" -#: dcim/choices.py:1670 +#: netbox/dcim/choices.py:1670 msgid "Copper" msgstr "" -#: dcim/choices.py:1693 +#: netbox/dcim/choices.py:1693 msgid "Fiber Optic" msgstr "" -#: dcim/choices.py:1729 dcim/choices.py:1945 +#: netbox/dcim/choices.py:1729 netbox/dcim/choices.py:1945 msgid "USB" msgstr "" -#: dcim/choices.py:1786 +#: netbox/dcim/choices.py:1786 msgid "Single" msgstr "" -#: dcim/choices.py:1788 +#: netbox/dcim/choices.py:1788 msgid "1C1P" msgstr "" -#: dcim/choices.py:1789 +#: netbox/dcim/choices.py:1789 msgid "1C2P" msgstr "" -#: dcim/choices.py:1790 +#: netbox/dcim/choices.py:1790 msgid "1C4P" msgstr "" -#: dcim/choices.py:1791 +#: netbox/dcim/choices.py:1791 msgid "1C6P" msgstr "" -#: dcim/choices.py:1792 +#: netbox/dcim/choices.py:1792 msgid "1C8P" msgstr "" -#: dcim/choices.py:1793 +#: netbox/dcim/choices.py:1793 msgid "1C12P" msgstr "" -#: dcim/choices.py:1794 +#: netbox/dcim/choices.py:1794 msgid "1C16P" msgstr "" -#: dcim/choices.py:1798 +#: netbox/dcim/choices.py:1798 msgid "Trunk" msgstr "" -#: dcim/choices.py:1800 +#: netbox/dcim/choices.py:1800 msgid "2C1P trunk" msgstr "" -#: dcim/choices.py:1801 +#: netbox/dcim/choices.py:1801 msgid "2C2P trunk" msgstr "" -#: dcim/choices.py:1802 +#: netbox/dcim/choices.py:1802 msgid "2C4P trunk" msgstr "" -#: dcim/choices.py:1803 +#: netbox/dcim/choices.py:1803 msgid "2C4P trunk (shuffle)" msgstr "" -#: dcim/choices.py:1804 +#: netbox/dcim/choices.py:1804 msgid "2C6P trunk" msgstr "" -#: dcim/choices.py:1805 +#: netbox/dcim/choices.py:1805 msgid "2C8P trunk" msgstr "" -#: dcim/choices.py:1806 +#: netbox/dcim/choices.py:1806 msgid "2C12P trunk" msgstr "" -#: dcim/choices.py:1807 +#: netbox/dcim/choices.py:1807 msgid "4C1P trunk" msgstr "" -#: dcim/choices.py:1808 +#: netbox/dcim/choices.py:1808 msgid "4C2P trunk" msgstr "" -#: dcim/choices.py:1809 +#: netbox/dcim/choices.py:1809 msgid "4C4P trunk" msgstr "" -#: dcim/choices.py:1810 +#: netbox/dcim/choices.py:1810 msgid "4C4P trunk (shuffle)" msgstr "" -#: dcim/choices.py:1811 +#: netbox/dcim/choices.py:1811 msgid "4C6P trunk" msgstr "" -#: dcim/choices.py:1812 +#: netbox/dcim/choices.py:1812 msgid "4C8P trunk" msgstr "" -#: dcim/choices.py:1813 +#: netbox/dcim/choices.py:1813 msgid "8C4P trunk" msgstr "" -#: dcim/choices.py:1817 +#: netbox/dcim/choices.py:1817 msgid "Breakout" msgstr "" -#: dcim/choices.py:1819 +#: netbox/dcim/choices.py:1819 msgid "1C2P:2C1P breakout" msgstr "" -#: dcim/choices.py:1820 +#: netbox/dcim/choices.py:1820 msgid "1C4P:4C1P breakout" msgstr "" -#: dcim/choices.py:1821 +#: netbox/dcim/choices.py:1821 msgid "1C6P:6C1P breakout" msgstr "" -#: dcim/choices.py:1822 +#: netbox/dcim/choices.py:1822 msgid "2C4P:8C1P breakout (shuffle)" msgstr "" -#: dcim/choices.py:1880 +#: netbox/dcim/choices.py:1880 msgid "Copper - Twisted Pair (UTP/STP)" msgstr "" -#: dcim/choices.py:1894 +#: netbox/dcim/choices.py:1894 msgid "Copper - Twinax (DAC)" msgstr "" -#: dcim/choices.py:1901 +#: netbox/dcim/choices.py:1901 msgid "Copper - Coaxial" msgstr "" -#: dcim/choices.py:1916 +#: netbox/dcim/choices.py:1916 msgid "Fiber - Multimode" msgstr "" -#: dcim/choices.py:1927 +#: netbox/dcim/choices.py:1927 msgid "Fiber - Single-mode" msgstr "" -#: dcim/choices.py:1935 +#: netbox/dcim/choices.py:1935 msgid "Fiber - Other" msgstr "" -#: dcim/choices.py:1960 dcim/forms/filtersets.py:1463 +#: netbox/dcim/choices.py:1960 netbox/dcim/forms/filtersets.py:1463 msgid "Connected" msgstr "" -#: dcim/choices.py:1979 netbox/choices.py:177 +#: netbox/dcim/choices.py:1979 netbox/netbox/choices.py:177 msgid "Kilometers" msgstr "" -#: dcim/choices.py:1980 netbox/choices.py:178 -#: templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1980 netbox/netbox/choices.py:178 +#: netbox/templates/dcim/cable_trace.html:65 msgid "Meters" msgstr "" -#: dcim/choices.py:1981 +#: netbox/dcim/choices.py:1981 msgid "Centimeters" msgstr "" -#: dcim/choices.py:1982 netbox/choices.py:179 +#: netbox/dcim/choices.py:1982 netbox/netbox/choices.py:179 msgid "Miles" msgstr "" -#: dcim/choices.py:1983 netbox/choices.py:180 -#: templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1983 netbox/netbox/choices.py:180 +#: netbox/templates/dcim/cable_trace.html:66 msgid "Feet" msgstr "" -#: dcim/choices.py:2031 +#: netbox/dcim/choices.py:2031 msgid "Redundant" msgstr "" -#: dcim/choices.py:2052 +#: netbox/dcim/choices.py:2052 msgid "Single phase" msgstr "" -#: dcim/choices.py:2053 +#: netbox/dcim/choices.py:2053 msgid "Three-phase" msgstr "" -#: dcim/choices.py:2069 extras/choices.py:53 netbox/preferences.py:45 -#: netbox/preferences.py:70 -#: templates/extras/customfield/attrs/search_weight.html:1 vpn/choices.py:20 -#: wireless/choices.py:27 +#: netbox/dcim/choices.py:2069 netbox/extras/choices.py:53 +#: netbox/netbox/preferences.py:45 netbox/netbox/preferences.py:70 +#: netbox/templates/extras/customfield/attrs/search_weight.html:1 +#: netbox/vpn/choices.py:20 netbox/wireless/choices.py:27 msgid "Disabled" msgstr "" -#: dcim/choices.py:2070 +#: netbox/dcim/choices.py:2070 msgid "Faulty" msgstr "" -#: dcim/fields.py:48 +#: netbox/dcim/fields.py:48 #, python-brace-format msgid "Invalid MAC address format: {value}" msgstr "" -#: dcim/fields.py:77 +#: netbox/dcim/fields.py:77 #, python-brace-format msgid "Invalid WWN format: {value}" msgstr "" -#: dcim/filtersets.py:110 +#: netbox/dcim/filtersets.py:110 msgid "Parent region (ID)" msgstr "" -#: dcim/filtersets.py:117 +#: netbox/dcim/filtersets.py:117 msgid "Parent region (slug)" msgstr "" -#: dcim/filtersets.py:143 +#: netbox/dcim/filtersets.py:143 msgid "Parent site group (ID)" msgstr "" -#: dcim/filtersets.py:150 +#: netbox/dcim/filtersets.py:150 msgid "Parent site group (slug)" msgstr "" -#: dcim/filtersets.py:194 dcim/filtersets.py:434 dcim/filtersets.py:581 -#: extras/filtersets.py:475 ipam/filtersets.py:896 ipam/filtersets.py:1042 -#: users/filtersets.py:285 +#: netbox/dcim/filtersets.py:194 netbox/dcim/filtersets.py:434 +#: netbox/dcim/filtersets.py:581 netbox/extras/filtersets.py:475 +#: netbox/ipam/filtersets.py:896 netbox/ipam/filtersets.py:1042 +#: netbox/users/filtersets.py:285 msgid "Group (ID)" msgstr "" -#: dcim/filtersets.py:200 dcim/filtersets.py:441 dcim/filtersets.py:588 +#: netbox/dcim/filtersets.py:200 netbox/dcim/filtersets.py:441 +#: netbox/dcim/filtersets.py:588 msgid "Group (slug)" msgstr "" -#: dcim/filtersets.py:206 dcim/filtersets.py:211 +#: netbox/dcim/filtersets.py:206 netbox/dcim/filtersets.py:211 msgid "AS (ID)" msgstr "" -#: dcim/filtersets.py:280 +#: netbox/dcim/filtersets.py:280 msgid "Parent location (ID)" msgstr "" -#: dcim/filtersets.py:287 +#: netbox/dcim/filtersets.py:287 msgid "Parent location (slug)" msgstr "" -#: dcim/filtersets.py:340 dcim/filtersets.py:447 dcim/filtersets.py:659 -#: dcim/filtersets.py:832 dcim/filtersets.py:1074 dcim/filtersets.py:1182 -#: dcim/filtersets.py:1226 dcim/filtersets.py:1612 dcim/filtersets.py:2464 +#: netbox/dcim/filtersets.py:340 netbox/dcim/filtersets.py:447 +#: netbox/dcim/filtersets.py:659 netbox/dcim/filtersets.py:832 +#: netbox/dcim/filtersets.py:1074 netbox/dcim/filtersets.py:1182 +#: netbox/dcim/filtersets.py:1226 netbox/dcim/filtersets.py:1612 +#: netbox/dcim/filtersets.py:2464 msgid "Manufacturer (ID)" msgstr "" -#: dcim/filtersets.py:347 dcim/filtersets.py:454 dcim/filtersets.py:666 -#: dcim/filtersets.py:839 dcim/filtersets.py:1081 dcim/filtersets.py:1189 -#: dcim/filtersets.py:1233 dcim/filtersets.py:1619 dcim/filtersets.py:2471 +#: netbox/dcim/filtersets.py:347 netbox/dcim/filtersets.py:454 +#: netbox/dcim/filtersets.py:666 netbox/dcim/filtersets.py:839 +#: netbox/dcim/filtersets.py:1081 netbox/dcim/filtersets.py:1189 +#: netbox/dcim/filtersets.py:1233 netbox/dcim/filtersets.py:1619 +#: netbox/dcim/filtersets.py:2471 msgid "Manufacturer (slug)" msgstr "" -#: dcim/filtersets.py:461 +#: netbox/dcim/filtersets.py:461 msgid "Rack type (slug)" msgstr "" -#: dcim/filtersets.py:466 +#: netbox/dcim/filtersets.py:466 msgid "Rack type (ID)" msgstr "" -#: dcim/filtersets.py:484 dcim/filtersets.py:1086 dcim/filtersets.py:1251 -#: dcim/filtersets.py:2476 ipam/filtersets.py:295 ipam/filtersets.py:418 -#: ipam/filtersets.py:535 ipam/filtersets.py:1054 -#: virtualization/filtersets.py:258 +#: netbox/dcim/filtersets.py:484 netbox/dcim/filtersets.py:1086 +#: netbox/dcim/filtersets.py:1251 netbox/dcim/filtersets.py:2476 +#: netbox/ipam/filtersets.py:295 netbox/ipam/filtersets.py:418 +#: netbox/ipam/filtersets.py:535 netbox/ipam/filtersets.py:1054 +#: netbox/virtualization/filtersets.py:258 msgid "Role (ID)" msgstr "" -#: dcim/filtersets.py:491 dcim/filtersets.py:1093 dcim/filtersets.py:1258 -#: dcim/filtersets.py:2483 extras/filtersets.py:765 ipam/filtersets.py:302 -#: ipam/filtersets.py:425 ipam/filtersets.py:542 ipam/filtersets.py:1061 -#: virtualization/filtersets.py:265 +#: netbox/dcim/filtersets.py:491 netbox/dcim/filtersets.py:1093 +#: netbox/dcim/filtersets.py:1258 netbox/dcim/filtersets.py:2483 +#: netbox/extras/filtersets.py:765 netbox/ipam/filtersets.py:302 +#: netbox/ipam/filtersets.py:425 netbox/ipam/filtersets.py:542 +#: netbox/ipam/filtersets.py:1061 netbox/virtualization/filtersets.py:265 msgid "Role (slug)" msgstr "" -#: dcim/filtersets.py:523 dcim/filtersets.py:1333 dcim/filtersets.py:1696 -#: dcim/filtersets.py:1803 dcim/filtersets.py:2927 +#: netbox/dcim/filtersets.py:523 netbox/dcim/filtersets.py:1333 +#: netbox/dcim/filtersets.py:1696 netbox/dcim/filtersets.py:1803 +#: netbox/dcim/filtersets.py:2927 msgid "Rack (ID)" msgstr "" -#: dcim/filtersets.py:605 extras/filtersets.py:343 extras/filtersets.py:399 -#: extras/filtersets.py:447 extras/filtersets.py:470 extras/filtersets.py:539 -#: users/filtersets.py:142 users/filtersets.py:223 +#: netbox/dcim/filtersets.py:605 netbox/extras/filtersets.py:343 +#: netbox/extras/filtersets.py:399 netbox/extras/filtersets.py:447 +#: netbox/extras/filtersets.py:470 netbox/extras/filtersets.py:539 +#: netbox/users/filtersets.py:142 netbox/users/filtersets.py:223 msgid "User (name)" msgstr "" -#: dcim/filtersets.py:614 +#: netbox/dcim/filtersets.py:614 msgid "Minimum unit count" msgstr "" -#: dcim/filtersets.py:619 +#: netbox/dcim/filtersets.py:619 msgid "Maximum unit count" msgstr "" -#: dcim/filtersets.py:672 virtualization/filtersets.py:101 +#: netbox/dcim/filtersets.py:672 netbox/virtualization/filtersets.py:101 msgid "Default platform (ID)" msgstr "" -#: dcim/filtersets.py:679 virtualization/filtersets.py:108 +#: netbox/dcim/filtersets.py:679 netbox/virtualization/filtersets.py:108 msgid "Default platform (slug)" msgstr "" -#: dcim/filtersets.py:682 dcim/forms/filtersets.py:606 +#: netbox/dcim/filtersets.py:682 netbox/dcim/forms/filtersets.py:606 msgid "Has a front image" msgstr "" -#: dcim/filtersets.py:686 dcim/forms/filtersets.py:613 +#: netbox/dcim/filtersets.py:686 netbox/dcim/forms/filtersets.py:613 msgid "Has a rear image" msgstr "" -#: dcim/filtersets.py:691 dcim/filtersets.py:843 dcim/filtersets.py:1409 -#: dcim/forms/filtersets.py:620 dcim/forms/filtersets.py:741 -#: dcim/forms/filtersets.py:983 +#: netbox/dcim/filtersets.py:691 netbox/dcim/filtersets.py:843 +#: netbox/dcim/filtersets.py:1409 netbox/dcim/forms/filtersets.py:620 +#: netbox/dcim/forms/filtersets.py:741 netbox/dcim/forms/filtersets.py:983 msgid "Has console ports" msgstr "" -#: dcim/filtersets.py:695 dcim/filtersets.py:847 dcim/filtersets.py:1413 -#: dcim/forms/filtersets.py:627 dcim/forms/filtersets.py:748 -#: dcim/forms/filtersets.py:990 +#: netbox/dcim/filtersets.py:695 netbox/dcim/filtersets.py:847 +#: netbox/dcim/filtersets.py:1413 netbox/dcim/forms/filtersets.py:627 +#: netbox/dcim/forms/filtersets.py:748 netbox/dcim/forms/filtersets.py:990 msgid "Has console server ports" msgstr "" -#: dcim/filtersets.py:699 dcim/filtersets.py:851 dcim/filtersets.py:1417 -#: dcim/forms/filtersets.py:634 dcim/forms/filtersets.py:755 -#: dcim/forms/filtersets.py:997 +#: netbox/dcim/filtersets.py:699 netbox/dcim/filtersets.py:851 +#: netbox/dcim/filtersets.py:1417 netbox/dcim/forms/filtersets.py:634 +#: netbox/dcim/forms/filtersets.py:755 netbox/dcim/forms/filtersets.py:997 msgid "Has power ports" msgstr "" -#: dcim/filtersets.py:703 dcim/filtersets.py:855 dcim/filtersets.py:1421 -#: dcim/forms/filtersets.py:641 dcim/forms/filtersets.py:762 -#: dcim/forms/filtersets.py:1004 +#: netbox/dcim/filtersets.py:703 netbox/dcim/filtersets.py:855 +#: netbox/dcim/filtersets.py:1421 netbox/dcim/forms/filtersets.py:641 +#: netbox/dcim/forms/filtersets.py:762 netbox/dcim/forms/filtersets.py:1004 msgid "Has power outlets" msgstr "" -#: dcim/filtersets.py:707 dcim/filtersets.py:859 dcim/filtersets.py:1425 -#: dcim/forms/filtersets.py:648 dcim/forms/filtersets.py:769 -#: dcim/forms/filtersets.py:1011 +#: netbox/dcim/filtersets.py:707 netbox/dcim/filtersets.py:859 +#: netbox/dcim/filtersets.py:1425 netbox/dcim/forms/filtersets.py:648 +#: netbox/dcim/forms/filtersets.py:769 netbox/dcim/forms/filtersets.py:1011 msgid "Has interfaces" msgstr "" -#: dcim/filtersets.py:711 dcim/filtersets.py:863 dcim/filtersets.py:1429 -#: dcim/forms/filtersets.py:655 dcim/forms/filtersets.py:776 -#: dcim/forms/filtersets.py:1018 +#: netbox/dcim/filtersets.py:711 netbox/dcim/filtersets.py:863 +#: netbox/dcim/filtersets.py:1429 netbox/dcim/forms/filtersets.py:655 +#: netbox/dcim/forms/filtersets.py:776 netbox/dcim/forms/filtersets.py:1018 msgid "Has pass-through ports" msgstr "" -#: dcim/filtersets.py:715 dcim/filtersets.py:1433 dcim/forms/filtersets.py:669 +#: netbox/dcim/filtersets.py:715 netbox/dcim/filtersets.py:1433 +#: netbox/dcim/forms/filtersets.py:669 msgid "Has module bays" msgstr "" -#: dcim/filtersets.py:719 dcim/filtersets.py:1437 dcim/forms/filtersets.py:662 +#: netbox/dcim/filtersets.py:719 netbox/dcim/filtersets.py:1437 +#: netbox/dcim/forms/filtersets.py:662 msgid "Has device bays" msgstr "" -#: dcim/filtersets.py:723 dcim/forms/filtersets.py:676 +#: netbox/dcim/filtersets.py:723 netbox/dcim/forms/filtersets.py:676 msgid "Has inventory items" msgstr "" -#: dcim/filtersets.py:820 dcim/filtersets.py:1599 extras/filtersets.py:698 +#: netbox/dcim/filtersets.py:820 netbox/dcim/filtersets.py:1599 +#: netbox/extras/filtersets.py:698 msgid "Profile (ID)" msgstr "" -#: dcim/filtersets.py:827 dcim/filtersets.py:1606 extras/filtersets.py:705 +#: netbox/dcim/filtersets.py:827 netbox/dcim/filtersets.py:1606 +#: netbox/extras/filtersets.py:705 msgid "Profile (name)" msgstr "" -#: dcim/filtersets.py:917 dcim/filtersets.py:1245 dcim/filtersets.py:1828 +#: netbox/dcim/filtersets.py:917 netbox/dcim/filtersets.py:1245 +#: netbox/dcim/filtersets.py:1828 msgid "Device type (ID)" msgstr "" -#: dcim/filtersets.py:934 dcim/filtersets.py:1625 +#: netbox/dcim/filtersets.py:934 netbox/dcim/filtersets.py:1625 msgid "Module type (ID)" msgstr "" -#: dcim/filtersets.py:972 dcim/filtersets.py:1997 +#: netbox/dcim/filtersets.py:972 netbox/dcim/filtersets.py:1997 msgid "Power port (ID)" msgstr "" -#: dcim/filtersets.py:1021 dcim/filtersets.py:2383 +#: netbox/dcim/filtersets.py:1021 netbox/dcim/filtersets.py:2383 msgid "Rear port (ID)" msgstr "" -#: dcim/filtersets.py:1040 dcim/filtersets.py:2405 +#: netbox/dcim/filtersets.py:1040 netbox/dcim/filtersets.py:2405 msgid "Front port (ID)" msgstr "" -#: dcim/filtersets.py:1069 dcim/filtersets.py:2459 +#: netbox/dcim/filtersets.py:1069 netbox/dcim/filtersets.py:2459 msgid "Parent inventory item (ID)" msgstr "" -#: dcim/filtersets.py:1118 dcim/filtersets.py:1198 dcim/filtersets.py:1405 -#: virtualization/filtersets.py:291 +#: netbox/dcim/filtersets.py:1118 netbox/dcim/filtersets.py:1198 +#: netbox/dcim/filtersets.py:1405 netbox/virtualization/filtersets.py:291 msgid "Config template (ID)" msgstr "" -#: dcim/filtersets.py:1123 dcim/filtersets.py:1136 +#: netbox/dcim/filtersets.py:1123 netbox/dcim/filtersets.py:1136 msgid "Parent device role (ID)" msgstr "" -#: dcim/filtersets.py:1130 dcim/filtersets.py:1143 +#: netbox/dcim/filtersets.py:1130 netbox/dcim/filtersets.py:1143 msgid "Parent device role (slug)" msgstr "" -#: dcim/filtersets.py:1156 +#: netbox/dcim/filtersets.py:1156 msgid "Immediate parent platform (ID)" msgstr "" -#: dcim/filtersets.py:1163 +#: netbox/dcim/filtersets.py:1163 msgid "Immediate parent platform (slug)" msgstr "" -#: dcim/filtersets.py:1169 +#: netbox/dcim/filtersets.py:1169 msgid "Parent platform (ID)" msgstr "" -#: dcim/filtersets.py:1176 +#: netbox/dcim/filtersets.py:1176 msgid "Parent platform (slug)" msgstr "" -#: dcim/filtersets.py:1240 +#: netbox/dcim/filtersets.py:1240 msgid "Device type (slug)" msgstr "" -#: dcim/filtersets.py:1263 +#: netbox/dcim/filtersets.py:1263 msgid "Parent Device (ID)" msgstr "" -#: dcim/filtersets.py:1269 virtualization/filtersets.py:271 +#: netbox/dcim/filtersets.py:1269 netbox/virtualization/filtersets.py:271 msgid "Platform (ID)" msgstr "" -#: dcim/filtersets.py:1276 extras/filtersets.py:776 -#: virtualization/filtersets.py:278 +#: netbox/dcim/filtersets.py:1276 netbox/extras/filtersets.py:776 +#: netbox/virtualization/filtersets.py:278 msgid "Platform (slug)" msgstr "" -#: dcim/filtersets.py:1314 dcim/filtersets.py:1677 dcim/filtersets.py:1784 -#: dcim/filtersets.py:2572 dcim/filtersets.py:2854 dcim/filtersets.py:2916 +#: netbox/dcim/filtersets.py:1314 netbox/dcim/filtersets.py:1677 +#: netbox/dcim/filtersets.py:1784 netbox/dcim/filtersets.py:2572 +#: netbox/dcim/filtersets.py:2854 netbox/dcim/filtersets.py:2916 msgid "Site name (slug)" msgstr "" -#: dcim/filtersets.py:1338 +#: netbox/dcim/filtersets.py:1338 msgid "Parent bay (ID)" msgstr "" -#: dcim/filtersets.py:1343 +#: netbox/dcim/filtersets.py:1343 msgid "VM cluster (ID)" msgstr "" -#: dcim/filtersets.py:1350 extras/filtersets.py:798 -#: virtualization/filtersets.py:175 +#: netbox/dcim/filtersets.py:1350 netbox/extras/filtersets.py:798 +#: netbox/virtualization/filtersets.py:175 msgid "Cluster group (slug)" msgstr "" -#: dcim/filtersets.py:1356 virtualization/filtersets.py:168 +#: netbox/dcim/filtersets.py:1356 netbox/virtualization/filtersets.py:168 msgid "Cluster group (ID)" msgstr "" -#: dcim/filtersets.py:1363 +#: netbox/dcim/filtersets.py:1363 msgid "Device model (slug)" msgstr "" -#: dcim/filtersets.py:1375 dcim/forms/bulk_edit.py:529 +#: netbox/dcim/filtersets.py:1375 netbox/dcim/forms/bulk_edit.py:529 msgid "Is full depth" msgstr "" -#: dcim/filtersets.py:1379 dcim/forms/filtersets.py:953 -#: dcim/forms/filtersets.py:1695 dcim/forms/filtersets.py:2060 -#: dcim/forms/model_forms.py:1978 dcim/models/devices.py:1359 -#: dcim/models/devices.py:1383 dcim/ui/panels.py:383 dcim/ui/panels.py:518 -#: virtualization/filtersets.py:282 virtualization/filtersets.py:370 -#: virtualization/forms/filtersets.py:239 -#: virtualization/forms/filtersets.py:293 +#: netbox/dcim/filtersets.py:1379 netbox/dcim/forms/filtersets.py:953 +#: netbox/dcim/forms/filtersets.py:1695 netbox/dcim/forms/filtersets.py:2060 +#: netbox/dcim/forms/model_forms.py:1978 netbox/dcim/models/devices.py:1359 +#: netbox/dcim/models/devices.py:1383 netbox/dcim/ui/panels.py:383 +#: netbox/dcim/ui/panels.py:518 netbox/virtualization/filtersets.py:282 +#: netbox/virtualization/filtersets.py:370 +#: netbox/virtualization/forms/filtersets.py:239 +#: netbox/virtualization/forms/filtersets.py:293 msgid "MAC address" msgstr "" -#: dcim/filtersets.py:1386 dcim/filtersets.py:1565 dcim/forms/filtersets.py:962 -#: dcim/forms/filtersets.py:1063 virtualization/filtersets.py:286 -#: virtualization/forms/filtersets.py:243 +#: netbox/dcim/filtersets.py:1386 netbox/dcim/filtersets.py:1565 +#: netbox/dcim/forms/filtersets.py:962 netbox/dcim/forms/filtersets.py:1063 +#: netbox/virtualization/filtersets.py:286 +#: netbox/virtualization/forms/filtersets.py:243 msgid "Has a primary IP" msgstr "" -#: dcim/filtersets.py:1390 +#: netbox/dcim/filtersets.py:1390 msgid "Has an out-of-band IP" msgstr "" -#: dcim/filtersets.py:1396 +#: netbox/dcim/filtersets.py:1396 msgid "Virtual chassis (ID)" msgstr "" -#: dcim/filtersets.py:1400 +#: netbox/dcim/filtersets.py:1400 msgid "Is a virtual chassis member" msgstr "" -#: dcim/filtersets.py:1443 +#: netbox/dcim/filtersets.py:1443 msgid "OOB IP (ID)" msgstr "" -#: dcim/filtersets.py:1447 +#: netbox/dcim/filtersets.py:1447 msgid "Has virtual device context" msgstr "" -#: dcim/filtersets.py:1546 +#: netbox/dcim/filtersets.py:1546 msgid "VDC (ID)" msgstr "" -#: dcim/filtersets.py:1552 +#: netbox/dcim/filtersets.py:1552 msgid "Device model" msgstr "" -#: dcim/filtersets.py:1632 +#: netbox/dcim/filtersets.py:1632 msgid "Module type (model)" msgstr "" -#: dcim/filtersets.py:1638 +#: netbox/dcim/filtersets.py:1638 msgid "Module bay (ID)" msgstr "" -#: dcim/filtersets.py:1703 dcim/filtersets.py:1810 +#: netbox/dcim/filtersets.py:1703 netbox/dcim/filtersets.py:1810 msgid "Rack (name)" msgstr "" -#: dcim/filtersets.py:1708 dcim/filtersets.py:1815 dcim/filtersets.py:2025 -#: ipam/filtersets.py:659 ipam/filtersets.py:906 ipam/filtersets.py:1243 -#: virtualization/filtersets.py:205 vpn/filtersets.py:423 +#: netbox/dcim/filtersets.py:1708 netbox/dcim/filtersets.py:1815 +#: netbox/dcim/filtersets.py:2025 netbox/ipam/filtersets.py:659 +#: netbox/ipam/filtersets.py:906 netbox/ipam/filtersets.py:1243 +#: netbox/virtualization/filtersets.py:205 netbox/vpn/filtersets.py:423 msgid "Device (ID)" msgstr "" -#: dcim/filtersets.py:1715 dcim/filtersets.py:1822 dcim/filtersets.py:2020 -#: ipam/filtersets.py:654 ipam/filtersets.py:901 ipam/filtersets.py:1238 -#: vpn/filtersets.py:418 +#: netbox/dcim/filtersets.py:1715 netbox/dcim/filtersets.py:1822 +#: netbox/dcim/filtersets.py:2020 netbox/ipam/filtersets.py:654 +#: netbox/ipam/filtersets.py:901 netbox/ipam/filtersets.py:1238 +#: netbox/vpn/filtersets.py:418 msgid "Device (name)" msgstr "" -#: dcim/filtersets.py:1835 +#: netbox/dcim/filtersets.py:1835 msgid "Device type (model)" msgstr "" -#: dcim/filtersets.py:1841 +#: netbox/dcim/filtersets.py:1841 msgid "Device role (ID)" msgstr "" -#: dcim/filtersets.py:1848 +#: netbox/dcim/filtersets.py:1848 msgid "Device role (slug)" msgstr "" -#: dcim/filtersets.py:1854 +#: netbox/dcim/filtersets.py:1854 msgid "Virtual Chassis (ID)" msgstr "" -#: dcim/filtersets.py:1861 dcim/forms/filtersets.py:130 -#: dcim/forms/object_create.py:329 dcim/tables/devices.py:215 -#: netbox/navigation/menu.py:88 templates/dcim/device_edit.html:95 -#: templates/dcim/virtualchassis_edit.html:28 +#: netbox/dcim/filtersets.py:1861 netbox/dcim/forms/filtersets.py:130 +#: netbox/dcim/forms/object_create.py:329 netbox/dcim/tables/devices.py:215 +#: netbox/netbox/navigation/menu.py:88 +#: netbox/templates/dcim/device_edit.html:95 +#: netbox/templates/dcim/virtualchassis_edit.html:28 msgid "Virtual Chassis" msgstr "" -#: dcim/filtersets.py:1872 dcim/filtersets.py:2578 tenancy/filtersets.py:271 +#: netbox/dcim/filtersets.py:1872 netbox/dcim/filtersets.py:2578 +#: netbox/tenancy/filtersets.py:271 msgid "Tenant (ID)" msgstr "" -#: dcim/filtersets.py:1879 dcim/filtersets.py:2585 extras/filtersets.py:825 -#: tenancy/filtersets.py:278 +#: netbox/dcim/filtersets.py:1879 netbox/dcim/filtersets.py:2585 +#: netbox/extras/filtersets.py:825 netbox/tenancy/filtersets.py:278 msgid "Tenant (slug)" msgstr "" -#: dcim/filtersets.py:1900 +#: netbox/dcim/filtersets.py:1900 msgid "Module (ID)" msgstr "" -#: dcim/filtersets.py:1908 +#: netbox/dcim/filtersets.py:1908 msgid "Cable (ID)" msgstr "" -#: dcim/filtersets.py:2030 ipam/filtersets.py:664 ipam/filtersets.py:911 -#: ipam/filtersets.py:1248 vpn/filtersets.py:429 +#: netbox/dcim/filtersets.py:2030 netbox/ipam/filtersets.py:664 +#: netbox/ipam/filtersets.py:911 netbox/ipam/filtersets.py:1248 +#: netbox/vpn/filtersets.py:429 msgid "Virtual machine (name)" msgstr "" -#: dcim/filtersets.py:2035 ipam/filtersets.py:669 ipam/filtersets.py:916 -#: ipam/filtersets.py:1253 virtualization/filtersets.py:347 -#: virtualization/filtersets.py:405 vpn/filtersets.py:434 +#: netbox/dcim/filtersets.py:2035 netbox/ipam/filtersets.py:669 +#: netbox/ipam/filtersets.py:916 netbox/ipam/filtersets.py:1253 +#: netbox/virtualization/filtersets.py:347 +#: netbox/virtualization/filtersets.py:405 netbox/vpn/filtersets.py:434 msgid "Virtual machine (ID)" msgstr "" -#: dcim/filtersets.py:2041 ipam/filtersets.py:675 vpn/filtersets.py:112 -#: vpn/filtersets.py:440 +#: netbox/dcim/filtersets.py:2041 netbox/ipam/filtersets.py:675 +#: netbox/vpn/filtersets.py:112 netbox/vpn/filtersets.py:440 msgid "Interface (name)" msgstr "" -#: dcim/filtersets.py:2052 ipam/filtersets.py:686 vpn/filtersets.py:123 -#: vpn/filtersets.py:451 +#: netbox/dcim/filtersets.py:2052 netbox/ipam/filtersets.py:686 +#: netbox/vpn/filtersets.py:123 netbox/vpn/filtersets.py:451 msgid "VM interface (name)" msgstr "" -#: dcim/filtersets.py:2057 ipam/filtersets.py:691 vpn/filtersets.py:128 +#: netbox/dcim/filtersets.py:2057 netbox/ipam/filtersets.py:691 +#: netbox/vpn/filtersets.py:128 msgid "VM interface (ID)" msgstr "" -#: dcim/filtersets.py:2061 ipam/filtersets.py:704 +#: netbox/dcim/filtersets.py:2061 netbox/ipam/filtersets.py:704 msgid "Is assigned" msgstr "" -#: dcim/filtersets.py:2065 dcim/forms/bulk_import.py:1365 -#: ipam/forms/bulk_import.py:344 +#: netbox/dcim/filtersets.py:2065 netbox/dcim/forms/bulk_import.py:1365 +#: netbox/ipam/forms/bulk_import.py:344 msgid "Is primary" msgstr "" -#: dcim/filtersets.py:2129 virtualization/forms/model_forms.py:467 -#: virtualization/ui/panels.py:95 +#: netbox/dcim/filtersets.py:2129 +#: netbox/virtualization/forms/model_forms.py:467 +#: netbox/virtualization/ui/panels.py:95 msgid "802.1Q Mode" msgstr "" -#: dcim/filtersets.py:2133 ipam/forms/bulk_import.py:202 -#: vpn/forms/bulk_import.py:313 +#: netbox/dcim/filtersets.py:2133 netbox/ipam/forms/bulk_import.py:202 +#: netbox/vpn/forms/bulk_import.py:313 msgid "Assigned VLAN" msgstr "" -#: dcim/filtersets.py:2137 +#: netbox/dcim/filtersets.py:2137 msgid "Assigned VID" msgstr "" -#: dcim/filtersets.py:2143 dcim/forms/bulk_edit.py:1568 -#: dcim/forms/bulk_import.py:1050 dcim/forms/filtersets.py:1748 -#: dcim/forms/model_forms.py:1618 dcim/models/device_components.py:942 -#: dcim/tables/devices.py:678 dcim/ui/panels.py:521 ipam/filtersets.py:372 -#: ipam/filtersets.py:384 ipam/filtersets.py:523 ipam/filtersets.py:630 -#: ipam/filtersets.py:642 ipam/forms/bulk_edit.py:195 -#: ipam/forms/bulk_edit.py:245 ipam/forms/bulk_edit.py:286 -#: ipam/forms/bulk_import.py:170 ipam/forms/bulk_import.py:255 -#: ipam/forms/bulk_import.py:291 ipam/forms/filtersets.py:70 -#: ipam/forms/filtersets.py:199 ipam/forms/filtersets.py:353 -#: ipam/forms/model_forms.py:69 ipam/forms/model_forms.py:210 -#: ipam/forms/model_forms.py:274 ipam/forms/model_forms.py:327 -#: ipam/forms/model_forms.py:490 ipam/forms/model_forms.py:510 -#: ipam/forms/model_forms.py:524 ipam/models/ip.py:232 ipam/models/ip.py:544 -#: ipam/models/ip.py:777 ipam/models/vrfs.py:64 ipam/tables/ip.py:192 -#: ipam/tables/ip.py:263 ipam/tables/ip.py:316 ipam/tables/ip.py:418 -#: ipam/ui/panels.py:103 ipam/ui/panels.py:112 ipam/ui/panels.py:140 -#: virtualization/forms/bulk_edit.py:270 -#: virtualization/forms/bulk_import.py:245 -#: virtualization/forms/filtersets.py:298 -#: virtualization/forms/model_forms.py:440 -#: virtualization/models/virtualmachines.py:487 -#: virtualization/tables/virtualmachines.py:154 virtualization/ui/panels.py:106 +#: netbox/dcim/filtersets.py:2143 netbox/dcim/forms/bulk_edit.py:1568 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/forms/filtersets.py:1748 +#: netbox/dcim/forms/model_forms.py:1618 +#: netbox/dcim/models/device_components.py:942 +#: netbox/dcim/tables/devices.py:678 netbox/dcim/ui/panels.py:521 +#: netbox/ipam/filtersets.py:372 netbox/ipam/filtersets.py:384 +#: netbox/ipam/filtersets.py:523 netbox/ipam/filtersets.py:630 +#: netbox/ipam/filtersets.py:642 netbox/ipam/forms/bulk_edit.py:195 +#: netbox/ipam/forms/bulk_edit.py:245 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_import.py:170 netbox/ipam/forms/bulk_import.py:255 +#: netbox/ipam/forms/bulk_import.py:291 netbox/ipam/forms/filtersets.py:70 +#: netbox/ipam/forms/filtersets.py:199 netbox/ipam/forms/filtersets.py:353 +#: netbox/ipam/forms/model_forms.py:69 netbox/ipam/forms/model_forms.py:210 +#: netbox/ipam/forms/model_forms.py:274 netbox/ipam/forms/model_forms.py:327 +#: netbox/ipam/forms/model_forms.py:490 netbox/ipam/forms/model_forms.py:510 +#: netbox/ipam/forms/model_forms.py:524 netbox/ipam/models/ip.py:232 +#: netbox/ipam/models/ip.py:544 netbox/ipam/models/ip.py:777 +#: netbox/ipam/models/vrfs.py:64 netbox/ipam/tables/ip.py:192 +#: netbox/ipam/tables/ip.py:263 netbox/ipam/tables/ip.py:316 +#: netbox/ipam/tables/ip.py:418 netbox/ipam/ui/panels.py:103 +#: netbox/ipam/ui/panels.py:112 netbox/ipam/ui/panels.py:140 +#: netbox/virtualization/forms/bulk_edit.py:274 +#: netbox/virtualization/forms/bulk_import.py:245 +#: netbox/virtualization/forms/filtersets.py:298 +#: netbox/virtualization/forms/model_forms.py:440 +#: netbox/virtualization/models/virtualmachines.py:487 +#: netbox/virtualization/tables/virtualmachines.py:154 +#: netbox/virtualization/ui/panels.py:106 msgid "VRF" msgstr "" -#: dcim/filtersets.py:2150 ipam/filtersets.py:379 ipam/filtersets.py:390 -#: ipam/filtersets.py:530 ipam/filtersets.py:637 ipam/filtersets.py:648 +#: netbox/dcim/filtersets.py:2150 netbox/ipam/filtersets.py:379 +#: netbox/ipam/filtersets.py:390 netbox/ipam/filtersets.py:530 +#: netbox/ipam/filtersets.py:637 netbox/ipam/filtersets.py:648 msgid "VRF (RD)" msgstr "" -#: dcim/filtersets.py:2155 ipam/filtersets.py:1096 vpn/filtersets.py:385 +#: netbox/dcim/filtersets.py:2155 netbox/ipam/filtersets.py:1096 +#: netbox/vpn/filtersets.py:385 msgid "L2VPN (ID)" msgstr "" -#: dcim/filtersets.py:2161 dcim/forms/filtersets.py:1753 -#: dcim/tables/devices.py:618 dcim/ui/panels.py:501 ipam/filtersets.py:1102 -#: ipam/forms/filtersets.py:628 ipam/tables/vlans.py:120 ipam/ui/panels.py:207 -#: virtualization/forms/filtersets.py:303 vpn/forms/bulk_import.py:285 -#: vpn/forms/filtersets.py:268 vpn/forms/model_forms.py:407 -#: vpn/forms/model_forms.py:425 vpn/models/l2vpn.py:68 vpn/tables/l2vpn.py:55 -#: vpn/ui/panels.py:101 +#: netbox/dcim/filtersets.py:2161 netbox/dcim/forms/filtersets.py:1753 +#: netbox/dcim/tables/devices.py:618 netbox/dcim/ui/panels.py:501 +#: netbox/ipam/filtersets.py:1102 netbox/ipam/forms/filtersets.py:628 +#: netbox/ipam/tables/vlans.py:120 netbox/ipam/ui/panels.py:207 +#: netbox/virtualization/forms/filtersets.py:303 +#: netbox/vpn/forms/bulk_import.py:285 netbox/vpn/forms/filtersets.py:268 +#: netbox/vpn/forms/model_forms.py:407 netbox/vpn/forms/model_forms.py:425 +#: netbox/vpn/models/l2vpn.py:68 netbox/vpn/tables/l2vpn.py:55 +#: netbox/vpn/ui/panels.py:101 msgid "L2VPN" msgstr "" -#: dcim/filtersets.py:2167 ipam/filtersets.py:1182 +#: netbox/dcim/filtersets.py:2167 netbox/ipam/filtersets.py:1182 msgid "VLAN Translation Policy (ID)" msgstr "" -#: dcim/filtersets.py:2174 dcim/forms/filtersets.py:1719 -#: dcim/forms/model_forms.py:1635 dcim/models/device_components.py:743 -#: ipam/forms/filtersets.py:546 ipam/forms/model_forms.py:733 -#: virtualization/forms/bulk_edit.py:275 virtualization/forms/filtersets.py:313 -#: virtualization/forms/model_forms.py:445 +#: netbox/dcim/filtersets.py:2174 netbox/dcim/forms/filtersets.py:1719 +#: netbox/dcim/forms/model_forms.py:1635 +#: netbox/dcim/models/device_components.py:743 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:733 +#: netbox/virtualization/forms/bulk_edit.py:279 +#: netbox/virtualization/forms/filtersets.py:313 +#: netbox/virtualization/forms/model_forms.py:445 msgid "VLAN Translation Policy" msgstr "" -#: dcim/filtersets.py:2208 +#: netbox/dcim/filtersets.py:2208 msgid "Virtual Chassis Interfaces for Device when device is master" msgstr "" -#: dcim/filtersets.py:2213 +#: netbox/dcim/filtersets.py:2213 msgid "Virtual Chassis Interfaces for Device when device is master (ID)" msgstr "" -#: dcim/filtersets.py:2218 +#: netbox/dcim/filtersets.py:2218 msgid "Virtual Chassis Interfaces for Device" msgstr "" -#: dcim/filtersets.py:2223 +#: netbox/dcim/filtersets.py:2223 msgid "Virtual Chassis Interfaces for Device (ID)" msgstr "" -#: dcim/filtersets.py:2227 +#: netbox/dcim/filtersets.py:2227 msgid "Kind of interface" msgstr "" -#: dcim/filtersets.py:2233 virtualization/filtersets.py:360 +#: netbox/dcim/filtersets.py:2233 netbox/virtualization/filtersets.py:360 msgid "Parent interface (ID)" msgstr "" -#: dcim/filtersets.py:2239 virtualization/filtersets.py:366 +#: netbox/dcim/filtersets.py:2239 netbox/virtualization/filtersets.py:366 msgid "Bridged interface (ID)" msgstr "" -#: dcim/filtersets.py:2245 +#: netbox/dcim/filtersets.py:2245 msgid "LAG interface (ID)" msgstr "" -#: dcim/filtersets.py:2254 dcim/tables/devices.py:1226 -#: virtualization/ui/panels.py:104 +#: netbox/dcim/filtersets.py:2254 netbox/dcim/tables/devices.py:1226 +#: netbox/virtualization/ui/panels.py:104 msgid "MAC Address" msgstr "" -#: dcim/filtersets.py:2260 virtualization/filtersets.py:376 +#: netbox/dcim/filtersets.py:2260 netbox/virtualization/filtersets.py:376 msgid "Primary MAC address (ID)" msgstr "" -#: dcim/filtersets.py:2267 dcim/forms/model_forms.py:1622 -#: virtualization/filtersets.py:383 virtualization/forms/model_forms.py:383 +#: netbox/dcim/filtersets.py:2267 netbox/dcim/forms/model_forms.py:1622 +#: netbox/virtualization/filtersets.py:383 +#: netbox/virtualization/forms/model_forms.py:383 msgid "Primary MAC address" msgstr "" -#: dcim/filtersets.py:2294 dcim/filtersets.py:2306 -#: dcim/forms/filtersets.py:1655 dcim/forms/model_forms.py:1958 +#: netbox/dcim/filtersets.py:2294 netbox/dcim/filtersets.py:2306 +#: netbox/dcim/forms/filtersets.py:1655 netbox/dcim/forms/model_forms.py:1958 msgid "Virtual Device Context" msgstr "" -#: dcim/filtersets.py:2300 +#: netbox/dcim/filtersets.py:2300 msgid "Virtual Device Context (Identifier)" msgstr "" -#: dcim/filtersets.py:2311 wireless/forms/model_forms.py:54 +#: netbox/dcim/filtersets.py:2311 netbox/wireless/forms/model_forms.py:54 msgid "Wireless LAN" msgstr "" -#: dcim/filtersets.py:2316 dcim/tables/devices.py:665 +#: netbox/dcim/filtersets.py:2316 netbox/dcim/tables/devices.py:665 msgid "Wireless link" msgstr "" -#: dcim/filtersets.py:2326 +#: netbox/dcim/filtersets.py:2326 msgid "Virtual circuit termination (ID)" msgstr "" -#: dcim/filtersets.py:2421 +#: netbox/dcim/filtersets.py:2421 msgid "Parent module bay (ID)" msgstr "" -#: dcim/filtersets.py:2426 +#: netbox/dcim/filtersets.py:2426 msgid "Installed module (ID)" msgstr "" -#: dcim/filtersets.py:2439 +#: netbox/dcim/filtersets.py:2439 msgid "Installed device (ID)" msgstr "" -#: dcim/filtersets.py:2446 +#: netbox/dcim/filtersets.py:2446 msgid "Installed device (name)" msgstr "" -#: dcim/filtersets.py:2526 +#: netbox/dcim/filtersets.py:2526 msgid "Master (ID)" msgstr "" -#: dcim/filtersets.py:2533 +#: netbox/dcim/filtersets.py:2533 msgid "Master (name)" msgstr "" -#: dcim/filtersets.py:2639 dcim/forms/filtersets.py:1289 +#: netbox/dcim/filtersets.py:2639 netbox/dcim/forms/filtersets.py:1289 msgid "Unterminated" msgstr "" -#: dcim/filtersets.py:2643 +#: netbox/dcim/filtersets.py:2643 msgid "Cable bundle (ID)" msgstr "" -#: dcim/filtersets.py:2649 +#: netbox/dcim/filtersets.py:2649 msgid "Cable bundle (name)" msgstr "" -#: dcim/filtersets.py:2921 +#: netbox/dcim/filtersets.py:2921 msgid "Power panel (ID)" msgstr "" -#: dcim/forms/bulk_create.py:42 extras/forms/filtersets.py:496 -#: extras/forms/model_forms.py:675 extras/forms/model_forms.py:760 -#: extras/forms/model_forms.py:812 extras/ui/panels.py:103 -#: netbox/forms/bulk_import.py:27 netbox/forms/mixins.py:131 -#: netbox/tables/columns.py:495 -#: templates/circuits/inc/circuit_termination.html:29 -#: templates/circuits/panels/circuit_circuit_termination.html:29 -#: templates/generic/bulk_edit.html:78 templates/inc/panels/tags.html:5 -#: utilities/forms/fields/fields.py:124 +#: netbox/dcim/forms/bulk_create.py:42 netbox/extras/forms/filtersets.py:496 +#: netbox/extras/forms/model_forms.py:675 +#: netbox/extras/forms/model_forms.py:760 +#: netbox/extras/forms/model_forms.py:812 netbox/extras/ui/panels.py:103 +#: netbox/netbox/forms/bulk_import.py:27 netbox/netbox/forms/mixins.py:131 +#: netbox/netbox/tables/columns.py:495 +#: netbox/templates/circuits/inc/circuit_termination.html:29 +#: netbox/templates/circuits/panels/circuit_circuit_termination.html:29 +#: netbox/templates/generic/bulk_edit.html:78 +#: netbox/templates/inc/panels/tags.html:5 +#: netbox/utilities/forms/fields/fields.py:124 msgid "Tags" msgstr "" -#: dcim/forms/bulk_create.py:120 dcim/forms/filtersets.py:1902 -#: dcim/forms/filtersets.py:1921 dcim/forms/model_forms.py:640 -#: dcim/forms/model_forms.py:706 dcim/forms/object_create.py:155 -#: dcim/forms/object_create.py:256 dcim/tables/devices.py:169 -#: templates/dcim/panels/front_port_mappings.html:9 -#: templates/dcim/panels/rear_port_mappings.html:9 -#: templates/dcim/panels/virtual_chassis_members.html:9 -#: templates/dcim/virtualchassis_edit.html:67 +#: netbox/dcim/forms/bulk_create.py:120 netbox/dcim/forms/filtersets.py:1902 +#: netbox/dcim/forms/filtersets.py:1921 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/model_forms.py:706 netbox/dcim/forms/object_create.py:155 +#: netbox/dcim/forms/object_create.py:256 netbox/dcim/tables/devices.py:169 +#: netbox/templates/dcim/panels/front_port_mappings.html:9 +#: netbox/templates/dcim/panels/rear_port_mappings.html:9 +#: netbox/templates/dcim/panels/virtual_chassis_members.html:9 +#: netbox/templates/dcim/virtualchassis_edit.html:67 msgid "Position" msgstr "" -#: dcim/forms/bulk_create.py:122 +#: netbox/dcim/forms/bulk_create.py:122 msgid "" "Alphanumeric ranges are supported. (Must match the number of names being " "created.)" msgstr "" -#: dcim/forms/bulk_edit.py:136 dcim/forms/bulk_edit.py:200 -#: dcim/forms/filtersets.py:275 +#: netbox/dcim/forms/bulk_edit.py:136 netbox/dcim/forms/bulk_edit.py:200 +#: netbox/dcim/forms/filtersets.py:275 msgid "Facility" msgstr "" -#: dcim/forms/bulk_edit.py:146 +#: netbox/dcim/forms/bulk_edit.py:146 msgid "Contact name" msgstr "" -#: dcim/forms/bulk_edit.py:151 +#: netbox/dcim/forms/bulk_edit.py:151 msgid "Contact phone" msgstr "" -#: dcim/forms/bulk_edit.py:157 +#: netbox/dcim/forms/bulk_edit.py:157 msgid "Contact E-mail" msgstr "" -#: dcim/forms/bulk_edit.py:160 dcim/forms/bulk_import.py:140 -#: dcim/forms/model_forms.py:159 +#: netbox/dcim/forms/bulk_edit.py:160 netbox/dcim/forms/bulk_import.py:140 +#: netbox/dcim/forms/model_forms.py:159 msgid "Time zone" msgstr "" -#: dcim/forms/bulk_edit.py:235 dcim/forms/bulk_edit.py:508 -#: dcim/forms/bulk_edit.py:584 dcim/forms/bulk_edit.py:656 -#: dcim/forms/bulk_edit.py:675 dcim/forms/bulk_edit.py:762 -#: dcim/forms/bulk_edit.py:1306 dcim/forms/bulk_edit.py:1742 -#: dcim/forms/bulk_import.py:208 dcim/forms/bulk_import.py:432 -#: dcim/forms/bulk_import.py:482 dcim/forms/bulk_import.py:566 -#: dcim/forms/bulk_import.py:602 dcim/forms/bulk_import.py:1233 -#: dcim/forms/filtersets.py:355 dcim/forms/filtersets.py:426 -#: dcim/forms/filtersets.py:578 dcim/forms/filtersets.py:728 -#: dcim/forms/filtersets.py:834 dcim/forms/filtersets.py:917 -#: dcim/forms/filtersets.py:1133 dcim/forms/filtersets.py:1988 -#: dcim/forms/filtersets.py:2028 dcim/forms/model_forms.py:263 -#: dcim/forms/model_forms.py:399 dcim/forms/model_forms.py:411 -#: dcim/forms/model_forms.py:481 dcim/forms/model_forms.py:585 -#: dcim/forms/model_forms.py:1302 dcim/forms/model_forms.py:1785 -#: dcim/forms/object_import.py:204 dcim/tables/devices.py:101 -#: dcim/tables/devices.py:176 dcim/tables/devices.py:1067 -#: dcim/tables/devicetypes.py:87 dcim/tables/devicetypes.py:328 -#: dcim/tables/modules.py:47 dcim/tables/modules.py:92 dcim/tables/racks.py:75 -#: dcim/tables/racks.py:149 templates/dcim/panels/module_type.html:7 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:508 +#: netbox/dcim/forms/bulk_edit.py:584 netbox/dcim/forms/bulk_edit.py:656 +#: netbox/dcim/forms/bulk_edit.py:675 netbox/dcim/forms/bulk_edit.py:762 +#: netbox/dcim/forms/bulk_edit.py:1306 netbox/dcim/forms/bulk_edit.py:1742 +#: netbox/dcim/forms/bulk_import.py:208 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:482 netbox/dcim/forms/bulk_import.py:566 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/bulk_import.py:1233 +#: netbox/dcim/forms/filtersets.py:355 netbox/dcim/forms/filtersets.py:426 +#: netbox/dcim/forms/filtersets.py:578 netbox/dcim/forms/filtersets.py:728 +#: netbox/dcim/forms/filtersets.py:834 netbox/dcim/forms/filtersets.py:917 +#: netbox/dcim/forms/filtersets.py:1133 netbox/dcim/forms/filtersets.py:1988 +#: netbox/dcim/forms/filtersets.py:2028 netbox/dcim/forms/model_forms.py:263 +#: netbox/dcim/forms/model_forms.py:399 netbox/dcim/forms/model_forms.py:411 +#: netbox/dcim/forms/model_forms.py:481 netbox/dcim/forms/model_forms.py:585 +#: netbox/dcim/forms/model_forms.py:1302 netbox/dcim/forms/model_forms.py:1785 +#: netbox/dcim/forms/object_import.py:204 netbox/dcim/tables/devices.py:101 +#: netbox/dcim/tables/devices.py:176 netbox/dcim/tables/devices.py:1067 +#: netbox/dcim/tables/devicetypes.py:87 netbox/dcim/tables/devicetypes.py:328 +#: netbox/dcim/tables/modules.py:47 netbox/dcim/tables/modules.py:92 +#: netbox/dcim/tables/racks.py:75 netbox/dcim/tables/racks.py:149 +#: netbox/templates/dcim/panels/module_type.html:7 msgid "Manufacturer" msgstr "" -#: dcim/forms/bulk_edit.py:240 dcim/forms/bulk_edit.py:392 -#: dcim/forms/bulk_import.py:217 dcim/forms/bulk_import.py:303 -#: dcim/forms/filtersets.py:301 -#: templates/dcim/inc/panels/racktype_dimensions.html:6 +#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:392 +#: netbox/dcim/forms/bulk_import.py:217 netbox/dcim/forms/bulk_import.py:303 +#: netbox/dcim/forms/filtersets.py:301 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "" -#: dcim/forms/bulk_edit.py:245 dcim/forms/bulk_edit.py:397 -#: dcim/forms/bulk_import.py:225 dcim/forms/bulk_import.py:306 -#: dcim/forms/filtersets.py:306 -#: templates/dcim/inc/panels/racktype_dimensions.html:10 +#: netbox/dcim/forms/bulk_edit.py:245 netbox/dcim/forms/bulk_edit.py:397 +#: netbox/dcim/forms/bulk_import.py:225 netbox/dcim/forms/bulk_import.py:306 +#: netbox/dcim/forms/filtersets.py:306 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "" -#: dcim/forms/bulk_edit.py:251 dcim/forms/bulk_edit.py:403 -#: dcim/forms/bulk_import.py:313 +#: netbox/dcim/forms/bulk_edit.py:251 netbox/dcim/forms/bulk_edit.py:403 +#: netbox/dcim/forms/bulk_import.py:313 msgid "Height (U)" msgstr "" -#: dcim/forms/bulk_edit.py:260 dcim/forms/bulk_edit.py:408 -#: dcim/forms/filtersets.py:320 dcim/ui/panels.py:40 +#: netbox/dcim/forms/bulk_edit.py:260 netbox/dcim/forms/bulk_edit.py:408 +#: netbox/dcim/forms/filtersets.py:320 netbox/dcim/ui/panels.py:40 msgid "Descending units" msgstr "" -#: dcim/forms/bulk_edit.py:263 dcim/forms/bulk_edit.py:411 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:411 msgid "Outer width" msgstr "" -#: dcim/forms/bulk_edit.py:268 dcim/forms/bulk_edit.py:416 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:416 msgid "Outer height" msgstr "" -#: dcim/forms/bulk_edit.py:273 dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:421 msgid "Outer depth" msgstr "" -#: dcim/forms/bulk_edit.py:278 dcim/forms/bulk_edit.py:426 -#: dcim/forms/bulk_import.py:230 dcim/forms/bulk_import.py:316 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:426 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:316 msgid "Outer unit" msgstr "" -#: dcim/forms/bulk_edit.py:283 dcim/forms/bulk_edit.py:431 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:431 msgid "Mounting depth" msgstr "" -#: dcim/forms/bulk_edit.py:288 dcim/forms/bulk_edit.py:309 -#: dcim/forms/bulk_edit.py:441 dcim/forms/bulk_edit.py:465 -#: dcim/forms/bulk_edit.py:542 dcim/forms/bulk_edit.py:559 -#: dcim/forms/bulk_edit.py:598 dcim/forms/bulk_edit.py:614 -#: dcim/forms/bulk_import.py:445 dcim/forms/bulk_import.py:493 -#: dcim/forms/filtersets.py:326 dcim/forms/filtersets.py:348 -#: dcim/forms/filtersets.py:373 dcim/forms/filtersets.py:458 -#: dcim/forms/filtersets.py:571 dcim/forms/filtersets.py:683 -#: dcim/forms/filtersets.py:715 dcim/forms/filtersets.py:788 -#: dcim/forms/model_forms.py:277 dcim/forms/model_forms.py:363 -#: dcim/tables/devicetypes.py:110 dcim/tables/modules.py:55 -#: dcim/tables/racks.py:95 dcim/tables/racks.py:190 dcim/views.py:977 -#: dcim/views.py:1105 extras/forms/bulk_edit.py:57 -#: extras/forms/bulk_edit.py:144 extras/forms/bulk_edit.py:198 -#: extras/forms/bulk_edit.py:226 extras/forms/bulk_edit.py:322 -#: extras/forms/bulk_edit.py:348 extras/forms/filtersets.py:74 -#: extras/forms/filtersets.py:175 extras/forms/filtersets.py:271 -#: extras/forms/filtersets.py:302 ipam/forms/bulk_edit.py:167 +#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:309 +#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:465 +#: netbox/dcim/forms/bulk_edit.py:542 netbox/dcim/forms/bulk_edit.py:559 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/bulk_edit.py:614 +#: netbox/dcim/forms/bulk_import.py:445 netbox/dcim/forms/bulk_import.py:493 +#: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/filtersets.py:348 +#: netbox/dcim/forms/filtersets.py:373 netbox/dcim/forms/filtersets.py:458 +#: netbox/dcim/forms/filtersets.py:571 netbox/dcim/forms/filtersets.py:683 +#: netbox/dcim/forms/filtersets.py:715 netbox/dcim/forms/filtersets.py:788 +#: netbox/dcim/forms/model_forms.py:277 netbox/dcim/forms/model_forms.py:363 +#: netbox/dcim/tables/devicetypes.py:110 netbox/dcim/tables/modules.py:55 +#: netbox/dcim/tables/racks.py:95 netbox/dcim/tables/racks.py:190 +#: netbox/dcim/views.py:977 netbox/dcim/views.py:1105 +#: netbox/extras/forms/bulk_edit.py:57 netbox/extras/forms/bulk_edit.py:144 +#: netbox/extras/forms/bulk_edit.py:198 netbox/extras/forms/bulk_edit.py:226 +#: netbox/extras/forms/bulk_edit.py:322 netbox/extras/forms/bulk_edit.py:348 +#: netbox/extras/forms/filtersets.py:74 netbox/extras/forms/filtersets.py:175 +#: netbox/extras/forms/filtersets.py:271 netbox/extras/forms/filtersets.py:302 +#: netbox/ipam/forms/bulk_edit.py:167 msgid "Weight" msgstr "" -#: dcim/forms/bulk_edit.py:293 dcim/forms/bulk_edit.py:446 -#: dcim/forms/filtersets.py:331 +#: netbox/dcim/forms/bulk_edit.py:293 netbox/dcim/forms/bulk_edit.py:446 +#: netbox/dcim/forms/filtersets.py:331 msgid "Max weight" msgstr "" -#: dcim/forms/bulk_edit.py:298 dcim/forms/bulk_edit.py:451 -#: dcim/forms/bulk_edit.py:547 dcim/forms/bulk_edit.py:603 -#: dcim/forms/bulk_import.py:236 dcim/forms/bulk_import.py:328 -#: dcim/forms/bulk_import.py:450 dcim/forms/bulk_import.py:498 -#: dcim/forms/filtersets.py:336 dcim/forms/filtersets.py:687 -#: dcim/forms/filtersets.py:792 +#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/bulk_edit.py:451 +#: netbox/dcim/forms/bulk_edit.py:547 netbox/dcim/forms/bulk_edit.py:603 +#: netbox/dcim/forms/bulk_import.py:236 netbox/dcim/forms/bulk_import.py:328 +#: netbox/dcim/forms/bulk_import.py:450 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/filtersets.py:336 netbox/dcim/forms/filtersets.py:687 +#: netbox/dcim/forms/filtersets.py:792 msgid "Weight unit" msgstr "" -#: dcim/forms/bulk_edit.py:306 dcim/forms/filtersets.py:346 -#: dcim/forms/model_forms.py:273 dcim/forms/model_forms.py:317 +#: netbox/dcim/forms/bulk_edit.py:306 netbox/dcim/forms/filtersets.py:346 +#: netbox/dcim/forms/model_forms.py:273 netbox/dcim/forms/model_forms.py:317 msgid "Rack Type" msgstr "" -#: dcim/forms/bulk_edit.py:308 dcim/forms/bulk_edit.py:463 -#: dcim/forms/model_forms.py:276 dcim/forms/model_forms.py:362 +#: netbox/dcim/forms/bulk_edit.py:308 netbox/dcim/forms/bulk_edit.py:463 +#: netbox/dcim/forms/model_forms.py:276 netbox/dcim/forms/model_forms.py:362 msgid "Outer Dimensions" msgstr "" -#: dcim/forms/bulk_edit.py:311 dcim/forms/model_forms.py:278 -#: dcim/forms/model_forms.py:364 dcim/ui/panels.py:138 dcim/views.py:971 -#: dcim/views.py:1103 extras/tables/tables.py:282 -#: templates/dcim/inc/panels/racktype_dimensions.html:3 -#: templates/extras/panels/imageattachment_file.html:14 +#: netbox/dcim/forms/bulk_edit.py:311 netbox/dcim/forms/model_forms.py:278 +#: netbox/dcim/forms/model_forms.py:364 netbox/dcim/ui/panels.py:138 +#: netbox/dcim/views.py:971 netbox/dcim/views.py:1103 +#: netbox/extras/tables/tables.py:282 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 +#: netbox/templates/extras/panels/imageattachment_file.html:14 msgid "Dimensions" msgstr "" -#: dcim/forms/bulk_edit.py:313 dcim/forms/filtersets.py:347 -#: dcim/forms/filtersets.py:372 dcim/forms/model_forms.py:280 dcim/views.py:976 -#: dcim/views.py:1104 templates/dcim/inc/panels/racktype_numbering.html:3 +#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/filtersets.py:347 +#: netbox/dcim/forms/filtersets.py:372 netbox/dcim/forms/model_forms.py:280 +#: netbox/dcim/views.py:976 netbox/dcim/views.py:1104 +#: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "" -#: dcim/forms/bulk_edit.py:377 dcim/forms/bulk_import.py:293 -#: dcim/forms/filtersets.py:434 +#: netbox/dcim/forms/bulk_edit.py:377 netbox/dcim/forms/bulk_import.py:293 +#: netbox/dcim/forms/filtersets.py:434 msgid "Rack type" msgstr "" -#: dcim/forms/bulk_edit.py:384 dcim/forms/bulk_edit.py:731 -#: dcim/forms/bulk_edit.py:786 +#: netbox/dcim/forms/bulk_edit.py:384 netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:786 msgid "Serial Number" msgstr "" -#: dcim/forms/bulk_edit.py:387 dcim/forms/filtersets.py:446 -#: dcim/forms/filtersets.py:948 dcim/forms/filtersets.py:1160 -#: dcim/forms/filtersets.py:1995 +#: netbox/dcim/forms/bulk_edit.py:387 netbox/dcim/forms/filtersets.py:446 +#: netbox/dcim/forms/filtersets.py:948 netbox/dcim/forms/filtersets.py:1160 +#: netbox/dcim/forms/filtersets.py:1995 msgid "Asset tag" msgstr "" -#: dcim/forms/bulk_edit.py:436 dcim/forms/bulk_edit.py:537 -#: dcim/forms/bulk_edit.py:593 dcim/forms/bulk_edit.py:724 -#: dcim/forms/bulk_import.py:322 dcim/forms/bulk_import.py:487 -#: dcim/forms/bulk_import.py:696 dcim/forms/filtersets.py:437 -#: dcim/forms/filtersets.py:600 dcim/forms/filtersets.py:783 -#: dcim/forms/filtersets.py:939 +#: netbox/dcim/forms/bulk_edit.py:436 netbox/dcim/forms/bulk_edit.py:537 +#: netbox/dcim/forms/bulk_edit.py:593 netbox/dcim/forms/bulk_edit.py:724 +#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:487 +#: netbox/dcim/forms/bulk_import.py:696 netbox/dcim/forms/filtersets.py:437 +#: netbox/dcim/forms/filtersets.py:600 netbox/dcim/forms/filtersets.py:783 +#: netbox/dcim/forms/filtersets.py:939 msgid "Airflow" msgstr "" -#: dcim/forms/bulk_edit.py:460 dcim/forms/bulk_edit.py:937 -#: dcim/forms/bulk_import.py:378 dcim/forms/bulk_import.py:381 -#: dcim/forms/bulk_import.py:669 dcim/forms/bulk_import.py:1747 -#: dcim/forms/bulk_import.py:1751 dcim/forms/filtersets.py:125 -#: dcim/forms/filtersets.py:370 dcim/forms/filtersets.py:465 -#: dcim/forms/filtersets.py:479 dcim/forms/filtersets.py:525 -#: dcim/forms/filtersets.py:907 dcim/forms/filtersets.py:1123 -#: dcim/forms/filtersets.py:1242 dcim/forms/filtersets.py:1386 -#: dcim/forms/model_forms.py:327 dcim/forms/model_forms.py:371 -#: dcim/forms/model_forms.py:631 dcim/forms/model_forms.py:932 -#: dcim/forms/object_create.py:303 dcim/tables/devices.py:165 -#: dcim/tables/power.py:67 dcim/tables/racks.py:237 -#: ipam/forms/filtersets.py:496 templates/dcim/inc/cable_termination.html:16 -#: templates/dcim/rack/base.html:4 virtualization/forms/model_forms.py:111 +#: netbox/dcim/forms/bulk_edit.py:460 netbox/dcim/forms/bulk_edit.py:937 +#: netbox/dcim/forms/bulk_import.py:378 netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/bulk_import.py:1747 +#: netbox/dcim/forms/bulk_import.py:1751 netbox/dcim/forms/filtersets.py:125 +#: netbox/dcim/forms/filtersets.py:370 netbox/dcim/forms/filtersets.py:465 +#: netbox/dcim/forms/filtersets.py:479 netbox/dcim/forms/filtersets.py:525 +#: netbox/dcim/forms/filtersets.py:907 netbox/dcim/forms/filtersets.py:1123 +#: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1386 +#: netbox/dcim/forms/model_forms.py:327 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/model_forms.py:631 netbox/dcim/forms/model_forms.py:932 +#: netbox/dcim/forms/object_create.py:303 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/tables/power.py:67 netbox/dcim/tables/racks.py:237 +#: netbox/ipam/forms/filtersets.py:496 +#: netbox/templates/dcim/inc/cable_termination.html:16 +#: netbox/templates/dcim/rack/base.html:4 +#: netbox/virtualization/forms/model_forms.py:111 msgid "Rack" msgstr "" -#: dcim/forms/bulk_edit.py:464 dcim/forms/bulk_edit.py:751 -#: dcim/forms/filtersets.py:371 dcim/forms/filtersets.py:457 -#: dcim/forms/filtersets.py:564 dcim/forms/filtersets.py:709 -#: dcim/forms/filtersets.py:855 dcim/forms/filtersets.py:1078 -#: dcim/forms/model_forms.py:489 dcim/forms/model_forms.py:832 -#: dcim/forms/model_forms.py:1853 templates/dcim/device_edit.html:22 +#: netbox/dcim/forms/bulk_edit.py:464 netbox/dcim/forms/bulk_edit.py:751 +#: netbox/dcim/forms/filtersets.py:371 netbox/dcim/forms/filtersets.py:457 +#: netbox/dcim/forms/filtersets.py:564 netbox/dcim/forms/filtersets.py:709 +#: netbox/dcim/forms/filtersets.py:855 netbox/dcim/forms/filtersets.py:1078 +#: netbox/dcim/forms/model_forms.py:489 netbox/dcim/forms/model_forms.py:832 +#: netbox/dcim/forms/model_forms.py:1853 +#: netbox/templates/dcim/device_edit.html:22 msgid "Hardware" msgstr "" -#: dcim/forms/bulk_edit.py:513 dcim/forms/bulk_import.py:438 -#: dcim/forms/filtersets.py:583 dcim/forms/model_forms.py:416 -#: virtualization/forms/bulk_edit.py:87 virtualization/forms/bulk_import.py:89 -#: virtualization/forms/filtersets.py:124 -#: virtualization/forms/model_forms.py:177 -#: virtualization/tables/virtualmachines.py:32 +#: netbox/dcim/forms/bulk_edit.py:513 netbox/dcim/forms/bulk_import.py:438 +#: netbox/dcim/forms/filtersets.py:583 netbox/dcim/forms/model_forms.py:416 +#: netbox/virtualization/forms/bulk_edit.py:87 +#: netbox/virtualization/forms/bulk_import.py:89 +#: netbox/virtualization/forms/filtersets.py:124 +#: netbox/virtualization/forms/model_forms.py:177 +#: netbox/virtualization/tables/virtualmachines.py:32 msgid "Default platform" msgstr "" -#: dcim/forms/bulk_edit.py:518 dcim/forms/bulk_edit.py:589 -#: dcim/forms/filtersets.py:586 dcim/forms/filtersets.py:731 +#: netbox/dcim/forms/bulk_edit.py:518 netbox/dcim/forms/bulk_edit.py:589 +#: netbox/dcim/forms/filtersets.py:586 netbox/dcim/forms/filtersets.py:731 msgid "Part number" msgstr "" -#: dcim/forms/bulk_edit.py:522 +#: netbox/dcim/forms/bulk_edit.py:522 msgid "U height" msgstr "" -#: dcim/forms/bulk_edit.py:534 dcim/tables/devicetypes.py:106 +#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/tables/devicetypes.py:106 msgid "Exclude from utilization" msgstr "" -#: dcim/forms/bulk_edit.py:557 dcim/forms/model_forms.py:430 -#: dcim/forms/model_forms.py:1083 dcim/forms/model_forms.py:1127 -#: dcim/forms/model_forms.py:1154 dcim/forms/model_forms.py:1182 -#: dcim/forms/model_forms.py:1203 dcim/forms/model_forms.py:1243 -#: dcim/forms/model_forms.py:1261 dcim/forms/object_create.py:119 -#: dcim/tables/devicetypes.py:84 dcim/ui/panels.py:128 +#: netbox/dcim/forms/bulk_edit.py:557 netbox/dcim/forms/model_forms.py:430 +#: netbox/dcim/forms/model_forms.py:1083 netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1182 +#: netbox/dcim/forms/model_forms.py:1203 netbox/dcim/forms/model_forms.py:1243 +#: netbox/dcim/forms/model_forms.py:1261 netbox/dcim/forms/object_create.py:119 +#: netbox/dcim/tables/devicetypes.py:84 netbox/dcim/ui/panels.py:128 msgid "Device Type" msgstr "" -#: dcim/forms/bulk_edit.py:566 dcim/forms/model_forms.py:457 dcim/views.py:1684 -#: extras/forms/model_forms.py:670 +#: netbox/dcim/forms/bulk_edit.py:566 netbox/dcim/forms/model_forms.py:457 +#: netbox/dcim/views.py:1684 netbox/extras/forms/model_forms.py:670 msgid "Schema" msgstr "" -#: dcim/forms/bulk_edit.py:572 dcim/forms/bulk_edit.py:579 -#: dcim/forms/bulk_edit.py:828 dcim/forms/bulk_import.py:476 -#: dcim/forms/bulk_import.py:1509 dcim/forms/filtersets.py:723 -#: dcim/forms/filtersets.py:1139 dcim/forms/filtersets.py:1271 -#: dcim/forms/model_forms.py:463 dcim/forms/model_forms.py:476 -#: dcim/tables/modules.py:43 dcim/tables/modules.py:97 -#: extras/forms/filtersets.py:418 extras/forms/model_forms.py:695 -#: extras/tables/tables.py:633 templates/account/base.html:7 -#: templates/dcim/panels/module_type.html:15 templates/inc/user_menu.html:38 -#: vpn/forms/bulk_edit.py:213 vpn/forms/filtersets.py:203 -#: vpn/forms/model_forms.py:378 +#: netbox/dcim/forms/bulk_edit.py:572 netbox/dcim/forms/bulk_edit.py:579 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:476 +#: netbox/dcim/forms/bulk_import.py:1509 netbox/dcim/forms/filtersets.py:723 +#: netbox/dcim/forms/filtersets.py:1139 netbox/dcim/forms/filtersets.py:1271 +#: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:476 +#: netbox/dcim/tables/modules.py:43 netbox/dcim/tables/modules.py:97 +#: netbox/extras/forms/filtersets.py:418 netbox/extras/forms/model_forms.py:695 +#: netbox/extras/tables/tables.py:633 netbox/templates/account/base.html:7 +#: netbox/templates/dcim/panels/module_type.html:15 +#: netbox/templates/inc/user_menu.html:38 netbox/vpn/forms/bulk_edit.py:213 +#: netbox/vpn/forms/filtersets.py:203 netbox/vpn/forms/model_forms.py:378 msgid "Profile" msgstr "" -#: dcim/forms/bulk_edit.py:611 dcim/forms/filtersets.py:1440 -#: dcim/forms/model_forms.py:488 dcim/forms/model_forms.py:1084 -#: dcim/forms/model_forms.py:1128 dcim/forms/model_forms.py:1155 -#: dcim/forms/model_forms.py:1183 dcim/forms/model_forms.py:1204 -#: dcim/forms/model_forms.py:1244 dcim/forms/model_forms.py:1262 -#: dcim/forms/object_create.py:120 dcim/tables/modules.py:52 -#: dcim/tables/modules.py:102 dcim/views.py:2948 +#: netbox/dcim/forms/bulk_edit.py:611 netbox/dcim/forms/filtersets.py:1440 +#: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:1084 +#: netbox/dcim/forms/model_forms.py:1128 netbox/dcim/forms/model_forms.py:1155 +#: netbox/dcim/forms/model_forms.py:1183 netbox/dcim/forms/model_forms.py:1204 +#: netbox/dcim/forms/model_forms.py:1244 netbox/dcim/forms/model_forms.py:1262 +#: netbox/dcim/forms/object_create.py:120 netbox/dcim/tables/modules.py:52 +#: netbox/dcim/tables/modules.py:102 netbox/dcim/views.py:2948 msgid "Module Type" msgstr "" -#: dcim/forms/bulk_edit.py:615 dcim/forms/model_forms.py:433 +#: netbox/dcim/forms/bulk_edit.py:615 netbox/dcim/forms/model_forms.py:433 msgid "Chassis" msgstr "" -#: dcim/forms/bulk_edit.py:634 dcim/models/devices.py:400 -#: dcim/tables/devices.py:76 dcim/ui/panels.py:145 +#: netbox/dcim/forms/bulk_edit.py:634 netbox/dcim/models/devices.py:400 +#: netbox/dcim/tables/devices.py:76 netbox/dcim/ui/panels.py:145 msgid "VM role" msgstr "" -#: dcim/forms/bulk_edit.py:637 dcim/forms/bulk_edit.py:661 -#: dcim/forms/bulk_edit.py:734 dcim/forms/bulk_import.py:540 -#: dcim/forms/bulk_import.py:544 dcim/forms/bulk_import.py:573 -#: dcim/forms/bulk_import.py:577 dcim/forms/bulk_import.py:702 -#: dcim/forms/bulk_import.py:706 dcim/forms/filtersets.py:808 -#: dcim/forms/filtersets.py:839 dcim/forms/filtersets.py:958 -#: dcim/forms/model_forms.py:554 dcim/forms/model_forms.py:591 -#: dcim/forms/model_forms.py:715 virtualization/forms/bulk_import.py:171 -#: virtualization/forms/bulk_import.py:172 -#: virtualization/forms/filtersets.py:255 -#: virtualization/forms/model_forms.py:257 +#: netbox/dcim/forms/bulk_edit.py:637 netbox/dcim/forms/bulk_edit.py:661 +#: netbox/dcim/forms/bulk_edit.py:734 netbox/dcim/forms/bulk_import.py:540 +#: netbox/dcim/forms/bulk_import.py:544 netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:577 netbox/dcim/forms/bulk_import.py:702 +#: netbox/dcim/forms/bulk_import.py:706 netbox/dcim/forms/filtersets.py:808 +#: netbox/dcim/forms/filtersets.py:839 netbox/dcim/forms/filtersets.py:958 +#: netbox/dcim/forms/model_forms.py:554 netbox/dcim/forms/model_forms.py:591 +#: netbox/dcim/forms/model_forms.py:715 +#: netbox/virtualization/forms/bulk_import.py:171 +#: netbox/virtualization/forms/bulk_import.py:172 +#: netbox/virtualization/forms/filtersets.py:255 +#: netbox/virtualization/forms/model_forms.py:257 msgid "Config template" msgstr "" -#: dcim/forms/bulk_edit.py:680 dcim/forms/bulk_edit.py:1086 -#: dcim/forms/bulk_import.py:608 dcim/forms/filtersets.py:135 -#: dcim/forms/filtersets.py:1431 dcim/forms/model_forms.py:661 -#: dcim/forms/model_forms.py:1047 dcim/forms/model_forms.py:1064 -#: extras/filtersets.py:754 +#: netbox/dcim/forms/bulk_edit.py:680 netbox/dcim/forms/bulk_edit.py:1086 +#: netbox/dcim/forms/bulk_import.py:608 netbox/dcim/forms/filtersets.py:135 +#: netbox/dcim/forms/filtersets.py:1431 netbox/dcim/forms/model_forms.py:661 +#: netbox/dcim/forms/model_forms.py:1047 netbox/dcim/forms/model_forms.py:1064 +#: netbox/extras/filtersets.py:754 msgid "Device type" msgstr "" -#: dcim/forms/bulk_edit.py:691 dcim/forms/bulk_import.py:589 -#: dcim/forms/filtersets.py:140 dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/bulk_edit.py:691 netbox/dcim/forms/bulk_import.py:589 +#: netbox/dcim/forms/filtersets.py:140 netbox/dcim/forms/model_forms.py:669 msgid "Device role" msgstr "" -#: dcim/forms/bulk_edit.py:714 dcim/forms/bulk_import.py:614 -#: dcim/forms/filtersets.py:822 dcim/forms/filtersets.py:931 -#: dcim/forms/model_forms.py:602 dcim/forms/model_forms.py:674 -#: dcim/tables/devices.py:191 extras/filtersets.py:770 -#: virtualization/forms/bulk_edit.py:166 -#: virtualization/forms/bulk_import.py:161 -#: virtualization/forms/filtersets.py:235 -#: virtualization/forms/model_forms.py:245 -#: virtualization/tables/virtualmachines.py:89 +#: netbox/dcim/forms/bulk_edit.py:714 netbox/dcim/forms/bulk_import.py:614 +#: netbox/dcim/forms/filtersets.py:822 netbox/dcim/forms/filtersets.py:931 +#: netbox/dcim/forms/model_forms.py:602 netbox/dcim/forms/model_forms.py:674 +#: netbox/dcim/tables/devices.py:191 netbox/extras/filtersets.py:770 +#: netbox/virtualization/forms/bulk_edit.py:166 +#: netbox/virtualization/forms/bulk_import.py:161 +#: netbox/virtualization/forms/filtersets.py:235 +#: netbox/virtualization/forms/model_forms.py:245 +#: netbox/virtualization/tables/virtualmachines.py:89 msgid "Platform" msgstr "" -#: dcim/forms/bulk_edit.py:739 dcim/forms/bulk_import.py:633 -#: dcim/forms/filtersets.py:863 dcim/forms/filtersets.py:1033 -#: dcim/forms/model_forms.py:683 dcim/tables/devices.py:211 -#: extras/filtersets.py:803 extras/forms/filtersets.py:411 -#: ipam/forms/filtersets.py:462 ipam/forms/filtersets.py:501 -#: virtualization/filtersets.py:200 virtualization/filtersets.py:341 -#: virtualization/forms/bulk_edit.py:134 -#: virtualization/forms/bulk_import.py:131 -#: virtualization/forms/filtersets.py:153 -#: virtualization/forms/filtersets.py:185 -#: virtualization/forms/filtersets.py:274 -#: virtualization/forms/model_forms.py:76 -#: virtualization/forms/model_forms.py:213 -#: virtualization/tables/virtualmachines.py:77 +#: netbox/dcim/forms/bulk_edit.py:739 netbox/dcim/forms/bulk_import.py:633 +#: netbox/dcim/forms/filtersets.py:863 netbox/dcim/forms/filtersets.py:1033 +#: netbox/dcim/forms/model_forms.py:683 netbox/dcim/tables/devices.py:211 +#: netbox/extras/filtersets.py:803 netbox/extras/forms/filtersets.py:411 +#: netbox/ipam/forms/filtersets.py:462 netbox/ipam/forms/filtersets.py:501 +#: netbox/virtualization/filtersets.py:200 +#: netbox/virtualization/filtersets.py:341 +#: netbox/virtualization/forms/bulk_edit.py:134 +#: netbox/virtualization/forms/bulk_import.py:131 +#: netbox/virtualization/forms/filtersets.py:153 +#: netbox/virtualization/forms/filtersets.py:185 +#: netbox/virtualization/forms/filtersets.py:274 +#: netbox/virtualization/forms/model_forms.py:76 +#: netbox/virtualization/forms/model_forms.py:213 +#: netbox/virtualization/tables/virtualmachines.py:77 msgid "Cluster" msgstr "" -#: dcim/forms/bulk_edit.py:752 templates/extras/dashboard/widget_config.html:7 -#: virtualization/forms/bulk_edit.py:192 +#: netbox/dcim/forms/bulk_edit.py:752 +#: netbox/templates/extras/dashboard/widget_config.html:7 +#: netbox/virtualization/forms/bulk_edit.py:192 msgid "Configuration" msgstr "" -#: dcim/forms/bulk_edit.py:753 netbox/navigation/menu.py:262 -#: templates/dcim/device_edit.html:80 +#: netbox/dcim/forms/bulk_edit.py:753 netbox/netbox/navigation/menu.py:262 +#: netbox/templates/dcim/device_edit.html:80 msgid "Virtualization" msgstr "" -#: dcim/forms/bulk_edit.py:767 dcim/forms/bulk_import.py:775 -#: dcim/forms/model_forms.py:810 dcim/forms/model_forms.py:1072 +#: netbox/dcim/forms/bulk_edit.py:767 netbox/dcim/forms/bulk_import.py:775 +#: netbox/dcim/forms/model_forms.py:810 netbox/dcim/forms/model_forms.py:1072 msgid "Module type" msgstr "" -#: dcim/forms/bulk_edit.py:839 dcim/forms/bulk_import.py:1528 -#: dcim/forms/filtersets.py:1298 dcim/forms/model_forms.py:887 -#: dcim/tables/cables.py:124 +#: netbox/dcim/forms/bulk_edit.py:839 netbox/dcim/forms/bulk_import.py:1528 +#: netbox/dcim/forms/filtersets.py:1298 netbox/dcim/forms/model_forms.py:887 +#: netbox/dcim/tables/cables.py:124 msgid "Bundle" msgstr "" -#: dcim/forms/bulk_edit.py:844 dcim/forms/bulk_edit.py:1009 -#: dcim/forms/bulk_edit.py:1028 dcim/forms/bulk_edit.py:1051 -#: dcim/forms/bulk_edit.py:1093 dcim/forms/bulk_edit.py:1141 -#: dcim/forms/bulk_edit.py:1192 dcim/forms/bulk_edit.py:1219 -#: dcim/forms/bulk_edit.py:1246 dcim/forms/bulk_edit.py:1269 -#: dcim/forms/bulk_edit.py:1292 dcim/forms/filtersets.py:88 -#: dcim/forms/object_create.py:48 -#: templates/dcim/inc/panels/inventory_items.html:19 -#: templates/dcim/panels/component_inventory_items.html:9 -#: templates/extras/panels/customfieldchoiceset_choices.html:10 -#: templates/generic/bulk_import.html:193 +#: netbox/dcim/forms/bulk_edit.py:844 netbox/dcim/forms/bulk_edit.py:1009 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1051 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_edit.py:1141 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1246 netbox/dcim/forms/bulk_edit.py:1269 +#: netbox/dcim/forms/bulk_edit.py:1292 netbox/dcim/forms/filtersets.py:88 +#: netbox/dcim/forms/object_create.py:48 +#: netbox/templates/dcim/inc/panels/inventory_items.html:19 +#: netbox/templates/dcim/panels/component_inventory_items.html:9 +#: netbox/templates/extras/panels/customfieldchoiceset_choices.html:10 +#: netbox/templates/generic/bulk_import.html:193 msgid "Label" msgstr "" -#: dcim/forms/bulk_edit.py:853 dcim/forms/filtersets.py:1280 +#: netbox/dcim/forms/bulk_edit.py:853 netbox/dcim/forms/filtersets.py:1280 msgid "Length" msgstr "" -#: dcim/forms/bulk_edit.py:858 dcim/forms/bulk_import.py:1535 -#: dcim/forms/bulk_import.py:1538 dcim/forms/filtersets.py:1284 +#: netbox/dcim/forms/bulk_edit.py:858 netbox/dcim/forms/bulk_import.py:1535 +#: netbox/dcim/forms/bulk_import.py:1538 netbox/dcim/forms/filtersets.py:1284 msgid "Length unit" msgstr "" -#: dcim/forms/bulk_edit.py:876 +#: netbox/dcim/forms/bulk_edit.py:876 msgid "Domain" msgstr "" -#: dcim/forms/bulk_edit.py:932 dcim/forms/bulk_import.py:1734 -#: dcim/forms/filtersets.py:1377 dcim/forms/model_forms.py:926 +#: netbox/dcim/forms/bulk_edit.py:932 netbox/dcim/forms/bulk_import.py:1734 +#: netbox/dcim/forms/filtersets.py:1377 netbox/dcim/forms/model_forms.py:926 msgid "Power panel" msgstr "" -#: dcim/forms/bulk_edit.py:954 dcim/forms/bulk_import.py:1770 -#: dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/bulk_import.py:1770 +#: netbox/dcim/forms/filtersets.py:1399 msgid "Supply" msgstr "" -#: dcim/forms/bulk_edit.py:960 dcim/forms/bulk_import.py:1775 -#: dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:960 netbox/dcim/forms/bulk_import.py:1775 +#: netbox/dcim/forms/filtersets.py:1404 msgid "Phase" msgstr "" -#: dcim/forms/bulk_edit.py:966 dcim/forms/filtersets.py:1409 +#: netbox/dcim/forms/bulk_edit.py:966 netbox/dcim/forms/filtersets.py:1409 msgid "Voltage" msgstr "" -#: dcim/forms/bulk_edit.py:970 dcim/forms/filtersets.py:1413 +#: netbox/dcim/forms/bulk_edit.py:970 netbox/dcim/forms/filtersets.py:1413 msgid "Amperage" msgstr "" -#: dcim/forms/bulk_edit.py:974 dcim/forms/filtersets.py:1417 +#: netbox/dcim/forms/bulk_edit.py:974 netbox/dcim/forms/filtersets.py:1417 msgid "Max utilization" msgstr "" -#: dcim/forms/bulk_edit.py:1061 +#: netbox/dcim/forms/bulk_edit.py:1061 msgid "Maximum draw" msgstr "" -#: dcim/forms/bulk_edit.py:1064 dcim/models/device_component_templates.py:302 -#: dcim/models/device_components.py:495 +#: netbox/dcim/forms/bulk_edit.py:1064 +#: netbox/dcim/models/device_component_templates.py:302 +#: netbox/dcim/models/device_components.py:495 msgid "Maximum power draw (watts)" msgstr "" -#: dcim/forms/bulk_edit.py:1067 +#: netbox/dcim/forms/bulk_edit.py:1067 msgid "Allocated draw" msgstr "" -#: dcim/forms/bulk_edit.py:1070 dcim/models/device_component_templates.py:309 -#: dcim/models/device_components.py:502 +#: netbox/dcim/forms/bulk_edit.py:1070 +#: netbox/dcim/models/device_component_templates.py:309 +#: netbox/dcim/models/device_components.py:502 msgid "Allocated power draw (watts)" msgstr "" -#: dcim/forms/bulk_edit.py:1107 dcim/forms/bulk_import.py:908 -#: dcim/forms/model_forms.py:1143 dcim/forms/model_forms.py:1508 -#: dcim/forms/model_forms.py:1837 dcim/forms/object_import.py:56 +#: netbox/dcim/forms/bulk_edit.py:1107 netbox/dcim/forms/bulk_import.py:908 +#: netbox/dcim/forms/model_forms.py:1143 netbox/dcim/forms/model_forms.py:1508 +#: netbox/dcim/forms/model_forms.py:1837 netbox/dcim/forms/object_import.py:56 msgid "Power port" msgstr "" -#: dcim/forms/bulk_edit.py:1112 dcim/forms/bulk_import.py:915 +#: netbox/dcim/forms/bulk_edit.py:1112 netbox/dcim/forms/bulk_import.py:915 msgid "Feed leg" msgstr "" -#: dcim/forms/bulk_edit.py:1158 dcim/forms/bulk_edit.py:1489 -#: dcim/forms/filtersets.py:1780 dcim/ui/panels.py:492 +#: netbox/dcim/forms/bulk_edit.py:1158 netbox/dcim/forms/bulk_edit.py:1489 +#: netbox/dcim/forms/filtersets.py:1780 netbox/dcim/ui/panels.py:492 msgid "Management only" msgstr "" -#: dcim/forms/bulk_edit.py:1168 dcim/forms/bulk_edit.py:1495 -#: dcim/forms/bulk_import.py:1001 dcim/forms/filtersets.py:1704 -#: dcim/forms/filtersets.py:1789 dcim/forms/object_import.py:91 -#: dcim/models/device_component_templates.py:472 -#: dcim/models/device_components.py:914 dcim/ui/panels.py:494 +#: netbox/dcim/forms/bulk_edit.py:1168 netbox/dcim/forms/bulk_edit.py:1495 +#: netbox/dcim/forms/bulk_import.py:1001 netbox/dcim/forms/filtersets.py:1704 +#: netbox/dcim/forms/filtersets.py:1789 netbox/dcim/forms/object_import.py:91 +#: netbox/dcim/models/device_component_templates.py:472 +#: netbox/dcim/models/device_components.py:914 netbox/dcim/ui/panels.py:494 msgid "PoE mode" msgstr "" -#: dcim/forms/bulk_edit.py:1174 dcim/forms/bulk_edit.py:1501 -#: dcim/forms/bulk_import.py:1007 dcim/forms/filtersets.py:1709 -#: dcim/forms/filtersets.py:1794 dcim/forms/object_import.py:96 -#: dcim/models/device_component_templates.py:479 -#: dcim/models/device_components.py:921 dcim/ui/panels.py:495 +#: netbox/dcim/forms/bulk_edit.py:1174 netbox/dcim/forms/bulk_edit.py:1501 +#: netbox/dcim/forms/bulk_import.py:1007 netbox/dcim/forms/filtersets.py:1709 +#: netbox/dcim/forms/filtersets.py:1794 netbox/dcim/forms/object_import.py:96 +#: netbox/dcim/models/device_component_templates.py:479 +#: netbox/dcim/models/device_components.py:921 netbox/dcim/ui/panels.py:495 msgid "PoE type" msgstr "" -#: dcim/forms/bulk_edit.py:1180 dcim/forms/filtersets.py:1724 -#: dcim/forms/filtersets.py:1799 dcim/forms/object_import.py:101 +#: netbox/dcim/forms/bulk_edit.py:1180 netbox/dcim/forms/filtersets.py:1724 +#: netbox/dcim/forms/filtersets.py:1799 netbox/dcim/forms/object_import.py:101 msgid "Wireless role" msgstr "" -#: dcim/forms/bulk_edit.py:1327 dcim/forms/model_forms.py:831 -#: dcim/forms/model_forms.py:1453 dcim/tables/devices.py:330 +#: netbox/dcim/forms/bulk_edit.py:1327 netbox/dcim/forms/model_forms.py:831 +#: netbox/dcim/forms/model_forms.py:1453 netbox/dcim/tables/devices.py:330 msgid "Module" msgstr "" -#: dcim/forms/bulk_edit.py:1469 dcim/tables/devices.py:766 -#: dcim/ui/panels.py:509 +#: netbox/dcim/forms/bulk_edit.py:1469 netbox/dcim/tables/devices.py:766 +#: netbox/dcim/ui/panels.py:509 msgid "LAG" msgstr "" -#: dcim/forms/bulk_edit.py:1474 dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/bulk_edit.py:1474 netbox/dcim/forms/model_forms.py:1535 msgid "Virtual device contexts" msgstr "" -#: dcim/forms/bulk_edit.py:1509 dcim/forms/bulk_import.py:1010 -#: virtualization/forms/bulk_edit.py:242 -#: virtualization/forms/bulk_import.py:205 vpn/forms/bulk_edit.py:128 -#: vpn/forms/bulk_edit.py:196 vpn/forms/bulk_import.py:175 -#: vpn/forms/bulk_import.py:233 vpn/forms/filtersets.py:147 -#: vpn/forms/filtersets.py:192 vpn/forms/filtersets.py:207 -#: vpn/tables/crypto.py:61 vpn/tables/crypto.py:150 +#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/bulk_import.py:1010 +#: netbox/virtualization/forms/bulk_edit.py:246 +#: netbox/virtualization/forms/bulk_import.py:205 +#: netbox/vpn/forms/bulk_edit.py:128 netbox/vpn/forms/bulk_edit.py:196 +#: netbox/vpn/forms/bulk_import.py:175 netbox/vpn/forms/bulk_import.py:233 +#: netbox/vpn/forms/filtersets.py:147 netbox/vpn/forms/filtersets.py:192 +#: netbox/vpn/forms/filtersets.py:207 netbox/vpn/tables/crypto.py:61 +#: netbox/vpn/tables/crypto.py:150 msgid "Mode" msgstr "" -#: dcim/forms/bulk_edit.py:1517 dcim/forms/bulk_import.py:1016 -#: dcim/forms/model_forms.py:1584 ipam/forms/bulk_import.py:184 -#: ipam/forms/filtersets.py:597 ipam/models/vlans.py:92 -#: virtualization/forms/bulk_edit.py:249 -#: virtualization/forms/bulk_import.py:211 -#: virtualization/forms/model_forms.py:407 +#: netbox/dcim/forms/bulk_edit.py:1517 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/model_forms.py:1584 netbox/ipam/forms/bulk_import.py:184 +#: netbox/ipam/forms/filtersets.py:597 netbox/ipam/models/vlans.py:92 +#: netbox/virtualization/forms/bulk_edit.py:253 +#: netbox/virtualization/forms/bulk_import.py:211 +#: netbox/virtualization/forms/model_forms.py:407 msgid "VLAN group" msgstr "" -#: dcim/forms/bulk_edit.py:1526 dcim/forms/bulk_import.py:1023 -#: dcim/forms/model_forms.py:1590 dcim/tables/devices.py:627 -#: dcim/ui/panels.py:498 virtualization/forms/bulk_edit.py:257 -#: virtualization/forms/bulk_import.py:218 -#: virtualization/forms/model_forms.py:412 +#: netbox/dcim/forms/bulk_edit.py:1526 netbox/dcim/forms/bulk_import.py:1023 +#: netbox/dcim/forms/model_forms.py:1590 netbox/dcim/tables/devices.py:627 +#: netbox/dcim/ui/panels.py:498 netbox/virtualization/forms/bulk_edit.py:261 +#: netbox/virtualization/forms/bulk_import.py:218 +#: netbox/virtualization/forms/model_forms.py:412 msgid "Untagged VLAN" msgstr "" -#: dcim/forms/bulk_edit.py:1535 dcim/forms/bulk_import.py:1030 -#: dcim/forms/model_forms.py:1599 dcim/tables/devices.py:633 -#: virtualization/forms/bulk_edit.py:265 -#: virtualization/forms/bulk_import.py:225 -#: virtualization/forms/model_forms.py:421 +#: netbox/dcim/forms/bulk_edit.py:1535 netbox/dcim/forms/bulk_import.py:1030 +#: netbox/dcim/forms/model_forms.py:1599 netbox/dcim/tables/devices.py:633 +#: netbox/virtualization/forms/bulk_edit.py:269 +#: netbox/virtualization/forms/bulk_import.py:225 +#: netbox/virtualization/forms/model_forms.py:421 msgid "Tagged VLANs" msgstr "" -#: dcim/forms/bulk_edit.py:1538 +#: netbox/dcim/forms/bulk_edit.py:1538 msgid "Add tagged VLANs" msgstr "" -#: dcim/forms/bulk_edit.py:1547 +#: netbox/dcim/forms/bulk_edit.py:1547 msgid "Remove tagged VLANs" msgstr "" -#: dcim/forms/bulk_edit.py:1558 dcim/forms/bulk_import.py:1043 -#: dcim/forms/model_forms.py:1608 virtualization/forms/bulk_import.py:238 -#: virtualization/forms/model_forms.py:430 +#: netbox/dcim/forms/bulk_edit.py:1558 netbox/dcim/forms/bulk_import.py:1043 +#: netbox/dcim/forms/model_forms.py:1608 +#: netbox/virtualization/forms/bulk_import.py:238 +#: netbox/virtualization/forms/model_forms.py:430 msgid "Q-in-Q Service VLAN" msgstr "" -#: dcim/forms/bulk_edit.py:1573 dcim/forms/model_forms.py:1571 -#: wireless/forms/filtersets.py:26 +#: netbox/dcim/forms/bulk_edit.py:1573 netbox/dcim/forms/model_forms.py:1571 +#: netbox/wireless/forms/filtersets.py:26 msgid "Wireless LAN group" msgstr "" -#: dcim/forms/bulk_edit.py:1578 dcim/forms/model_forms.py:1576 -#: dcim/tables/devices.py:671 dcim/ui/panels.py:568 -#: netbox/navigation/menu.py:163 wireless/tables/wirelesslan.py:20 +#: netbox/dcim/forms/bulk_edit.py:1578 netbox/dcim/forms/model_forms.py:1576 +#: netbox/dcim/tables/devices.py:671 netbox/dcim/ui/panels.py:568 +#: netbox/netbox/navigation/menu.py:163 +#: netbox/wireless/tables/wirelesslan.py:20 msgid "Wireless LANs" msgstr "" -#: dcim/forms/bulk_edit.py:1587 dcim/forms/filtersets.py:1635 -#: dcim/forms/model_forms.py:1642 dcim/ui/panels.py:513 -#: ipam/forms/bulk_edit.py:232 ipam/forms/bulk_edit.py:318 -#: ipam/forms/filtersets.py:196 netbox/navigation/menu.py:118 -#: templates/ipam/panels/prefix_addressing.html:4 -#: virtualization/forms/filtersets.py:266 -#: virtualization/forms/model_forms.py:450 virtualization/ui/panels.py:101 +#: netbox/dcim/forms/bulk_edit.py:1587 netbox/dcim/forms/filtersets.py:1635 +#: netbox/dcim/forms/model_forms.py:1642 netbox/dcim/ui/panels.py:513 +#: netbox/ipam/forms/bulk_edit.py:232 netbox/ipam/forms/bulk_edit.py:318 +#: netbox/ipam/forms/filtersets.py:196 netbox/netbox/navigation/menu.py:118 +#: netbox/templates/ipam/panels/prefix_addressing.html:4 +#: netbox/virtualization/forms/filtersets.py:266 +#: netbox/virtualization/forms/model_forms.py:450 +#: netbox/virtualization/ui/panels.py:101 msgid "Addressing" msgstr "" -#: dcim/forms/bulk_edit.py:1588 dcim/forms/filtersets.py:854 -#: dcim/forms/model_forms.py:1643 virtualization/forms/model_forms.py:451 +#: netbox/dcim/forms/bulk_edit.py:1588 netbox/dcim/forms/filtersets.py:854 +#: netbox/dcim/forms/model_forms.py:1643 +#: netbox/virtualization/forms/model_forms.py:451 msgid "Operation" msgstr "" -#: dcim/forms/bulk_edit.py:1589 dcim/forms/filtersets.py:1636 -#: dcim/forms/filtersets.py:1763 dcim/forms/model_forms.py:1187 -#: dcim/forms/model_forms.py:1645 +#: netbox/dcim/forms/bulk_edit.py:1589 netbox/dcim/forms/filtersets.py:1636 +#: netbox/dcim/forms/filtersets.py:1763 netbox/dcim/forms/model_forms.py:1187 +#: netbox/dcim/forms/model_forms.py:1645 msgid "PoE" msgstr "" -#: dcim/forms/bulk_edit.py:1590 dcim/forms/model_forms.py:1644 -#: dcim/ui/panels.py:505 virtualization/forms/bulk_edit.py:281 -#: virtualization/forms/model_forms.py:452 +#: netbox/dcim/forms/bulk_edit.py:1590 netbox/dcim/forms/model_forms.py:1644 +#: netbox/dcim/ui/panels.py:505 netbox/virtualization/forms/bulk_edit.py:285 +#: netbox/virtualization/forms/model_forms.py:452 msgid "Related Interfaces" msgstr "" -#: dcim/forms/bulk_edit.py:1592 dcim/forms/filtersets.py:1637 -#: dcim/forms/model_forms.py:1648 virtualization/forms/bulk_edit.py:284 -#: virtualization/forms/filtersets.py:267 -#: virtualization/forms/model_forms.py:455 +#: netbox/dcim/forms/bulk_edit.py:1592 netbox/dcim/forms/filtersets.py:1637 +#: netbox/dcim/forms/model_forms.py:1648 +#: netbox/virtualization/forms/bulk_edit.py:288 +#: netbox/virtualization/forms/filtersets.py:267 +#: netbox/virtualization/forms/model_forms.py:455 msgid "802.1Q Switching" msgstr "" -#: dcim/forms/bulk_edit.py:1597 +#: netbox/dcim/forms/bulk_edit.py:1597 msgid "Add/Remove" msgstr "" -#: dcim/forms/bulk_edit.py:1656 dcim/forms/bulk_edit.py:1658 +#: netbox/dcim/forms/bulk_edit.py:1656 netbox/dcim/forms/bulk_edit.py:1658 msgid "Interface mode must be specified to assign VLANs" msgstr "" -#: dcim/forms/bulk_edit.py:1663 +#: netbox/dcim/forms/bulk_edit.py:1663 msgid "An access interface cannot have tagged VLANs assigned." msgstr "" -#: dcim/forms/bulk_import.py:81 +#: netbox/dcim/forms/bulk_import.py:81 msgid "Name of parent region" msgstr "" -#: dcim/forms/bulk_import.py:95 +#: netbox/dcim/forms/bulk_import.py:95 msgid "Name of parent site group" msgstr "" -#: dcim/forms/bulk_import.py:114 +#: netbox/dcim/forms/bulk_import.py:114 msgid "Assigned region" msgstr "" -#: dcim/forms/bulk_import.py:121 tenancy/forms/bulk_import.py:50 -#: wireless/forms/bulk_import.py:41 +#: netbox/dcim/forms/bulk_import.py:121 netbox/tenancy/forms/bulk_import.py:50 +#: netbox/wireless/forms/bulk_import.py:41 msgid "Assigned group" msgstr "" -#: dcim/forms/bulk_import.py:140 +#: netbox/dcim/forms/bulk_import.py:140 msgid "available options" msgstr "" -#: dcim/forms/bulk_import.py:151 dcim/forms/bulk_import.py:659 -#: dcim/forms/bulk_import.py:1731 ipam/forms/bulk_import.py:519 -#: virtualization/forms/bulk_import.py:66 +#: netbox/dcim/forms/bulk_import.py:151 netbox/dcim/forms/bulk_import.py:659 +#: netbox/dcim/forms/bulk_import.py:1731 netbox/ipam/forms/bulk_import.py:519 +#: netbox/virtualization/forms/bulk_import.py:66 msgid "Assigned site" msgstr "" -#: dcim/forms/bulk_import.py:158 +#: netbox/dcim/forms/bulk_import.py:158 msgid "Parent location" msgstr "" -#: dcim/forms/bulk_import.py:160 +#: netbox/dcim/forms/bulk_import.py:160 msgid "Location not found." msgstr "" -#: dcim/forms/bulk_import.py:211 +#: netbox/dcim/forms/bulk_import.py:211 msgid "The manufacturer of this rack type" msgstr "" -#: dcim/forms/bulk_import.py:222 +#: netbox/dcim/forms/bulk_import.py:222 msgid "The lowest-numbered position in the rack" msgstr "" -#: dcim/forms/bulk_import.py:227 dcim/forms/bulk_import.py:309 +#: netbox/dcim/forms/bulk_import.py:227 netbox/dcim/forms/bulk_import.py:309 msgid "Rail-to-rail width (in inches)" msgstr "" -#: dcim/forms/bulk_import.py:233 dcim/forms/bulk_import.py:319 +#: netbox/dcim/forms/bulk_import.py:233 netbox/dcim/forms/bulk_import.py:319 msgid "Unit for outer dimensions" msgstr "" -#: dcim/forms/bulk_import.py:239 dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:239 netbox/dcim/forms/bulk_import.py:331 msgid "Unit for rack weights" msgstr "" -#: dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_import.py:271 msgid "Name of assigned tenant" msgstr "" -#: dcim/forms/bulk_import.py:274 dcim/forms/filtersets.py:410 -#: dcim/forms/filtersets.py:515 dcim/ui/panels.py:47 -#: ipam/forms/filtersets.py:491 +#: netbox/dcim/forms/bulk_import.py:274 netbox/dcim/forms/filtersets.py:410 +#: netbox/dcim/forms/filtersets.py:515 netbox/dcim/ui/panels.py:47 +#: netbox/ipam/forms/filtersets.py:491 msgid "Rack group" msgstr "" -#: dcim/forms/bulk_import.py:278 +#: netbox/dcim/forms/bulk_import.py:278 msgid "Name of assigned group" msgstr "" -#: dcim/forms/bulk_import.py:290 +#: netbox/dcim/forms/bulk_import.py:290 msgid "Name of assigned role" msgstr "" -#: dcim/forms/bulk_import.py:297 +#: netbox/dcim/forms/bulk_import.py:297 msgid "Rack type model" msgstr "" -#: dcim/forms/bulk_import.py:325 dcim/forms/bulk_import.py:490 -#: dcim/forms/bulk_import.py:699 +#: netbox/dcim/forms/bulk_import.py:325 netbox/dcim/forms/bulk_import.py:490 +#: netbox/dcim/forms/bulk_import.py:699 msgid "Airflow direction" msgstr "" -#: dcim/forms/bulk_import.py:358 +#: netbox/dcim/forms/bulk_import.py:358 msgid "Width must be set if not specifying a rack type." msgstr "" -#: dcim/forms/bulk_import.py:360 +#: netbox/dcim/forms/bulk_import.py:360 msgid "U height must be set if not specifying a rack type." msgstr "" -#: dcim/forms/bulk_import.py:368 +#: netbox/dcim/forms/bulk_import.py:368 msgid "Parent site" msgstr "" -#: dcim/forms/bulk_import.py:375 dcim/forms/bulk_import.py:1744 +#: netbox/dcim/forms/bulk_import.py:375 netbox/dcim/forms/bulk_import.py:1744 msgid "Rack's location (if any)" msgstr "" -#: dcim/forms/bulk_import.py:384 dcim/forms/model_forms.py:376 -#: dcim/tables/racks.py:242 templates/dcim/rackreservation.html:7 +#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/model_forms.py:376 +#: netbox/dcim/tables/racks.py:242 netbox/templates/dcim/rackreservation.html:7 msgid "Units" msgstr "" -#: dcim/forms/bulk_import.py:387 +#: netbox/dcim/forms/bulk_import.py:387 msgid "Comma-separated list of individual unit numbers" msgstr "" -#: dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:435 msgid "The manufacturer which produces this device type" msgstr "" -#: dcim/forms/bulk_import.py:442 +#: netbox/dcim/forms/bulk_import.py:442 msgid "The default platform for devices of this type (optional)" msgstr "" -#: dcim/forms/bulk_import.py:447 +#: netbox/dcim/forms/bulk_import.py:447 msgid "Device weight" msgstr "" -#: dcim/forms/bulk_import.py:453 +#: netbox/dcim/forms/bulk_import.py:453 msgid "Unit for device weight" msgstr "" -#: dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:495 msgid "Module weight" msgstr "" -#: dcim/forms/bulk_import.py:501 +#: netbox/dcim/forms/bulk_import.py:501 msgid "Unit for module weight" msgstr "" -#: dcim/forms/bulk_import.py:506 +#: netbox/dcim/forms/bulk_import.py:506 msgid "Attribute values for the assigned profile, passed as a dictionary" msgstr "" -#: dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:521 msgid "Profile must be specified if attribute data is provided." msgstr "" -#: dcim/forms/bulk_import.py:534 +#: netbox/dcim/forms/bulk_import.py:534 msgid "Parent Device Role" msgstr "" -#: dcim/forms/bulk_import.py:536 +#: netbox/dcim/forms/bulk_import.py:536 msgid "Device role not found." msgstr "" -#: dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:560 msgid "Parent platform" msgstr "" -#: dcim/forms/bulk_import.py:562 +#: netbox/dcim/forms/bulk_import.py:562 msgid "Platform not found." msgstr "" -#: dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:570 msgid "Limit platform assignments to this manufacturer" msgstr "" -#: dcim/forms/bulk_import.py:592 dcim/forms/bulk_import.py:1813 -#: tenancy/forms/bulk_import.py:116 +#: netbox/dcim/forms/bulk_import.py:592 netbox/dcim/forms/bulk_import.py:1813 +#: netbox/tenancy/forms/bulk_import.py:116 msgid "Assigned role" msgstr "" -#: dcim/forms/bulk_import.py:605 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Device type manufacturer" msgstr "" -#: dcim/forms/bulk_import.py:611 +#: netbox/dcim/forms/bulk_import.py:611 msgid "Device type model" msgstr "" -#: dcim/forms/bulk_import.py:618 virtualization/forms/bulk_import.py:165 +#: netbox/dcim/forms/bulk_import.py:618 +#: netbox/virtualization/forms/bulk_import.py:165 msgid "Assigned platform" msgstr "" -#: dcim/forms/bulk_import.py:626 dcim/forms/bulk_import.py:630 -#: dcim/forms/model_forms.py:696 +#: netbox/dcim/forms/bulk_import.py:626 netbox/dcim/forms/bulk_import.py:630 +#: netbox/dcim/forms/model_forms.py:696 msgid "Virtual chassis" msgstr "" -#: dcim/forms/bulk_import.py:637 +#: netbox/dcim/forms/bulk_import.py:637 msgid "Virtualization cluster" msgstr "" -#: dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:666 msgid "Assigned location (if any)" msgstr "" -#: dcim/forms/bulk_import.py:673 +#: netbox/dcim/forms/bulk_import.py:673 msgid "Assigned rack (if any)" msgstr "" -#: dcim/forms/bulk_import.py:676 dcim/forms/model_forms.py:653 +#: netbox/dcim/forms/bulk_import.py:676 netbox/dcim/forms/model_forms.py:653 msgid "Face" msgstr "" -#: dcim/forms/bulk_import.py:679 +#: netbox/dcim/forms/bulk_import.py:679 msgid "Mounted rack face" msgstr "" -#: dcim/forms/bulk_import.py:686 +#: netbox/dcim/forms/bulk_import.py:686 msgid "Parent device (for child devices)" msgstr "" -#: dcim/forms/bulk_import.py:689 +#: netbox/dcim/forms/bulk_import.py:689 msgid "Device bay" msgstr "" -#: dcim/forms/bulk_import.py:693 +#: netbox/dcim/forms/bulk_import.py:693 msgid "Device bay in which this device is installed (for child devices)" msgstr "" -#: dcim/forms/bulk_import.py:766 +#: netbox/dcim/forms/bulk_import.py:766 msgid "The device in which this module is installed" msgstr "" -#: dcim/forms/bulk_import.py:769 dcim/forms/model_forms.py:800 +#: netbox/dcim/forms/bulk_import.py:769 netbox/dcim/forms/model_forms.py:800 msgid "Module bay" msgstr "" -#: dcim/forms/bulk_import.py:772 +#: netbox/dcim/forms/bulk_import.py:772 msgid "The module bay in which this module is installed" msgstr "" -#: dcim/forms/bulk_import.py:778 +#: netbox/dcim/forms/bulk_import.py:778 msgid "The type of module" msgstr "" -#: dcim/forms/bulk_import.py:788 +#: netbox/dcim/forms/bulk_import.py:788 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" msgstr "" -#: dcim/forms/bulk_import.py:832 dcim/forms/bulk_import.py:858 -#: dcim/forms/bulk_import.py:884 +#: netbox/dcim/forms/bulk_import.py:832 netbox/dcim/forms/bulk_import.py:858 +#: netbox/dcim/forms/bulk_import.py:884 msgid "Port type" msgstr "" -#: dcim/forms/bulk_import.py:840 dcim/forms/bulk_import.py:866 +#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/bulk_import.py:866 msgid "Port speed in bps" msgstr "" -#: dcim/forms/bulk_import.py:905 +#: netbox/dcim/forms/bulk_import.py:905 msgid "Outlet type" msgstr "" -#: dcim/forms/bulk_import.py:912 +#: netbox/dcim/forms/bulk_import.py:912 msgid "Local power port which feeds this outlet" msgstr "" -#: dcim/forms/bulk_import.py:918 +#: netbox/dcim/forms/bulk_import.py:918 msgid "Electrical phase (for three-phase circuits)" msgstr "" -#: dcim/forms/bulk_import.py:962 dcim/forms/model_forms.py:1546 -#: virtualization/forms/bulk_import.py:195 -#: virtualization/forms/model_forms.py:391 +#: netbox/dcim/forms/bulk_import.py:962 netbox/dcim/forms/model_forms.py:1546 +#: netbox/virtualization/forms/bulk_import.py:195 +#: netbox/virtualization/forms/model_forms.py:391 msgid "Parent interface" msgstr "" -#: dcim/forms/bulk_import.py:969 dcim/forms/model_forms.py:1554 -#: virtualization/forms/bulk_import.py:202 -#: virtualization/forms/model_forms.py:399 +#: netbox/dcim/forms/bulk_import.py:969 netbox/dcim/forms/model_forms.py:1554 +#: netbox/virtualization/forms/bulk_import.py:202 +#: netbox/virtualization/forms/model_forms.py:399 msgid "Bridged interface" msgstr "" -#: dcim/forms/bulk_import.py:972 +#: netbox/dcim/forms/bulk_import.py:972 msgid "Lag" msgstr "" -#: dcim/forms/bulk_import.py:976 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Parent LAG interface" msgstr "" -#: dcim/forms/bulk_import.py:979 +#: netbox/dcim/forms/bulk_import.py:979 msgid "Vdcs" msgstr "" -#: dcim/forms/bulk_import.py:984 +#: netbox/dcim/forms/bulk_import.py:984 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" -#: dcim/forms/bulk_import.py:990 +#: netbox/dcim/forms/bulk_import.py:990 msgid "Physical medium" msgstr "" -#: dcim/forms/bulk_import.py:993 dcim/forms/filtersets.py:1675 +#: netbox/dcim/forms/bulk_import.py:993 netbox/dcim/forms/filtersets.py:1675 msgid "Duplex" msgstr "" -#: dcim/forms/bulk_import.py:998 +#: netbox/dcim/forms/bulk_import.py:998 msgid "Poe mode" msgstr "" -#: dcim/forms/bulk_import.py:1004 +#: netbox/dcim/forms/bulk_import.py:1004 msgid "Poe type" msgstr "" -#: dcim/forms/bulk_import.py:1013 virtualization/forms/bulk_import.py:208 +#: netbox/dcim/forms/bulk_import.py:1013 +#: netbox/virtualization/forms/bulk_import.py:208 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "" -#: dcim/forms/bulk_import.py:1020 virtualization/forms/bulk_import.py:215 +#: netbox/dcim/forms/bulk_import.py:1020 +#: netbox/virtualization/forms/bulk_import.py:215 msgid "Filter VLANs available for assignment by group" msgstr "" -#: dcim/forms/bulk_import.py:1027 virtualization/forms/bulk_import.py:222 +#: netbox/dcim/forms/bulk_import.py:1027 +#: netbox/virtualization/forms/bulk_import.py:222 msgid "Assigned untagged VLAN ID (filtered by VLAN group)" msgstr "" -#: dcim/forms/bulk_import.py:1036 virtualization/forms/bulk_import.py:231 +#: netbox/dcim/forms/bulk_import.py:1036 +#: netbox/virtualization/forms/bulk_import.py:231 msgid "" "Assigned tagged VLAN IDs separated by commas, encased with double quotes " "(filtered by VLAN group). Example:" msgstr "" -#: dcim/forms/bulk_import.py:1047 virtualization/forms/bulk_import.py:242 +#: netbox/dcim/forms/bulk_import.py:1047 +#: netbox/virtualization/forms/bulk_import.py:242 msgid "Assigned Q-in-Q Service VLAN ID (filtered by VLAN group)" msgstr "" -#: dcim/forms/bulk_import.py:1054 ipam/forms/bulk_import.py:174 -#: ipam/forms/bulk_import.py:259 ipam/forms/bulk_import.py:295 -#: ipam/forms/filtersets.py:230 ipam/forms/filtersets.py:314 -#: ipam/forms/filtersets.py:382 virtualization/forms/bulk_import.py:249 +#: netbox/dcim/forms/bulk_import.py:1054 netbox/ipam/forms/bulk_import.py:174 +#: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 +#: netbox/ipam/forms/filtersets.py:230 netbox/ipam/forms/filtersets.py:314 +#: netbox/ipam/forms/filtersets.py:382 +#: netbox/virtualization/forms/bulk_import.py:249 msgid "Assigned VRF" msgstr "" -#: dcim/forms/bulk_import.py:1057 +#: netbox/dcim/forms/bulk_import.py:1057 msgid "Rf role" msgstr "" -#: dcim/forms/bulk_import.py:1060 +#: netbox/dcim/forms/bulk_import.py:1060 msgid "Wireless role (AP/station)" msgstr "" -#: dcim/forms/bulk_import.py:1103 +#: netbox/dcim/forms/bulk_import.py:1103 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "" -#: dcim/forms/bulk_import.py:1119 dcim/forms/bulk_import.py:1137 -#: dcim/forms/bulk_import.py:1518 +#: netbox/dcim/forms/bulk_import.py:1119 netbox/dcim/forms/bulk_import.py:1137 +#: netbox/dcim/forms/bulk_import.py:1518 msgid "Physical medium classification" msgstr "" -#: dcim/forms/bulk_import.py:1173 +#: netbox/dcim/forms/bulk_import.py:1173 msgid "Installed device" msgstr "" -#: dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1177 msgid "Child device installed within this bay" msgstr "" -#: dcim/forms/bulk_import.py:1179 +#: netbox/dcim/forms/bulk_import.py:1179 msgid "Child device not found." msgstr "" -#: dcim/forms/bulk_import.py:1243 +#: netbox/dcim/forms/bulk_import.py:1243 msgid "Parent inventory item" msgstr "" -#: dcim/forms/bulk_import.py:1246 +#: netbox/dcim/forms/bulk_import.py:1246 msgid "Component type" msgstr "" -#: dcim/forms/bulk_import.py:1250 +#: netbox/dcim/forms/bulk_import.py:1250 msgid "Component Type" msgstr "" -#: dcim/forms/bulk_import.py:1253 +#: netbox/dcim/forms/bulk_import.py:1253 msgid "Component name" msgstr "" -#: dcim/forms/bulk_import.py:1255 +#: netbox/dcim/forms/bulk_import.py:1255 msgid "Component Name" msgstr "" -#: dcim/forms/bulk_import.py:1298 dcim/forms/bulk_import.py:1316 +#: netbox/dcim/forms/bulk_import.py:1298 netbox/dcim/forms/bulk_import.py:1316 msgid "Component name must be specified when component type is specified" msgstr "" -#: dcim/forms/bulk_import.py:1308 +#: netbox/dcim/forms/bulk_import.py:1308 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "" -#: dcim/forms/bulk_import.py:1321 +#: netbox/dcim/forms/bulk_import.py:1321 msgid "Component type must be specified when component name is specified" msgstr "" -#: dcim/forms/bulk_import.py:1348 ipam/forms/bulk_import.py:320 +#: netbox/dcim/forms/bulk_import.py:1348 netbox/ipam/forms/bulk_import.py:320 msgid "Parent device of assigned interface (if any)" msgstr "" -#: dcim/forms/bulk_import.py:1351 ipam/forms/bulk_import.py:323 -#: virtualization/filtersets.py:354 virtualization/filtersets.py:412 -#: virtualization/forms/bulk_edit.py:209 virtualization/forms/bulk_edit.py:351 -#: virtualization/forms/bulk_import.py:186 -#: virtualization/forms/bulk_import.py:287 -#: virtualization/forms/filtersets.py:282 -#: virtualization/forms/filtersets.py:329 -#: virtualization/forms/model_forms.py:367 vpn/forms/bulk_import.py:92 -#: vpn/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:1351 netbox/ipam/forms/bulk_import.py:323 +#: netbox/virtualization/filtersets.py:354 +#: netbox/virtualization/filtersets.py:412 +#: netbox/virtualization/forms/bulk_edit.py:213 +#: netbox/virtualization/forms/bulk_edit.py:355 +#: netbox/virtualization/forms/bulk_import.py:186 +#: netbox/virtualization/forms/bulk_import.py:287 +#: netbox/virtualization/forms/filtersets.py:282 +#: netbox/virtualization/forms/filtersets.py:329 +#: netbox/virtualization/forms/model_forms.py:367 +#: netbox/vpn/forms/bulk_import.py:92 netbox/vpn/forms/bulk_import.py:295 msgid "Virtual machine" msgstr "" -#: dcim/forms/bulk_import.py:1355 ipam/forms/bulk_import.py:327 +#: netbox/dcim/forms/bulk_import.py:1355 netbox/ipam/forms/bulk_import.py:327 msgid "Parent VM of assigned interface (if any)" msgstr "" -#: dcim/forms/bulk_import.py:1362 ipam/filtersets.py:1107 -#: ipam/forms/bulk_import.py:334 +#: netbox/dcim/forms/bulk_import.py:1362 netbox/ipam/filtersets.py:1107 +#: netbox/ipam/forms/bulk_import.py:334 msgid "Assigned interface" msgstr "" -#: dcim/forms/bulk_import.py:1366 +#: netbox/dcim/forms/bulk_import.py:1366 msgid "Make this the primary MAC address for the assigned interface" msgstr "" -#: dcim/forms/bulk_import.py:1404 +#: netbox/dcim/forms/bulk_import.py:1404 msgid "Must specify the parent device or VM when assigning an interface" msgstr "" -#: dcim/forms/bulk_import.py:1437 +#: netbox/dcim/forms/bulk_import.py:1437 msgid "Side A site" msgstr "" -#: dcim/forms/bulk_import.py:1441 wireless/forms/bulk_import.py:93 +#: netbox/dcim/forms/bulk_import.py:1441 +#: netbox/wireless/forms/bulk_import.py:93 msgid "Site of parent device A (if any)" msgstr "" -#: dcim/forms/bulk_import.py:1444 +#: netbox/dcim/forms/bulk_import.py:1444 msgid "Side A device" msgstr "" -#: dcim/forms/bulk_import.py:1448 dcim/forms/bulk_import.py:1481 +#: netbox/dcim/forms/bulk_import.py:1448 netbox/dcim/forms/bulk_import.py:1481 msgid "Device name (for device component terminations)" msgstr "" -#: dcim/forms/bulk_import.py:1451 +#: netbox/dcim/forms/bulk_import.py:1451 msgid "Side A power panel" msgstr "" -#: dcim/forms/bulk_import.py:1455 dcim/forms/bulk_import.py:1488 +#: netbox/dcim/forms/bulk_import.py:1455 netbox/dcim/forms/bulk_import.py:1488 msgid "Power panel name (for power feed terminations)" msgstr "" -#: dcim/forms/bulk_import.py:1458 +#: netbox/dcim/forms/bulk_import.py:1458 msgid "Side A type" msgstr "" -#: dcim/forms/bulk_import.py:1464 +#: netbox/dcim/forms/bulk_import.py:1464 msgid "Side A name" msgstr "" -#: dcim/forms/bulk_import.py:1465 dcim/forms/bulk_import.py:1498 +#: netbox/dcim/forms/bulk_import.py:1465 netbox/dcim/forms/bulk_import.py:1498 msgid "Termination name" msgstr "" -#: dcim/forms/bulk_import.py:1470 +#: netbox/dcim/forms/bulk_import.py:1470 msgid "Side B site" msgstr "" -#: dcim/forms/bulk_import.py:1474 wireless/forms/bulk_import.py:114 +#: netbox/dcim/forms/bulk_import.py:1474 +#: netbox/wireless/forms/bulk_import.py:114 msgid "Site of parent device B (if any)" msgstr "" -#: dcim/forms/bulk_import.py:1477 +#: netbox/dcim/forms/bulk_import.py:1477 msgid "Side B device" msgstr "" -#: dcim/forms/bulk_import.py:1484 +#: netbox/dcim/forms/bulk_import.py:1484 msgid "Side B power panel" msgstr "" -#: dcim/forms/bulk_import.py:1491 +#: netbox/dcim/forms/bulk_import.py:1491 msgid "Side B type" msgstr "" -#: dcim/forms/bulk_import.py:1497 +#: netbox/dcim/forms/bulk_import.py:1497 msgid "Side B name" msgstr "" -#: dcim/forms/bulk_import.py:1506 templates/dcim/panels/connection.html:60 -#: wireless/forms/bulk_import.py:133 +#: netbox/dcim/forms/bulk_import.py:1506 +#: netbox/templates/dcim/panels/connection.html:60 +#: netbox/wireless/forms/bulk_import.py:133 msgid "Connection status" msgstr "" -#: dcim/forms/bulk_import.py:1512 +#: netbox/dcim/forms/bulk_import.py:1512 msgid "Cable connection profile" msgstr "" -#: dcim/forms/bulk_import.py:1532 +#: netbox/dcim/forms/bulk_import.py:1532 msgid "Cable bundle name" msgstr "" -#: dcim/forms/bulk_import.py:1544 +#: netbox/dcim/forms/bulk_import.py:1544 msgid "Color name (e.g. \"Red\") or hex code (e.g. \"f44336\")" msgstr "" -#: dcim/forms/bulk_import.py:1605 +#: netbox/dcim/forms/bulk_import.py:1605 #, python-brace-format msgid "" "Side {side_upper}: {power_panel} {termination_object} is already connected" msgstr "" -#: dcim/forms/bulk_import.py:1611 +#: netbox/dcim/forms/bulk_import.py:1611 #, python-brace-format msgid "{side_upper} side termination not found: {power_panel} {name}" msgstr "" -#: dcim/forms/bulk_import.py:1629 +#: netbox/dcim/forms/bulk_import.py:1629 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "" -#: dcim/forms/bulk_import.py:1635 +#: netbox/dcim/forms/bulk_import.py:1635 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "" -#: dcim/forms/bulk_import.py:1657 +#: netbox/dcim/forms/bulk_import.py:1657 #, python-brace-format msgid "" "{color} did not match any used color name and was longer than six " "characters: invalid hex." msgstr "" -#: dcim/forms/bulk_import.py:1682 dcim/forms/model_forms.py:961 -#: dcim/tables/devices.py:1156 -#: templates/dcim/panels/virtual_chassis_members.html:10 +#: netbox/dcim/forms/bulk_import.py:1682 netbox/dcim/forms/model_forms.py:961 +#: netbox/dcim/tables/devices.py:1156 +#: netbox/templates/dcim/panels/virtual_chassis_members.html:10 msgid "Master" msgstr "" -#: dcim/forms/bulk_import.py:1686 +#: netbox/dcim/forms/bulk_import.py:1686 msgid "Master device" msgstr "" -#: dcim/forms/bulk_import.py:1703 +#: netbox/dcim/forms/bulk_import.py:1703 msgid "Name of parent site" msgstr "" -#: dcim/forms/bulk_import.py:1737 +#: netbox/dcim/forms/bulk_import.py:1737 msgid "Upstream power panel" msgstr "" -#: dcim/forms/bulk_import.py:1767 +#: netbox/dcim/forms/bulk_import.py:1767 msgid "Primary or redundant" msgstr "" -#: dcim/forms/bulk_import.py:1772 +#: netbox/dcim/forms/bulk_import.py:1772 msgid "Supply type (AC/DC)" msgstr "" -#: dcim/forms/bulk_import.py:1777 +#: netbox/dcim/forms/bulk_import.py:1777 msgid "Single or three-phase" msgstr "" -#: dcim/forms/bulk_import.py:1827 dcim/forms/model_forms.py:1938 -#: dcim/ui/panels.py:111 dcim/ui/panels.py:371 virtualization/ui/panels.py:51 +#: netbox/dcim/forms/bulk_import.py:1827 netbox/dcim/forms/model_forms.py:1938 +#: netbox/dcim/ui/panels.py:111 netbox/dcim/ui/panels.py:371 +#: netbox/virtualization/ui/panels.py:51 msgid "Primary IPv4" msgstr "" -#: dcim/forms/bulk_import.py:1831 +#: netbox/dcim/forms/bulk_import.py:1831 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "" -#: dcim/forms/bulk_import.py:1834 dcim/forms/model_forms.py:1947 -#: dcim/ui/panels.py:116 dcim/ui/panels.py:376 virtualization/ui/panels.py:56 +#: netbox/dcim/forms/bulk_import.py:1834 netbox/dcim/forms/model_forms.py:1947 +#: netbox/dcim/ui/panels.py:116 netbox/dcim/ui/panels.py:376 +#: netbox/virtualization/ui/panels.py:56 msgid "Primary IPv6" msgstr "" -#: dcim/forms/bulk_import.py:1838 +#: netbox/dcim/forms/bulk_import.py:1838 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "" -#: dcim/forms/common.py:20 dcim/models/device_components.py:690 -#: dcim/ui/panels.py:490 virtualization/forms/bulk_edit.py:234 -#: virtualization/ui/panels.py:94 +#: netbox/dcim/forms/common.py:20 netbox/dcim/models/device_components.py:690 +#: netbox/dcim/ui/panels.py:490 netbox/virtualization/forms/bulk_edit.py:238 +#: netbox/virtualization/ui/panels.py:94 msgid "MTU" msgstr "" -#: dcim/forms/common.py:60 +#: netbox/dcim/forms/common.py:60 #, python-brace-format msgid "" "The tagged VLANs ({vlans}) must belong to the same site as the interface's " "parent device/VM, or they must be global" msgstr "" -#: dcim/forms/connections.py:59 dcim/forms/model_forms.py:914 -#: dcim/tables/power.py:63 templates/dcim/inc/cable_termination.html:40 -#: templates/dcim/trace/powerpanel.html:4 +#: netbox/dcim/forms/connections.py:59 netbox/dcim/forms/model_forms.py:914 +#: netbox/dcim/tables/power.py:63 +#: netbox/templates/dcim/inc/cable_termination.html:40 +#: netbox/templates/dcim/trace/powerpanel.html:4 msgid "Power Panel" msgstr "" -#: dcim/forms/connections.py:68 dcim/forms/model_forms.py:941 -#: dcim/views.py:3203 +#: netbox/dcim/forms/connections.py:68 netbox/dcim/forms/model_forms.py:941 +#: netbox/dcim/views.py:3203 msgid "Power Feed" msgstr "" -#: dcim/forms/filtersets.py:163 dcim/tables/devices.py:312 +#: netbox/dcim/forms/filtersets.py:163 netbox/dcim/tables/devices.py:312 msgid "Device Status" msgstr "" -#: dcim/forms/filtersets.py:178 +#: netbox/dcim/forms/filtersets.py:178 msgid "Parent region" msgstr "" -#: dcim/forms/filtersets.py:194 tenancy/forms/bulk_import.py:35 -#: tenancy/forms/bulk_import.py:68 tenancy/forms/filtersets.py:46 -#: tenancy/forms/filtersets.py:82 wireless/forms/bulk_import.py:27 -#: wireless/forms/filtersets.py:32 +#: netbox/dcim/forms/filtersets.py:194 netbox/tenancy/forms/bulk_import.py:35 +#: netbox/tenancy/forms/bulk_import.py:68 netbox/tenancy/forms/filtersets.py:46 +#: netbox/tenancy/forms/filtersets.py:82 +#: netbox/wireless/forms/bulk_import.py:27 +#: netbox/wireless/forms/filtersets.py:32 msgid "Parent group" msgstr "" -#: dcim/forms/filtersets.py:358 +#: netbox/dcim/forms/filtersets.py:358 msgid "Rack count" msgstr "" -#: dcim/forms/filtersets.py:456 +#: netbox/dcim/forms/filtersets.py:456 msgid "Function" msgstr "" -#: dcim/forms/filtersets.py:478 dcim/forms/model_forms.py:386 -#: dcim/tables/racks.py:217 dcim/views.py:1254 +#: netbox/dcim/forms/filtersets.py:478 netbox/dcim/forms/model_forms.py:386 +#: netbox/dcim/tables/racks.py:217 netbox/dcim/views.py:1254 msgid "Reservation" msgstr "" -#: dcim/forms/filtersets.py:539 +#: netbox/dcim/forms/filtersets.py:539 msgid "Minimum U's" msgstr "" -#: dcim/forms/filtersets.py:543 +#: netbox/dcim/forms/filtersets.py:543 msgid "Maximum U's" msgstr "" -#: dcim/forms/filtersets.py:566 dcim/forms/model_forms.py:435 -#: netbox/views/generic/feature_views.py:92 -#: templates/inc/panels/image_attachments.html:6 +#: netbox/dcim/forms/filtersets.py:566 netbox/dcim/forms/model_forms.py:435 +#: netbox/netbox/views/generic/feature_views.py:92 +#: netbox/templates/inc/panels/image_attachments.html:6 msgid "Images" msgstr "" -#: dcim/forms/filtersets.py:569 dcim/forms/filtersets.py:713 -#: dcim/forms/filtersets.py:861 +#: netbox/dcim/forms/filtersets.py:569 netbox/dcim/forms/filtersets.py:713 +#: netbox/dcim/forms/filtersets.py:861 msgid "Components" msgstr "" -#: dcim/forms/filtersets.py:590 +#: netbox/dcim/forms/filtersets.py:590 msgid "Device count" msgstr "" -#: dcim/forms/filtersets.py:595 +#: netbox/dcim/forms/filtersets.py:595 msgid "Subdevice role" msgstr "" -#: dcim/forms/filtersets.py:735 +#: netbox/dcim/forms/filtersets.py:735 msgid "Module count" msgstr "" -#: dcim/forms/filtersets.py:802 dcim/forms/model_forms.py:567 +#: netbox/dcim/forms/filtersets.py:802 netbox/dcim/forms/model_forms.py:567 msgid "Device Role" msgstr "" -#: dcim/forms/filtersets.py:925 dcim/tables/racks.py:71 -#: templates/dcim/panels/module_type.html:11 +#: netbox/dcim/forms/filtersets.py:925 netbox/dcim/tables/racks.py:71 +#: netbox/templates/dcim/panels/module_type.html:11 msgid "Model" msgstr "" -#: dcim/forms/filtersets.py:969 +#: netbox/dcim/forms/filtersets.py:969 msgid "Has an OOB IP" msgstr "" -#: dcim/forms/filtersets.py:976 +#: netbox/dcim/forms/filtersets.py:976 msgid "Virtual chassis member" msgstr "" -#: dcim/forms/filtersets.py:1025 +#: netbox/dcim/forms/filtersets.py:1025 msgid "Has virtual device contexts" msgstr "" -#: dcim/forms/filtersets.py:1038 extras/filtersets.py:792 -#: ipam/forms/filtersets.py:506 virtualization/forms/filtersets.py:174 +#: netbox/dcim/forms/filtersets.py:1038 netbox/extras/filtersets.py:792 +#: netbox/ipam/forms/filtersets.py:506 +#: netbox/virtualization/forms/filtersets.py:174 msgid "Cluster group" msgstr "" -#: dcim/forms/filtersets.py:1446 +#: netbox/dcim/forms/filtersets.py:1446 msgid "Cabled" msgstr "" -#: dcim/forms/filtersets.py:1453 +#: netbox/dcim/forms/filtersets.py:1453 msgid "Occupied" msgstr "" -#: dcim/forms/filtersets.py:1658 extras/forms/bulk_edit.py:433 -#: extras/forms/bulk_import.py:332 extras/forms/filtersets.py:595 -#: extras/forms/model_forms.py:877 extras/tables/tables.py:765 +#: netbox/dcim/forms/filtersets.py:1658 netbox/extras/forms/bulk_edit.py:433 +#: netbox/extras/forms/bulk_import.py:332 netbox/extras/forms/filtersets.py:595 +#: netbox/extras/forms/model_forms.py:877 netbox/extras/tables/tables.py:765 msgid "Kind" msgstr "" -#: dcim/forms/filtersets.py:1687 +#: netbox/dcim/forms/filtersets.py:1687 msgid "Mgmt only" msgstr "" -#: dcim/forms/filtersets.py:1699 dcim/forms/model_forms.py:1630 -#: dcim/models/device_components.py:867 dcim/ui/panels.py:520 +#: netbox/dcim/forms/filtersets.py:1699 netbox/dcim/forms/model_forms.py:1630 +#: netbox/dcim/models/device_components.py:867 netbox/dcim/ui/panels.py:520 msgid "WWN" msgstr "" -#: dcim/forms/filtersets.py:1714 dcim/ui/panels.py:496 -#: virtualization/forms/filtersets.py:308 +#: netbox/dcim/forms/filtersets.py:1714 netbox/dcim/ui/panels.py:496 +#: netbox/virtualization/forms/filtersets.py:308 msgid "802.1Q mode" msgstr "" -#: dcim/forms/filtersets.py:1729 +#: netbox/dcim/forms/filtersets.py:1729 msgid "Wireless channel" msgstr "" -#: dcim/forms/filtersets.py:1733 +#: netbox/dcim/forms/filtersets.py:1733 msgid "Channel frequency (MHz)" msgstr "" -#: dcim/forms/filtersets.py:1737 +#: netbox/dcim/forms/filtersets.py:1737 msgid "Channel width (MHz)" msgstr "" -#: dcim/forms/filtersets.py:1741 +#: netbox/dcim/forms/filtersets.py:1741 msgid "Transmit power (dBm)" msgstr "" -#: dcim/forms/filtersets.py:1812 dcim/forms/filtersets.py:1856 -#: dcim/tables/devices.py:344 templates/dcim/cable_trace.html:46 -#: templates/dcim/htmx/cable_edit.html:53 -#: templates/dcim/inc/connection_endpoints.html:4 -#: templates/dcim/panels/connection.html:14 -#: templates/dcim/panels/connection.html:51 -#: templates/dcim/panels/interface_connection.html:13 -#: templates/dcim/trace/cable.html:7 +#: netbox/dcim/forms/filtersets.py:1812 netbox/dcim/forms/filtersets.py:1856 +#: netbox/dcim/tables/devices.py:344 netbox/templates/dcim/cable_trace.html:46 +#: netbox/templates/dcim/htmx/cable_edit.html:53 +#: netbox/templates/dcim/inc/connection_endpoints.html:4 +#: netbox/templates/dcim/panels/connection.html:14 +#: netbox/templates/dcim/panels/connection.html:51 +#: netbox/templates/dcim/panels/interface_connection.html:13 +#: netbox/templates/dcim/trace/cable.html:7 msgid "Cable" msgstr "" -#: dcim/forms/filtersets.py:1999 dcim/tables/devices.py:1076 +#: netbox/dcim/forms/filtersets.py:1999 netbox/dcim/tables/devices.py:1076 msgid "Discovered" msgstr "" -#: dcim/forms/filtersets.py:2065 ipam/forms/filtersets.py:393 +#: netbox/dcim/forms/filtersets.py:2065 netbox/ipam/forms/filtersets.py:393 msgid "Assigned Device" msgstr "" -#: dcim/forms/filtersets.py:2070 ipam/forms/filtersets.py:398 +#: netbox/dcim/forms/filtersets.py:2070 netbox/ipam/forms/filtersets.py:398 msgid "Assigned VM" msgstr "" -#: dcim/forms/filtersets.py:2074 ipam/forms/filtersets.py:412 +#: netbox/dcim/forms/filtersets.py:2074 netbox/ipam/forms/filtersets.py:412 msgid "Assigned to an interface" msgstr "" -#: dcim/forms/filtersets.py:2081 +#: netbox/dcim/forms/filtersets.py:2081 msgid "Primary MAC of an interface" msgstr "" -#: dcim/forms/formsets.py:20 +#: netbox/dcim/forms/formsets.py:20 #, python-brace-format msgid "A virtual chassis member already exists in position {vc_position}." msgstr "" -#: dcim/forms/mixins.py:32 dcim/forms/mixins.py:93 ipam/forms/bulk_edit.py:365 -#: ipam/forms/model_forms.py:630 +#: netbox/dcim/forms/mixins.py:32 netbox/dcim/forms/mixins.py:93 +#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/forms/model_forms.py:630 msgid "Scope type" msgstr "" -#: dcim/forms/mixins.py:35 dcim/forms/mixins.py:96 ipam/forms/bulk_edit.py:233 -#: ipam/forms/bulk_edit.py:368 ipam/forms/bulk_edit.py:387 -#: ipam/forms/filtersets.py:200 ipam/forms/model_forms.py:232 -#: ipam/forms/model_forms.py:264 ipam/forms/model_forms.py:633 -#: ipam/forms/model_forms.py:643 ipam/tables/ip.py:198 ipam/tables/vlans.py:40 -#: virtualization/forms/bulk_edit.py:78 virtualization/forms/filtersets.py:57 -#: virtualization/forms/model_forms.py:77 virtualization/tables/clusters.py:81 -#: wireless/forms/bulk_edit.py:82 wireless/forms/filtersets.py:42 -#: wireless/forms/model_forms.py:55 wireless/tables/wirelesslan.py:51 +#: netbox/dcim/forms/mixins.py:35 netbox/dcim/forms/mixins.py:96 +#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_edit.py:368 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/filtersets.py:200 +#: netbox/ipam/forms/model_forms.py:232 netbox/ipam/forms/model_forms.py:264 +#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/forms/model_forms.py:643 +#: netbox/ipam/tables/ip.py:198 netbox/ipam/tables/vlans.py:40 +#: netbox/virtualization/forms/bulk_edit.py:78 +#: netbox/virtualization/forms/filtersets.py:57 +#: netbox/virtualization/forms/model_forms.py:77 +#: netbox/virtualization/tables/clusters.py:81 +#: netbox/wireless/forms/bulk_edit.py:82 netbox/wireless/forms/filtersets.py:42 +#: netbox/wireless/forms/model_forms.py:55 +#: netbox/wireless/tables/wirelesslan.py:51 msgid "Scope" msgstr "" -#: dcim/forms/mixins.py:61 dcim/forms/mixins.py:172 dcim/models/mixins.py:95 +#: netbox/dcim/forms/mixins.py:61 netbox/dcim/forms/mixins.py:172 +#: netbox/dcim/models/mixins.py:95 #, python-brace-format msgid "Please select a {scope_type}." msgstr "" -#: dcim/forms/mixins.py:122 ipam/forms/bulk_import.py:489 +#: netbox/dcim/forms/mixins.py:122 netbox/ipam/forms/bulk_import.py:489 msgid "Scope type (app & model)" msgstr "" -#: dcim/forms/mixins.py:126 +#: netbox/dcim/forms/mixins.py:126 msgid "Scope name" msgstr "" -#: dcim/forms/mixins.py:127 +#: netbox/dcim/forms/mixins.py:127 msgid "Name of the assigned scope object (if not using ID)" msgstr "" -#: dcim/forms/mixins.py:139 +#: netbox/dcim/forms/mixins.py:139 msgid "scope_name and scope_id are mutually exclusive." msgstr "" -#: dcim/forms/mixins.py:143 +#: netbox/dcim/forms/mixins.py:143 msgid "scope_type must be specified when using scope_name" msgstr "" -#: dcim/forms/mixins.py:145 +#: netbox/dcim/forms/mixins.py:145 msgid "scope_type must be specified when using scope_id" msgstr "" -#: dcim/forms/mixins.py:154 +#: netbox/dcim/forms/mixins.py:154 #, python-brace-format msgid "{scope_type} \"{name}\" not found." msgstr "" -#: dcim/forms/mixins.py:162 +#: netbox/dcim/forms/mixins.py:162 #, python-brace-format msgid "" "Multiple {scope_type} objects match \"{name}\". Use scope_id to specify the " "intended object." msgstr "" -#: dcim/forms/mixins.py:180 dcim/tables/devices.py:260 +#: netbox/dcim/forms/mixins.py:180 netbox/dcim/tables/devices.py:260 msgid "Rear ports" msgstr "" -#: dcim/forms/mixins.py:196 +#: netbox/dcim/forms/mixins.py:196 #, python-brace-format msgid "" "The total number of front port positions ({frontport_count}) must match the " "selected number of rear port positions ({rearport_count})." msgstr "" -#: dcim/forms/model_forms.py:171 +#: netbox/dcim/forms/model_forms.py:171 msgid "Contact Info" msgstr "" -#: dcim/forms/model_forms.py:239 dcim/forms/model_forms.py:307 +#: netbox/dcim/forms/model_forms.py:239 netbox/dcim/forms/model_forms.py:307 msgid "Rack Group" msgstr "" -#: dcim/forms/model_forms.py:251 +#: netbox/dcim/forms/model_forms.py:251 msgid "Rack Role" msgstr "" -#: dcim/forms/model_forms.py:268 dcim/forms/model_forms.py:425 -#: dcim/forms/model_forms.py:596 utilities/forms/fields/fields.py:81 +#: netbox/dcim/forms/model_forms.py:268 netbox/dcim/forms/model_forms.py:425 +#: netbox/dcim/forms/model_forms.py:596 +#: netbox/utilities/forms/fields/fields.py:81 msgid "Slug" msgstr "" -#: dcim/forms/model_forms.py:321 +#: netbox/dcim/forms/model_forms.py:321 msgid "Select a pre-defined rack type, or set physical characteristics below." msgstr "" -#: dcim/forms/model_forms.py:329 +#: netbox/dcim/forms/model_forms.py:329 msgid "Inventory Control" msgstr "" -#: dcim/forms/model_forms.py:378 +#: netbox/dcim/forms/model_forms.py:378 msgid "" "Comma-separated list of numeric unit IDs. A range may be specified using a " "hyphen." msgstr "" -#: dcim/forms/model_forms.py:459 extras/forms/model_forms.py:672 +#: netbox/dcim/forms/model_forms.py:459 netbox/extras/forms/model_forms.py:672 msgid "Enter a valid JSON schema to define supported attributes." msgstr "" -#: dcim/forms/model_forms.py:490 +#: netbox/dcim/forms/model_forms.py:490 msgid "Profile & Attributes" msgstr "" -#: dcim/forms/model_forms.py:642 dcim/models/devices.py:589 +#: netbox/dcim/forms/model_forms.py:642 netbox/dcim/models/devices.py:589 msgid "The lowest-numbered unit occupied by the device" msgstr "" -#: dcim/forms/model_forms.py:707 +#: netbox/dcim/forms/model_forms.py:707 msgid "The position in the virtual chassis this device is identified by" msgstr "" -#: dcim/forms/model_forms.py:712 +#: netbox/dcim/forms/model_forms.py:712 msgid "The priority of the device in the virtual chassis" msgstr "" -#: dcim/forms/model_forms.py:821 +#: netbox/dcim/forms/model_forms.py:821 msgid "Automatically populate components associated with this module type" msgstr "" -#: dcim/forms/model_forms.py:863 templates/dcim/cablebundle.html:14 +#: netbox/dcim/forms/model_forms.py:863 +#: netbox/templates/dcim/cablebundle.html:14 msgid "Cable Bundle" msgstr "" -#: dcim/forms/model_forms.py:943 +#: netbox/dcim/forms/model_forms.py:943 msgid "Characteristics" msgstr "" -#: dcim/forms/model_forms.py:1099 +#: netbox/dcim/forms/model_forms.py:1099 #, python-brace-format msgid "" "Alphanumeric ranges are supported for bulk creation. Mixed cases and types " @@ -5372,3661 +5734,3748 @@ msgid "" "(default is 0))" msgstr "" -#: dcim/forms/model_forms.py:1314 +#: netbox/dcim/forms/model_forms.py:1314 msgid "Console port template" msgstr "" -#: dcim/forms/model_forms.py:1322 +#: netbox/dcim/forms/model_forms.py:1322 msgid "Console server port template" msgstr "" -#: dcim/forms/model_forms.py:1330 +#: netbox/dcim/forms/model_forms.py:1330 msgid "Front port template" msgstr "" -#: dcim/forms/model_forms.py:1338 +#: netbox/dcim/forms/model_forms.py:1338 msgid "Interface template" msgstr "" -#: dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/model_forms.py:1346 msgid "Power outlet template" msgstr "" -#: dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/model_forms.py:1354 msgid "Power port template" msgstr "" -#: dcim/forms/model_forms.py:1362 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Rear port template" msgstr "" -#: dcim/forms/model_forms.py:1372 dcim/forms/model_forms.py:1857 -#: dcim/tables/connections.py:28 dcim/views.py:3113 dcim/views.py:3558 +#: netbox/dcim/forms/model_forms.py:1372 netbox/dcim/forms/model_forms.py:1857 +#: netbox/dcim/tables/connections.py:28 netbox/dcim/views.py:3113 +#: netbox/dcim/views.py:3558 msgid "Console Port" msgstr "" -#: dcim/forms/model_forms.py:1373 dcim/forms/model_forms.py:1858 -#: dcim/views.py:3023 dcim/views.py:3557 +#: netbox/dcim/forms/model_forms.py:1373 netbox/dcim/forms/model_forms.py:1858 +#: netbox/dcim/views.py:3023 netbox/dcim/views.py:3557 msgid "Console Server Port" msgstr "" -#: dcim/forms/model_forms.py:1374 dcim/forms/model_forms.py:1859 -#: dcim/views.py:3025 dcim/views.py:3114 dcim/views.py:3559 dcim/views.py:3660 -#: templates/circuits/circuit_termination/attrs/connection.html:41 -#: templates/circuits/inc/circuit_termination_fields.html:53 -#: templates/dcim/panels/interface_connection.html:86 -#: templates/dcim/panels/rear_port_mappings.html:10 +#: netbox/dcim/forms/model_forms.py:1374 netbox/dcim/forms/model_forms.py:1859 +#: netbox/dcim/views.py:3025 netbox/dcim/views.py:3114 +#: netbox/dcim/views.py:3559 netbox/dcim/views.py:3660 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:41 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:53 +#: netbox/templates/dcim/panels/interface_connection.html:86 +#: netbox/templates/dcim/panels/rear_port_mappings.html:10 msgid "Front Port" msgstr "" -#: dcim/forms/model_forms.py:1375 dcim/forms/model_forms.py:1860 -#: dcim/views.py:3026 dcim/views.py:3115 dcim/views.py:3560 dcim/views.py:3661 -#: templates/circuits/circuit_termination/attrs/connection.html:42 -#: templates/circuits/inc/circuit_termination_fields.html:54 -#: templates/dcim/panels/front_port_mappings.html:10 -#: templates/dcim/panels/interface_connection.html:89 +#: netbox/dcim/forms/model_forms.py:1375 netbox/dcim/forms/model_forms.py:1860 +#: netbox/dcim/views.py:3026 netbox/dcim/views.py:3115 +#: netbox/dcim/views.py:3560 netbox/dcim/views.py:3661 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:42 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:54 +#: netbox/templates/dcim/panels/front_port_mappings.html:10 +#: netbox/templates/dcim/panels/interface_connection.html:89 msgid "Rear Port" msgstr "" -#: dcim/forms/model_forms.py:1376 dcim/forms/model_forms.py:1861 -#: dcim/tables/connections.py:47 dcim/tables/devices.py:539 dcim/views.py:3290 -#: dcim/views.py:4815 +#: netbox/dcim/forms/model_forms.py:1376 netbox/dcim/forms/model_forms.py:1861 +#: netbox/dcim/tables/connections.py:47 netbox/dcim/tables/devices.py:539 +#: netbox/dcim/views.py:3290 netbox/dcim/views.py:4815 msgid "Power Port" msgstr "" -#: dcim/forms/model_forms.py:1377 dcim/forms/model_forms.py:1862 -#: dcim/views.py:3202 +#: netbox/dcim/forms/model_forms.py:1377 netbox/dcim/forms/model_forms.py:1862 +#: netbox/dcim/views.py:3202 msgid "Power Outlet" msgstr "" -#: dcim/forms/model_forms.py:1379 dcim/forms/model_forms.py:1864 +#: netbox/dcim/forms/model_forms.py:1379 netbox/dcim/forms/model_forms.py:1864 msgid "Component Assignment" msgstr "" -#: dcim/forms/model_forms.py:1425 dcim/forms/model_forms.py:1911 +#: netbox/dcim/forms/model_forms.py:1425 netbox/dcim/forms/model_forms.py:1911 msgid "An InventoryItem can only be assigned to a single component." msgstr "" -#: dcim/forms/model_forms.py:1562 +#: netbox/dcim/forms/model_forms.py:1562 msgid "LAG interface" msgstr "" -#: dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1585 msgid "Filter VLANs available for assignment by group." msgstr "" -#: dcim/forms/model_forms.py:1754 +#: netbox/dcim/forms/model_forms.py:1754 msgid "Child Device" msgstr "" -#: dcim/forms/model_forms.py:1755 +#: netbox/dcim/forms/model_forms.py:1755 msgid "" "Child devices must first be created and assigned to the site and rack of the " "parent device." msgstr "" -#: dcim/forms/model_forms.py:1797 +#: netbox/dcim/forms/model_forms.py:1797 msgid "Console port" msgstr "" -#: dcim/forms/model_forms.py:1805 +#: netbox/dcim/forms/model_forms.py:1805 msgid "Console server port" msgstr "" -#: dcim/forms/model_forms.py:1813 dcim/forms/object_import.py:140 +#: netbox/dcim/forms/model_forms.py:1813 netbox/dcim/forms/object_import.py:140 msgid "Front port" msgstr "" -#: dcim/forms/model_forms.py:1829 +#: netbox/dcim/forms/model_forms.py:1829 msgid "Power outlet" msgstr "" -#: dcim/forms/model_forms.py:1845 dcim/forms/object_import.py:145 +#: netbox/dcim/forms/model_forms.py:1845 netbox/dcim/forms/object_import.py:145 msgid "Rear port" msgstr "" -#: dcim/forms/model_forms.py:1851 +#: netbox/dcim/forms/model_forms.py:1851 msgid "Inventory Item" msgstr "" -#: dcim/forms/model_forms.py:1920 +#: netbox/dcim/forms/model_forms.py:1920 msgid "Inventory Item Role" msgstr "" -#: dcim/forms/model_forms.py:1990 +#: netbox/dcim/forms/model_forms.py:1990 msgid "VM Interface" msgstr "" -#: dcim/forms/model_forms.py:2006 ipam/forms/filtersets.py:669 -#: ipam/forms/model_forms.py:350 ipam/tables/vlans.py:190 -#: virtualization/forms/filtersets.py:264 -#: virtualization/forms/filtersets.py:322 -#: virtualization/forms/model_forms.py:263 -#: virtualization/tables/virtualmachines.py:146 -#: virtualization/tables/virtualmachines.py:202 virtualization/ui/panels.py:76 -#: virtualization/ui/panels.py:88 vpn/choices.py:53 vpn/forms/filtersets.py:315 -#: vpn/forms/model_forms.py:158 vpn/forms/model_forms.py:169 -#: vpn/forms/model_forms.py:271 vpn/forms/model_forms.py:452 +#: netbox/dcim/forms/model_forms.py:2006 netbox/ipam/forms/filtersets.py:669 +#: netbox/ipam/forms/model_forms.py:350 netbox/ipam/tables/vlans.py:190 +#: netbox/virtualization/forms/filtersets.py:264 +#: netbox/virtualization/forms/filtersets.py:322 +#: netbox/virtualization/forms/model_forms.py:263 +#: netbox/virtualization/tables/virtualmachines.py:146 +#: netbox/virtualization/tables/virtualmachines.py:202 +#: netbox/virtualization/ui/panels.py:76 netbox/virtualization/ui/panels.py:88 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:315 +#: netbox/vpn/forms/model_forms.py:158 netbox/vpn/forms/model_forms.py:169 +#: netbox/vpn/forms/model_forms.py:271 netbox/vpn/forms/model_forms.py:452 msgid "Virtual Machine" msgstr "" -#: dcim/forms/model_forms.py:2045 +#: netbox/dcim/forms/model_forms.py:2045 msgid "A MAC address can only be assigned to a single object." msgstr "" -#: dcim/forms/object_create.py:50 dcim/forms/object_create.py:157 -#: dcim/forms/object_create.py:258 +#: netbox/dcim/forms/object_create.py:50 netbox/dcim/forms/object_create.py:157 +#: netbox/dcim/forms/object_create.py:258 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" msgstr "" -#: dcim/forms/object_create.py:74 +#: netbox/dcim/forms/object_create.py:74 #, python-brace-format msgid "" "The provided pattern specifies {value_count} values, but {pattern_count} are " "expected." msgstr "" -#: dcim/forms/object_create.py:312 dcim/tables/devices.py:1162 -#: ipam/tables/fhrp.py:31 ipam/ui/panels.py:185 ipam/views.py:1508 -#: templates/dcim/virtualchassis_edit.html:59 users/views.py:350 +#: netbox/dcim/forms/object_create.py:312 netbox/dcim/tables/devices.py:1162 +#: netbox/ipam/tables/fhrp.py:31 netbox/ipam/ui/panels.py:185 +#: netbox/ipam/views.py:1508 netbox/templates/dcim/virtualchassis_edit.html:59 +#: netbox/users/views.py:364 msgid "Members" msgstr "" -#: dcim/forms/object_create.py:322 +#: netbox/dcim/forms/object_create.py:322 msgid "Initial position" msgstr "" -#: dcim/forms/object_create.py:325 +#: netbox/dcim/forms/object_create.py:325 msgid "" "Position of the first member device. Increases by one for each additional " "member." msgstr "" -#: dcim/forms/object_create.py:330 +#: netbox/dcim/forms/object_create.py:330 msgid "Member Devices" msgstr "" -#: dcim/forms/object_create.py:345 +#: netbox/dcim/forms/object_create.py:345 msgid "A position must be specified for the first VC member." msgstr "" -#: dcim/models/base.py:54 +#: netbox/dcim/models/base.py:54 #, python-brace-format msgid "" "Invalid rear port position ({rear_port_position}): Rear port {name} has only " "{positions} positions." msgstr "" -#: dcim/models/cables.py:60 +#: netbox/dcim/models/cables.py:60 msgid "cable bundle" msgstr "" -#: dcim/models/cables.py:61 +#: netbox/dcim/models/cables.py:61 msgid "cable bundles" msgstr "" -#: dcim/models/cables.py:92 +#: netbox/dcim/models/cables.py:92 msgid "profile" msgstr "" -#: dcim/models/cables.py:105 dcim/models/device_component_templates.py:63 -#: dcim/models/device_components.py:61 extras/models/customfields.py:138 +#: netbox/dcim/models/cables.py:105 +#: netbox/dcim/models/device_component_templates.py:63 +#: netbox/dcim/models/device_components.py:61 +#: netbox/extras/models/customfields.py:138 msgid "label" msgstr "" -#: dcim/models/cables.py:114 +#: netbox/dcim/models/cables.py:114 msgid "length" msgstr "" -#: dcim/models/cables.py:121 +#: netbox/dcim/models/cables.py:121 msgid "length unit" msgstr "" -#: dcim/models/cables.py:140 +#: netbox/dcim/models/cables.py:140 msgid "bundle" msgstr "" -#: dcim/models/cables.py:147 +#: netbox/dcim/models/cables.py:147 msgid "cable" msgstr "" -#: dcim/models/cables.py:148 +#: netbox/dcim/models/cables.py:148 msgid "cables" msgstr "" -#: dcim/models/cables.py:273 +#: netbox/dcim/models/cables.py:273 msgid "Must specify a unit when setting a cable length" msgstr "" -#: dcim/models/cables.py:276 +#: netbox/dcim/models/cables.py:276 msgid "Must define A and B terminations when creating a new cable." msgstr "" -#: dcim/models/cables.py:287 +#: netbox/dcim/models/cables.py:287 msgid "Cannot connect different termination types to same end of cable." msgstr "" -#: dcim/models/cables.py:295 +#: netbox/dcim/models/cables.py:295 #, python-brace-format msgid "Incompatible termination types: {type_a} and {type_b}" msgstr "" -#: dcim/models/cables.py:305 +#: netbox/dcim/models/cables.py:305 msgid "A and B terminations cannot connect to the same object." msgstr "" -#: dcim/models/cables.py:502 ipam/models/asns.py:38 +#: netbox/dcim/models/cables.py:502 netbox/ipam/models/asns.py:38 msgid "end" msgstr "" -#: dcim/models/cables.py:573 +#: netbox/dcim/models/cables.py:573 msgid "cable termination" msgstr "" -#: dcim/models/cables.py:574 +#: netbox/dcim/models/cables.py:574 msgid "cable terminations" msgstr "" -#: dcim/models/cables.py:587 +#: netbox/dcim/models/cables.py:587 #, python-brace-format msgid "" "Cannot connect a cable to {obj_parent} > {obj} because it is marked as " "connected." msgstr "" -#: dcim/models/cables.py:604 +#: netbox/dcim/models/cables.py:604 #, python-brace-format msgid "" "Duplicate termination found for {app_label}.{model} {termination_id}: cable " "{cable_pk}" msgstr "" -#: dcim/models/cables.py:614 +#: netbox/dcim/models/cables.py:614 #, python-brace-format msgid "Cables cannot be terminated to {type_display} interfaces" msgstr "" -#: dcim/models/cables.py:621 +#: netbox/dcim/models/cables.py:621 msgid "Circuit terminations attached to a provider network may not be cabled." msgstr "" -#: dcim/models/cables.py:717 extras/models/configs.py:100 +#: netbox/dcim/models/cables.py:717 netbox/extras/models/configs.py:100 msgid "is active" msgstr "" -#: dcim/models/cables.py:721 +#: netbox/dcim/models/cables.py:721 msgid "is complete" msgstr "" -#: dcim/models/cables.py:725 +#: netbox/dcim/models/cables.py:725 msgid "is split" msgstr "" -#: dcim/models/cables.py:733 +#: netbox/dcim/models/cables.py:733 msgid "cable path" msgstr "" -#: dcim/models/cables.py:734 +#: netbox/dcim/models/cables.py:734 msgid "cable paths" msgstr "" -#: dcim/models/cables.py:821 +#: netbox/dcim/models/cables.py:821 msgid "All originating terminations must be attached to the same link" msgstr "" -#: dcim/models/cables.py:839 +#: netbox/dcim/models/cables.py:839 msgid "All mid-span terminations must have the same termination type" msgstr "" -#: dcim/models/cables.py:847 +#: netbox/dcim/models/cables.py:847 msgid "All mid-span terminations must have the same parent object" msgstr "" -#: dcim/models/cables.py:877 +#: netbox/dcim/models/cables.py:877 msgid "All links must be cable or wireless" msgstr "" -#: dcim/models/cables.py:879 +#: netbox/dcim/models/cables.py:879 msgid "All links must match first link type" msgstr "" -#: dcim/models/device_component_templates.py:58 +#: netbox/dcim/models/device_component_templates.py:58 #, python-brace-format msgid "" "{module} is accepted as a substitution for the module bay position when " "attached to a module type." msgstr "" -#: dcim/models/device_component_templates.py:66 -#: dcim/models/device_components.py:64 +#: netbox/dcim/models/device_component_templates.py:66 +#: netbox/dcim/models/device_components.py:64 msgid "Physical label" msgstr "" -#: dcim/models/device_component_templates.py:111 +#: netbox/dcim/models/device_component_templates.py:111 msgid "Component templates cannot be moved to a different device type." msgstr "" -#: dcim/models/device_component_templates.py:165 +#: netbox/dcim/models/device_component_templates.py:165 msgid "" "A component template cannot be associated with both a device type and a " "module type." msgstr "" -#: dcim/models/device_component_templates.py:169 +#: netbox/dcim/models/device_component_templates.py:169 msgid "" "A component template must be associated with either a device type or a " "module type." msgstr "" -#: dcim/models/device_component_templates.py:230 +#: netbox/dcim/models/device_component_templates.py:230 msgid "console port template" msgstr "" -#: dcim/models/device_component_templates.py:231 +#: netbox/dcim/models/device_component_templates.py:231 msgid "console port templates" msgstr "" -#: dcim/models/device_component_templates.py:265 +#: netbox/dcim/models/device_component_templates.py:265 msgid "console server port template" msgstr "" -#: dcim/models/device_component_templates.py:266 +#: netbox/dcim/models/device_component_templates.py:266 msgid "console server port templates" msgstr "" -#: dcim/models/device_component_templates.py:298 -#: dcim/models/device_components.py:491 +#: netbox/dcim/models/device_component_templates.py:298 +#: netbox/dcim/models/device_components.py:491 msgid "maximum draw" msgstr "" -#: dcim/models/device_component_templates.py:305 -#: dcim/models/device_components.py:498 +#: netbox/dcim/models/device_component_templates.py:305 +#: netbox/dcim/models/device_components.py:498 msgid "allocated draw" msgstr "" -#: dcim/models/device_component_templates.py:315 +#: netbox/dcim/models/device_component_templates.py:315 msgid "power port template" msgstr "" -#: dcim/models/device_component_templates.py:316 +#: netbox/dcim/models/device_component_templates.py:316 msgid "power port templates" msgstr "" -#: dcim/models/device_component_templates.py:336 -#: dcim/models/device_components.py:518 +#: netbox/dcim/models/device_component_templates.py:336 +#: netbox/dcim/models/device_components.py:518 #, python-brace-format msgid "Allocated draw cannot exceed the maximum draw ({maximum_draw}W)." msgstr "" -#: dcim/models/device_component_templates.py:374 -#: dcim/models/device_components.py:640 +#: netbox/dcim/models/device_component_templates.py:374 +#: netbox/dcim/models/device_components.py:640 msgid "feed leg" msgstr "" -#: dcim/models/device_component_templates.py:379 -#: dcim/models/device_components.py:645 +#: netbox/dcim/models/device_component_templates.py:379 +#: netbox/dcim/models/device_components.py:645 msgid "Phase (for three-phase feeds)" msgstr "" -#: dcim/models/device_component_templates.py:385 +#: netbox/dcim/models/device_component_templates.py:385 msgid "power outlet template" msgstr "" -#: dcim/models/device_component_templates.py:386 +#: netbox/dcim/models/device_component_templates.py:386 msgid "power outlet templates" msgstr "" -#: dcim/models/device_component_templates.py:395 +#: netbox/dcim/models/device_component_templates.py:395 #, python-brace-format msgid "Parent power port ({power_port}) must belong to the same device type" msgstr "" -#: dcim/models/device_component_templates.py:401 +#: netbox/dcim/models/device_component_templates.py:401 #, python-brace-format msgid "Parent power port ({power_port}) must belong to the same module type" msgstr "" -#: dcim/models/device_component_templates.py:457 -#: dcim/models/device_components.py:849 +#: netbox/dcim/models/device_component_templates.py:457 +#: netbox/dcim/models/device_components.py:849 msgid "management only" msgstr "" -#: dcim/models/device_component_templates.py:465 -#: dcim/models/device_components.py:714 +#: netbox/dcim/models/device_component_templates.py:465 +#: netbox/dcim/models/device_components.py:714 msgid "bridge interface" msgstr "" -#: dcim/models/device_component_templates.py:486 -#: dcim/models/device_components.py:875 +#: netbox/dcim/models/device_component_templates.py:486 +#: netbox/dcim/models/device_components.py:875 msgid "wireless role" msgstr "" -#: dcim/models/device_component_templates.py:492 +#: netbox/dcim/models/device_component_templates.py:492 msgid "interface template" msgstr "" -#: dcim/models/device_component_templates.py:493 +#: netbox/dcim/models/device_component_templates.py:493 msgid "interface templates" msgstr "" -#: dcim/models/device_component_templates.py:502 +#: netbox/dcim/models/device_component_templates.py:502 #, python-brace-format msgid "Bridge interface ({bridge}) must belong to the same device type" msgstr "" -#: dcim/models/device_component_templates.py:508 +#: netbox/dcim/models/device_component_templates.py:508 #, python-brace-format msgid "Bridge interface ({bridge}) must belong to the same module type" msgstr "" -#: dcim/models/device_component_templates.py:576 +#: netbox/dcim/models/device_component_templates.py:576 #, python-brace-format msgid "Rear port ({rear_port}) must belong to the same device type" msgstr "" -#: dcim/models/device_component_templates.py:610 -#: dcim/models/device_component_templates.py:683 -#: dcim/models/device_components.py:1235 dcim/models/device_components.py:1283 +#: netbox/dcim/models/device_component_templates.py:610 +#: netbox/dcim/models/device_component_templates.py:683 +#: netbox/dcim/models/device_components.py:1235 +#: netbox/dcim/models/device_components.py:1283 msgid "positions" msgstr "" -#: dcim/models/device_component_templates.py:631 +#: netbox/dcim/models/device_component_templates.py:631 msgid "front port template" msgstr "" -#: dcim/models/device_component_templates.py:632 +#: netbox/dcim/models/device_component_templates.py:632 msgid "front port templates" msgstr "" -#: dcim/models/device_component_templates.py:643 +#: netbox/dcim/models/device_component_templates.py:643 #, python-brace-format msgid "" "The number of positions cannot be less than the number of mapped rear port " "templates ({count})" msgstr "" -#: dcim/models/device_component_templates.py:694 +#: netbox/dcim/models/device_component_templates.py:694 msgid "rear port template" msgstr "" -#: dcim/models/device_component_templates.py:695 +#: netbox/dcim/models/device_component_templates.py:695 msgid "rear port templates" msgstr "" -#: dcim/models/device_component_templates.py:706 +#: netbox/dcim/models/device_component_templates.py:706 #, python-brace-format msgid "" "The number of positions cannot be less than the number of mapped front port " "templates ({count})" msgstr "" -#: dcim/models/device_component_templates.py:738 -#: dcim/models/device_components.py:1330 +#: netbox/dcim/models/device_component_templates.py:738 +#: netbox/dcim/models/device_components.py:1330 msgid "position" msgstr "" -#: dcim/models/device_component_templates.py:741 -#: dcim/models/device_components.py:1333 +#: netbox/dcim/models/device_component_templates.py:741 +#: netbox/dcim/models/device_components.py:1333 msgid "Identifier to reference when renaming installed components" msgstr "" -#: dcim/models/device_component_templates.py:751 +#: netbox/dcim/models/device_component_templates.py:751 msgid "module bay template" msgstr "" -#: dcim/models/device_component_templates.py:752 +#: netbox/dcim/models/device_component_templates.py:752 msgid "module bay templates" msgstr "" -#: dcim/models/device_component_templates.py:786 +#: netbox/dcim/models/device_component_templates.py:786 msgid "device bay template" msgstr "" -#: dcim/models/device_component_templates.py:787 +#: netbox/dcim/models/device_component_templates.py:787 msgid "device bay templates" msgstr "" -#: dcim/models/device_component_templates.py:802 +#: netbox/dcim/models/device_component_templates.py:802 #, python-brace-format msgid "" "Subdevice role of device type ({device_type}) must be set to \"parent\" to " "allow device bays." msgstr "" -#: dcim/models/device_component_templates.py:858 -#: dcim/models/device_components.py:1522 +#: netbox/dcim/models/device_component_templates.py:858 +#: netbox/dcim/models/device_components.py:1522 msgid "part ID" msgstr "" -#: dcim/models/device_component_templates.py:860 -#: dcim/models/device_components.py:1524 +#: netbox/dcim/models/device_component_templates.py:860 +#: netbox/dcim/models/device_components.py:1524 msgid "Manufacturer-assigned part identifier" msgstr "" -#: dcim/models/device_component_templates.py:877 +#: netbox/dcim/models/device_component_templates.py:877 msgid "inventory item template" msgstr "" -#: dcim/models/device_component_templates.py:878 +#: netbox/dcim/models/device_component_templates.py:878 msgid "inventory item templates" msgstr "" -#: dcim/models/device_components.py:127 +#: netbox/dcim/models/device_components.py:127 msgid "Components cannot be moved to a different device." msgstr "" -#: dcim/models/device_components.py:174 +#: netbox/dcim/models/device_components.py:174 msgid "cable end" msgstr "" -#: dcim/models/device_components.py:199 +#: netbox/dcim/models/device_components.py:199 msgid "mark connected" msgstr "" -#: dcim/models/device_components.py:201 +#: netbox/dcim/models/device_components.py:201 msgid "Treat as if a cable is connected" msgstr "" -#: dcim/models/device_components.py:220 +#: netbox/dcim/models/device_components.py:220 msgid "Must specify cable end (A or B) when attaching a cable." msgstr "" -#: dcim/models/device_components.py:224 +#: netbox/dcim/models/device_components.py:224 msgid "Must specify position(s) when specifying a cable connector." msgstr "" -#: dcim/models/device_components.py:228 +#: netbox/dcim/models/device_components.py:228 msgid "Cable positions cannot be set without a cable connector." msgstr "" -#: dcim/models/device_components.py:232 +#: netbox/dcim/models/device_components.py:232 msgid "Cannot mark as connected with a cable attached." msgstr "" -#: dcim/models/device_components.py:237 +#: netbox/dcim/models/device_components.py:237 msgid "Cable end must not be set without a cable." msgstr "" -#: dcim/models/device_components.py:241 +#: netbox/dcim/models/device_components.py:241 msgid "Cable connector must not be set without a cable." msgstr "" -#: dcim/models/device_components.py:245 +#: netbox/dcim/models/device_components.py:245 msgid "Cable termination positions must not be set without a cable." msgstr "" -#: dcim/models/device_components.py:296 +#: netbox/dcim/models/device_components.py:296 #, python-brace-format msgid "{class_name} models must declare a parent_object property" msgstr "" -#: dcim/models/device_components.py:430 dcim/models/device_components.py:457 -#: dcim/models/device_components.py:488 dcim/models/device_components.py:630 +#: netbox/dcim/models/device_components.py:430 +#: netbox/dcim/models/device_components.py:457 +#: netbox/dcim/models/device_components.py:488 +#: netbox/dcim/models/device_components.py:630 msgid "Physical port type" msgstr "" -#: dcim/models/device_components.py:433 dcim/models/device_components.py:460 +#: netbox/dcim/models/device_components.py:433 +#: netbox/dcim/models/device_components.py:460 msgid "speed" msgstr "" -#: dcim/models/device_components.py:437 dcim/models/device_components.py:464 +#: netbox/dcim/models/device_components.py:437 +#: netbox/dcim/models/device_components.py:464 msgid "Port speed in bits per second" msgstr "" -#: dcim/models/device_components.py:443 +#: netbox/dcim/models/device_components.py:443 msgid "console port" msgstr "" -#: dcim/models/device_components.py:444 +#: netbox/dcim/models/device_components.py:444 msgid "console ports" msgstr "" -#: dcim/models/device_components.py:470 +#: netbox/dcim/models/device_components.py:470 msgid "console server port" msgstr "" -#: dcim/models/device_components.py:471 +#: netbox/dcim/models/device_components.py:471 msgid "console server ports" msgstr "" -#: dcim/models/device_components.py:508 +#: netbox/dcim/models/device_components.py:508 msgid "power port" msgstr "" -#: dcim/models/device_components.py:509 +#: netbox/dcim/models/device_components.py:509 msgid "power ports" msgstr "" -#: dcim/models/device_components.py:655 +#: netbox/dcim/models/device_components.py:655 msgid "power outlet" msgstr "" -#: dcim/models/device_components.py:656 +#: netbox/dcim/models/device_components.py:656 msgid "power outlets" msgstr "" -#: dcim/models/device_components.py:664 +#: netbox/dcim/models/device_components.py:664 #, python-brace-format msgid "Parent power port ({power_port}) must belong to the same device" msgstr "" -#: dcim/models/device_components.py:693 vpn/models/crypto.py:80 -#: vpn/models/crypto.py:222 +#: netbox/dcim/models/device_components.py:693 netbox/vpn/models/crypto.py:80 +#: netbox/vpn/models/crypto.py:222 msgid "mode" msgstr "" -#: dcim/models/device_components.py:698 +#: netbox/dcim/models/device_components.py:698 msgid "IEEE 802.1Q tagging strategy" msgstr "" -#: dcim/models/device_components.py:706 +#: netbox/dcim/models/device_components.py:706 msgid "parent interface" msgstr "" -#: dcim/models/device_components.py:722 +#: netbox/dcim/models/device_components.py:722 msgid "untagged VLAN" msgstr "" -#: dcim/models/device_components.py:728 +#: netbox/dcim/models/device_components.py:728 msgid "tagged VLANs" msgstr "" -#: dcim/models/device_components.py:736 dcim/tables/devices.py:636 -#: dcim/ui/panels.py:497 ipam/forms/bulk_edit.py:456 -#: ipam/forms/bulk_import.py:554 ipam/forms/filtersets.py:623 -#: ipam/forms/model_forms.py:714 ipam/tables/vlans.py:113 ipam/ui/panels.py:206 -#: virtualization/ui/panels.py:96 +#: netbox/dcim/models/device_components.py:736 +#: netbox/dcim/tables/devices.py:636 netbox/dcim/ui/panels.py:497 +#: netbox/ipam/forms/bulk_edit.py:456 netbox/ipam/forms/bulk_import.py:554 +#: netbox/ipam/forms/filtersets.py:623 netbox/ipam/forms/model_forms.py:714 +#: netbox/ipam/tables/vlans.py:113 netbox/ipam/ui/panels.py:206 +#: netbox/virtualization/ui/panels.py:96 msgid "Q-in-Q SVLAN" msgstr "" -#: dcim/models/device_components.py:751 +#: netbox/dcim/models/device_components.py:751 msgid "primary MAC address" msgstr "" -#: dcim/models/device_components.py:763 +#: netbox/dcim/models/device_components.py:763 msgid "Only Q-in-Q interfaces may specify a service VLAN." msgstr "" -#: dcim/models/device_components.py:774 +#: netbox/dcim/models/device_components.py:774 #, python-brace-format msgid "" "MAC address {mac_address} is assigned to a different interface ({interface})." msgstr "" -#: dcim/models/device_components.py:840 +#: netbox/dcim/models/device_components.py:840 msgid "parent LAG" msgstr "" -#: dcim/models/device_components.py:850 +#: netbox/dcim/models/device_components.py:850 msgid "This interface is used only for out-of-band management" msgstr "" -#: dcim/models/device_components.py:855 +#: netbox/dcim/models/device_components.py:855 msgid "speed (Kbps)" msgstr "" -#: dcim/models/device_components.py:858 +#: netbox/dcim/models/device_components.py:858 msgid "duplex" msgstr "" -#: dcim/models/device_components.py:868 +#: netbox/dcim/models/device_components.py:868 msgid "64-bit World Wide Name" msgstr "" -#: dcim/models/device_components.py:882 +#: netbox/dcim/models/device_components.py:882 msgid "wireless channel" msgstr "" -#: dcim/models/device_components.py:889 +#: netbox/dcim/models/device_components.py:889 msgid "channel frequency (MHz)" msgstr "" -#: dcim/models/device_components.py:890 dcim/models/device_components.py:898 +#: netbox/dcim/models/device_components.py:890 +#: netbox/dcim/models/device_components.py:898 msgid "Populated by selected channel (if set)" msgstr "" -#: dcim/models/device_components.py:907 +#: netbox/dcim/models/device_components.py:907 msgid "transmit power (dBm)" msgstr "" -#: dcim/models/device_components.py:934 wireless/models.py:125 +#: netbox/dcim/models/device_components.py:934 netbox/wireless/models.py:125 msgid "wireless LANs" msgstr "" -#: dcim/models/device_components.py:982 -#: virtualization/models/virtualmachines.py:515 +#: netbox/dcim/models/device_components.py:982 +#: netbox/virtualization/models/virtualmachines.py:515 msgid "interface" msgstr "" -#: dcim/models/device_components.py:983 -#: virtualization/models/virtualmachines.py:516 +#: netbox/dcim/models/device_components.py:983 +#: netbox/virtualization/models/virtualmachines.py:516 msgid "interfaces" msgstr "" -#: dcim/models/device_components.py:991 +#: netbox/dcim/models/device_components.py:991 #, python-brace-format msgid "{display_type} interfaces cannot have a cable attached." msgstr "" -#: dcim/models/device_components.py:999 +#: netbox/dcim/models/device_components.py:999 #, python-brace-format msgid "{display_type} interfaces cannot be marked as connected." msgstr "" -#: dcim/models/device_components.py:1008 -#: virtualization/models/virtualmachines.py:526 +#: netbox/dcim/models/device_components.py:1008 +#: netbox/virtualization/models/virtualmachines.py:526 msgid "An interface cannot be its own parent." msgstr "" -#: dcim/models/device_components.py:1012 +#: netbox/dcim/models/device_components.py:1012 msgid "Only virtual interfaces may be assigned to a parent interface." msgstr "" -#: dcim/models/device_components.py:1019 +#: netbox/dcim/models/device_components.py:1019 #, python-brace-format msgid "" "The selected parent interface ({interface}) belongs to a different device " "({device})" msgstr "" -#: dcim/models/device_components.py:1025 +#: netbox/dcim/models/device_components.py:1025 #, python-brace-format msgid "" "The selected parent interface ({interface}) belongs to {device}, which is " "not part of virtual chassis {virtual_chassis}." msgstr "" -#: dcim/models/device_components.py:1041 +#: netbox/dcim/models/device_components.py:1041 #, python-brace-format msgid "" "The selected bridge interface ({bridge}) belongs to a different device " "({device})." msgstr "" -#: dcim/models/device_components.py:1047 +#: netbox/dcim/models/device_components.py:1047 #, python-brace-format msgid "" "The selected bridge interface ({interface}) belongs to {device}, which is " "not part of virtual chassis {virtual_chassis}." msgstr "" -#: dcim/models/device_components.py:1058 +#: netbox/dcim/models/device_components.py:1058 msgid "Virtual interfaces cannot have a parent LAG interface." msgstr "" -#: dcim/models/device_components.py:1062 +#: netbox/dcim/models/device_components.py:1062 msgid "A LAG interface cannot be its own parent." msgstr "" -#: dcim/models/device_components.py:1069 +#: netbox/dcim/models/device_components.py:1069 #, python-brace-format msgid "" "The selected LAG interface ({lag}) belongs to a different device ({device})." msgstr "" -#: dcim/models/device_components.py:1075 +#: netbox/dcim/models/device_components.py:1075 #, python-brace-format msgid "" "The selected LAG interface ({lag}) belongs to {device}, which is not part of " "virtual chassis {virtual_chassis}." msgstr "" -#: dcim/models/device_components.py:1085 +#: netbox/dcim/models/device_components.py:1085 msgid "Channel may be set only on wireless interfaces." msgstr "" -#: dcim/models/device_components.py:1091 +#: netbox/dcim/models/device_components.py:1091 msgid "Channel frequency may be set only on wireless interfaces." msgstr "" -#: dcim/models/device_components.py:1095 +#: netbox/dcim/models/device_components.py:1095 msgid "Cannot specify custom frequency with channel selected." msgstr "" -#: dcim/models/device_components.py:1101 +#: netbox/dcim/models/device_components.py:1101 msgid "Channel width may be set only on wireless interfaces." msgstr "" -#: dcim/models/device_components.py:1103 +#: netbox/dcim/models/device_components.py:1103 msgid "Cannot specify custom width with channel selected." msgstr "" -#: dcim/models/device_components.py:1107 +#: netbox/dcim/models/device_components.py:1107 msgid "Interface mode does not support an untagged vlan." msgstr "" -#: dcim/models/device_components.py:1113 +#: netbox/dcim/models/device_components.py:1113 #, python-brace-format msgid "" "The untagged VLAN ({untagged_vlan}) must belong to the same site as the " "interface's parent device, or it must be global." msgstr "" -#: dcim/models/device_components.py:1210 +#: netbox/dcim/models/device_components.py:1210 #, python-brace-format msgid "Rear port ({rear_port}) must belong to the same device" msgstr "" -#: dcim/models/device_components.py:1252 +#: netbox/dcim/models/device_components.py:1252 msgid "front port" msgstr "" -#: dcim/models/device_components.py:1253 +#: netbox/dcim/models/device_components.py:1253 msgid "front ports" msgstr "" -#: dcim/models/device_components.py:1264 +#: netbox/dcim/models/device_components.py:1264 #, python-brace-format msgid "" "The number of positions cannot be less than the number of mapped rear ports " "({count})" msgstr "" -#: dcim/models/device_components.py:1294 +#: netbox/dcim/models/device_components.py:1294 msgid "rear port" msgstr "" -#: dcim/models/device_components.py:1295 +#: netbox/dcim/models/device_components.py:1295 msgid "rear ports" msgstr "" -#: dcim/models/device_components.py:1306 +#: netbox/dcim/models/device_components.py:1306 #, python-brace-format msgid "" "The number of positions cannot be less than the number of mapped front ports " "({count})" msgstr "" -#: dcim/models/device_components.py:1354 +#: netbox/dcim/models/device_components.py:1354 msgid "module bay" msgstr "" -#: dcim/models/device_components.py:1355 +#: netbox/dcim/models/device_components.py:1355 msgid "module bays" msgstr "" -#: dcim/models/device_components.py:1369 dcim/models/modules.py:287 +#: netbox/dcim/models/device_components.py:1369 +#: netbox/dcim/models/modules.py:287 msgid "A module bay cannot belong to a module installed within it." msgstr "" -#: dcim/models/device_components.py:1408 +#: netbox/dcim/models/device_components.py:1408 msgid "device bay" msgstr "" -#: dcim/models/device_components.py:1409 +#: netbox/dcim/models/device_components.py:1409 msgid "device bays" msgstr "" -#: dcim/models/device_components.py:1416 +#: netbox/dcim/models/device_components.py:1416 #, python-brace-format msgid "This type of device ({device_type}) does not support device bays." msgstr "" -#: dcim/models/device_components.py:1427 +#: netbox/dcim/models/device_components.py:1427 msgid "Cannot install a device in a disabled device bay." msgstr "" -#: dcim/models/device_components.py:1432 +#: netbox/dcim/models/device_components.py:1432 msgid "Cannot install a device into itself." msgstr "" -#: dcim/models/device_components.py:1440 +#: netbox/dcim/models/device_components.py:1440 #, python-brace-format msgid "" "Cannot install the specified device; device is already installed in {bay}." msgstr "" -#: dcim/models/device_components.py:1468 +#: netbox/dcim/models/device_components.py:1468 msgid "inventory item role" msgstr "" -#: dcim/models/device_components.py:1469 +#: netbox/dcim/models/device_components.py:1469 msgid "inventory item roles" msgstr "" -#: dcim/models/device_components.py:1528 dcim/models/devices.py:552 -#: dcim/models/modules.py:238 dcim/models/racks.py:345 -#: virtualization/models/virtualmachines.py:221 +#: netbox/dcim/models/device_components.py:1528 +#: netbox/dcim/models/devices.py:552 netbox/dcim/models/modules.py:238 +#: netbox/dcim/models/racks.py:345 +#: netbox/virtualization/models/virtualmachines.py:221 msgid "serial number" msgstr "" -#: dcim/models/device_components.py:1536 dcim/models/devices.py:560 -#: dcim/models/modules.py:245 dcim/models/racks.py:352 +#: netbox/dcim/models/device_components.py:1536 +#: netbox/dcim/models/devices.py:560 netbox/dcim/models/modules.py:245 +#: netbox/dcim/models/racks.py:352 msgid "asset tag" msgstr "" -#: dcim/models/device_components.py:1537 +#: netbox/dcim/models/device_components.py:1537 msgid "A unique tag used to identify this item" msgstr "" -#: dcim/models/device_components.py:1540 +#: netbox/dcim/models/device_components.py:1540 msgid "discovered" msgstr "" -#: dcim/models/device_components.py:1542 +#: netbox/dcim/models/device_components.py:1542 msgid "This item was automatically discovered" msgstr "" -#: dcim/models/device_components.py:1560 +#: netbox/dcim/models/device_components.py:1560 msgid "inventory item" msgstr "" -#: dcim/models/device_components.py:1561 +#: netbox/dcim/models/device_components.py:1561 msgid "inventory items" msgstr "" -#: dcim/models/device_components.py:1569 +#: netbox/dcim/models/device_components.py:1569 msgid "Cannot assign self as parent." msgstr "" -#: dcim/models/device_components.py:1577 +#: netbox/dcim/models/device_components.py:1577 msgid "Parent inventory item does not belong to the same device." msgstr "" -#: dcim/models/device_components.py:1583 +#: netbox/dcim/models/device_components.py:1583 msgid "Cannot move an inventory item with dependent children" msgstr "" -#: dcim/models/device_components.py:1591 +#: netbox/dcim/models/device_components.py:1591 msgid "Cannot assign inventory item to component on another device" msgstr "" -#: dcim/models/devices.py:60 +#: netbox/dcim/models/devices.py:60 msgid "manufacturer" msgstr "" -#: dcim/models/devices.py:61 +#: netbox/dcim/models/devices.py:61 msgid "manufacturers" msgstr "" -#: dcim/models/devices.py:85 dcim/models/modules.py:77 dcim/models/racks.py:162 +#: netbox/dcim/models/devices.py:85 netbox/dcim/models/modules.py:77 +#: netbox/dcim/models/racks.py:162 msgid "model" msgstr "" -#: dcim/models/devices.py:98 virtualization/models/virtualmachines.py:54 +#: netbox/dcim/models/devices.py:98 +#: netbox/virtualization/models/virtualmachines.py:54 msgid "default platform" msgstr "" -#: dcim/models/devices.py:101 dcim/models/modules.py:81 +#: netbox/dcim/models/devices.py:101 netbox/dcim/models/modules.py:81 msgid "part number" msgstr "" -#: dcim/models/devices.py:104 dcim/models/modules.py:84 +#: netbox/dcim/models/devices.py:104 netbox/dcim/models/modules.py:84 msgid "Discrete part number (optional)" msgstr "" -#: dcim/models/devices.py:110 dcim/models/racks.py:72 +#: netbox/dcim/models/devices.py:110 netbox/dcim/models/racks.py:72 msgid "height (U)" msgstr "" -#: dcim/models/devices.py:114 +#: netbox/dcim/models/devices.py:114 msgid "exclude from utilization" msgstr "" -#: dcim/models/devices.py:115 +#: netbox/dcim/models/devices.py:115 msgid "Devices of this type are excluded when calculating rack utilization." msgstr "" -#: dcim/models/devices.py:119 +#: netbox/dcim/models/devices.py:119 msgid "is full depth" msgstr "" -#: dcim/models/devices.py:120 +#: netbox/dcim/models/devices.py:120 msgid "Device consumes both front and rear rack faces." msgstr "" -#: dcim/models/devices.py:127 +#: netbox/dcim/models/devices.py:127 msgid "parent/child status" msgstr "" -#: dcim/models/devices.py:128 +#: netbox/dcim/models/devices.py:128 msgid "" "Parent devices house child devices in device bays. Leave blank if this " "device type is neither a parent nor a child." msgstr "" -#: dcim/models/devices.py:132 dcim/models/devices.py:605 -#: dcim/models/modules.py:87 dcim/models/racks.py:356 +#: netbox/dcim/models/devices.py:132 netbox/dcim/models/devices.py:605 +#: netbox/dcim/models/modules.py:87 netbox/dcim/models/racks.py:356 msgid "airflow" msgstr "" -#: dcim/models/devices.py:213 +#: netbox/dcim/models/devices.py:213 msgid "device type" msgstr "" -#: dcim/models/devices.py:214 +#: netbox/dcim/models/devices.py:214 msgid "device types" msgstr "" -#: dcim/models/devices.py:305 +#: netbox/dcim/models/devices.py:305 msgid "U height must be in increments of 0.5 rack units." msgstr "" -#: dcim/models/devices.py:322 +#: netbox/dcim/models/devices.py:322 #, python-brace-format msgid "" "Device {device} in rack {rack} does not have sufficient space to accommodate " "a height of {height}U" msgstr "" -#: dcim/models/devices.py:337 +#: netbox/dcim/models/devices.py:337 #, python-brace-format msgid "" "Unable to set 0U height: Found {racked_instance_count} " "instances already mounted within racks." msgstr "" -#: dcim/models/devices.py:346 +#: netbox/dcim/models/devices.py:346 msgid "" "Must delete all device bay templates associated with this device before " "declassifying it as a parent device." msgstr "" -#: dcim/models/devices.py:352 +#: netbox/dcim/models/devices.py:352 msgid "Child device types must be 0U." msgstr "" -#: dcim/models/devices.py:401 +#: netbox/dcim/models/devices.py:401 msgid "Virtual machines may be assigned to this role" msgstr "" -#: dcim/models/devices.py:427 +#: netbox/dcim/models/devices.py:427 msgid "A top-level device role with this name already exists." msgstr "" -#: dcim/models/devices.py:437 +#: netbox/dcim/models/devices.py:437 msgid "A top-level device role with this slug already exists." msgstr "" -#: dcim/models/devices.py:440 +#: netbox/dcim/models/devices.py:440 msgid "device role" msgstr "" -#: dcim/models/devices.py:441 +#: netbox/dcim/models/devices.py:441 msgid "device roles" msgstr "" -#: dcim/models/devices.py:455 +#: netbox/dcim/models/devices.py:455 msgid "Optionally limit this platform to devices of a certain manufacturer" msgstr "" -#: dcim/models/devices.py:472 +#: netbox/dcim/models/devices.py:472 msgid "platform" msgstr "" -#: dcim/models/devices.py:473 +#: netbox/dcim/models/devices.py:473 msgid "platforms" msgstr "" -#: dcim/models/devices.py:483 +#: netbox/dcim/models/devices.py:483 msgid "Platform name must be unique." msgstr "" -#: dcim/models/devices.py:493 +#: netbox/dcim/models/devices.py:493 msgid "Platform slug must be unique." msgstr "" -#: dcim/models/devices.py:526 +#: netbox/dcim/models/devices.py:526 msgid "The function this device serves" msgstr "" -#: dcim/models/devices.py:553 +#: netbox/dcim/models/devices.py:553 msgid "Chassis serial number, assigned by the manufacturer" msgstr "" -#: dcim/models/devices.py:561 dcim/models/modules.py:246 +#: netbox/dcim/models/devices.py:561 netbox/dcim/models/modules.py:246 msgid "A unique tag used to identify this device" msgstr "" -#: dcim/models/devices.py:588 +#: netbox/dcim/models/devices.py:588 msgid "position (U)" msgstr "" -#: dcim/models/devices.py:596 +#: netbox/dcim/models/devices.py:596 msgid "rack face" msgstr "" -#: dcim/models/devices.py:617 dcim/models/devices.py:1277 -#: virtualization/models/virtualmachines.py:190 +#: netbox/dcim/models/devices.py:617 netbox/dcim/models/devices.py:1277 +#: netbox/virtualization/models/virtualmachines.py:190 msgid "primary IPv4" msgstr "" -#: dcim/models/devices.py:625 dcim/models/devices.py:1285 -#: virtualization/models/virtualmachines.py:198 +#: netbox/dcim/models/devices.py:625 netbox/dcim/models/devices.py:1285 +#: netbox/virtualization/models/virtualmachines.py:198 msgid "primary IPv6" msgstr "" -#: dcim/models/devices.py:633 +#: netbox/dcim/models/devices.py:633 msgid "out-of-band IP" msgstr "" -#: dcim/models/devices.py:650 +#: netbox/dcim/models/devices.py:650 msgid "VC position" msgstr "" -#: dcim/models/devices.py:653 +#: netbox/dcim/models/devices.py:653 msgid "Virtual chassis position" msgstr "" -#: dcim/models/devices.py:656 +#: netbox/dcim/models/devices.py:656 msgid "VC priority" msgstr "" -#: dcim/models/devices.py:660 +#: netbox/dcim/models/devices.py:660 msgid "Virtual chassis master election priority" msgstr "" -#: dcim/models/devices.py:663 dcim/models/sites.py:217 +#: netbox/dcim/models/devices.py:663 netbox/dcim/models/sites.py:217 msgid "latitude" msgstr "" -#: dcim/models/devices.py:672 dcim/models/devices.py:684 -#: dcim/models/sites.py:226 dcim/models/sites.py:238 +#: netbox/dcim/models/devices.py:672 netbox/dcim/models/devices.py:684 +#: netbox/dcim/models/sites.py:226 netbox/dcim/models/sites.py:238 msgid "GPS coordinate in decimal format (xx.yyyyyy)" msgstr "" -#: dcim/models/devices.py:675 dcim/models/sites.py:229 +#: netbox/dcim/models/devices.py:675 netbox/dcim/models/sites.py:229 msgid "longitude" msgstr "" -#: dcim/models/devices.py:761 +#: netbox/dcim/models/devices.py:761 msgid "Device name must be unique per site." msgstr "" -#: dcim/models/devices.py:772 +#: netbox/dcim/models/devices.py:772 msgid "device" msgstr "" -#: dcim/models/devices.py:773 +#: netbox/dcim/models/devices.py:773 msgid "devices" msgstr "" -#: dcim/models/devices.py:795 +#: netbox/dcim/models/devices.py:795 #, python-brace-format msgid "Rack {rack} does not belong to site {site}." msgstr "" -#: dcim/models/devices.py:800 +#: netbox/dcim/models/devices.py:800 #, python-brace-format msgid "Location {location} does not belong to site {site}." msgstr "" -#: dcim/models/devices.py:806 +#: netbox/dcim/models/devices.py:806 #, python-brace-format msgid "Rack {rack} does not belong to location {location}." msgstr "" -#: dcim/models/devices.py:813 +#: netbox/dcim/models/devices.py:813 msgid "Cannot select a rack face without assigning a rack." msgstr "" -#: dcim/models/devices.py:817 +#: netbox/dcim/models/devices.py:817 msgid "Cannot select a rack position without assigning a rack." msgstr "" -#: dcim/models/devices.py:823 +#: netbox/dcim/models/devices.py:823 msgid "Position must be in increments of 0.5 rack units." msgstr "" -#: dcim/models/devices.py:827 +#: netbox/dcim/models/devices.py:827 msgid "Must specify rack face when defining rack position." msgstr "" -#: dcim/models/devices.py:835 +#: netbox/dcim/models/devices.py:835 #, python-brace-format msgid "A 0U device type ({device_type}) cannot be assigned to a rack position." msgstr "" -#: dcim/models/devices.py:846 +#: netbox/dcim/models/devices.py:846 msgid "" "Child device types cannot be assigned to a rack face. This is an attribute " "of the parent device." msgstr "" -#: dcim/models/devices.py:853 +#: netbox/dcim/models/devices.py:853 msgid "" "Child device types cannot be assigned to a rack position. This is an " "attribute of the parent device." msgstr "" -#: dcim/models/devices.py:867 +#: netbox/dcim/models/devices.py:867 #, python-brace-format msgid "" "U{position} is already occupied or does not have sufficient space to " "accommodate this device type: {device_type} ({u_height}U)" msgstr "" -#: dcim/models/devices.py:882 +#: netbox/dcim/models/devices.py:882 #, python-brace-format msgid "{ip} is not an IPv4 address." msgstr "" -#: dcim/models/devices.py:894 dcim/models/devices.py:912 +#: netbox/dcim/models/devices.py:894 netbox/dcim/models/devices.py:912 #, python-brace-format msgid "The specified IP address ({ip}) is not assigned to this device." msgstr "" -#: dcim/models/devices.py:900 +#: netbox/dcim/models/devices.py:900 #, python-brace-format msgid "{ip} is not an IPv6 address." msgstr "" -#: dcim/models/devices.py:930 +#: netbox/dcim/models/devices.py:930 #, python-brace-format msgid "" "The assigned platform is limited to {platform_manufacturer} device types, " "but this device's type belongs to {devicetype_manufacturer}." msgstr "" -#: dcim/models/devices.py:941 +#: netbox/dcim/models/devices.py:941 #, python-brace-format msgid "The assigned cluster belongs to a different site ({site})" msgstr "" -#: dcim/models/devices.py:948 +#: netbox/dcim/models/devices.py:948 #, python-brace-format msgid "The assigned cluster belongs to a different location ({location})" msgstr "" -#: dcim/models/devices.py:956 +#: netbox/dcim/models/devices.py:956 msgid "A device assigned to a virtual chassis must have its position defined." msgstr "" -#: dcim/models/devices.py:962 +#: netbox/dcim/models/devices.py:962 #, python-brace-format msgid "" "Device cannot be removed from virtual chassis {virtual_chassis} because it " "is currently designated as its master." msgstr "" -#: dcim/models/devices.py:976 +#: netbox/dcim/models/devices.py:976 #, python-brace-format msgid "Component name conflict after resolving {{vc_position}}: {names}" msgstr "" -#: dcim/models/devices.py:1189 +#: netbox/dcim/models/devices.py:1189 msgid "domain" msgstr "" -#: dcim/models/devices.py:1205 dcim/models/devices.py:1206 +#: netbox/dcim/models/devices.py:1205 netbox/dcim/models/devices.py:1206 msgid "virtual chassis" msgstr "" -#: dcim/models/devices.py:1218 +#: netbox/dcim/models/devices.py:1218 #, python-brace-format msgid "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" -#: dcim/models/devices.py:1233 +#: netbox/dcim/models/devices.py:1233 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " "form a cross-chassis LAG interfaces." msgstr "" -#: dcim/models/devices.py:1266 vpn/models/l2vpn.py:42 +#: netbox/dcim/models/devices.py:1266 netbox/vpn/models/l2vpn.py:42 msgid "identifier" msgstr "" -#: dcim/models/devices.py:1267 +#: netbox/dcim/models/devices.py:1267 msgid "Numeric identifier unique to the parent device" msgstr "" -#: dcim/models/devices.py:1295 extras/models/customfields.py:263 -#: extras/models/models.py:118 extras/models/models.py:824 -#: netbox/models/__init__.py:134 netbox/models/__init__.py:173 -#: netbox/models/__init__.py:223 +#: netbox/dcim/models/devices.py:1295 netbox/extras/models/customfields.py:263 +#: netbox/extras/models/models.py:118 netbox/extras/models/models.py:824 +#: netbox/netbox/models/__init__.py:154 netbox/netbox/models/__init__.py:193 +#: netbox/netbox/models/__init__.py:243 msgid "comments" msgstr "" -#: dcim/models/devices.py:1314 +#: netbox/dcim/models/devices.py:1314 msgid "virtual device context" msgstr "" -#: dcim/models/devices.py:1315 +#: netbox/dcim/models/devices.py:1315 msgid "virtual device contexts" msgstr "" -#: dcim/models/devices.py:1343 +#: netbox/dcim/models/devices.py:1343 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "" -#: dcim/models/devices.py:1349 +#: netbox/dcim/models/devices.py:1349 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" -#: dcim/models/devices.py:1384 +#: netbox/dcim/models/devices.py:1384 msgid "MAC addresses" msgstr "" -#: dcim/models/devices.py:1416 +#: netbox/dcim/models/devices.py:1416 msgid "" "Cannot unassign MAC Address while it is designated as the primary MAC for an " "object" msgstr "" -#: dcim/models/devices.py:1420 +#: netbox/dcim/models/devices.py:1420 msgid "" "Cannot reassign MAC Address while it is designated as the primary MAC for an " "object" msgstr "" -#: dcim/models/mixins.py:132 virtualization/models/virtualmachines.py:541 +#: netbox/dcim/models/mixins.py:132 +#: netbox/virtualization/models/virtualmachines.py:541 msgid "An interface cannot be bridged to itself." msgstr "" -#: dcim/models/mixins.py:137 +#: netbox/dcim/models/mixins.py:137 msgid "Virtual interfaces cannot have a PoE mode." msgstr "" -#: dcim/models/mixins.py:141 +#: netbox/dcim/models/mixins.py:141 msgid "Virtual interfaces cannot have a PoE type." msgstr "" -#: dcim/models/mixins.py:147 +#: netbox/dcim/models/mixins.py:147 msgid "Must specify PoE mode when designating a PoE type." msgstr "" -#: dcim/models/mixins.py:152 +#: netbox/dcim/models/mixins.py:152 msgid "Wireless role may be set only on wireless interfaces." msgstr "" -#: dcim/models/modules.py:43 extras/models/configs.py:50 +#: netbox/dcim/models/modules.py:43 netbox/extras/models/configs.py:50 msgid "schema" msgstr "" -#: dcim/models/modules.py:50 +#: netbox/dcim/models/modules.py:50 msgid "module type profile" msgstr "" -#: dcim/models/modules.py:51 +#: netbox/dcim/models/modules.py:51 msgid "module type profiles" msgstr "" -#: dcim/models/modules.py:96 +#: netbox/dcim/models/modules.py:96 msgid "attributes" msgstr "" -#: dcim/models/modules.py:119 +#: netbox/dcim/models/modules.py:119 msgid "module type" msgstr "" -#: dcim/models/modules.py:120 +#: netbox/dcim/models/modules.py:120 msgid "module types" msgstr "" -#: dcim/models/modules.py:150 +#: netbox/dcim/models/modules.py:150 #, python-brace-format msgid "Invalid schema: {error}" msgstr "" -#: dcim/models/modules.py:253 +#: netbox/dcim/models/modules.py:253 msgid "module" msgstr "" -#: dcim/models/modules.py:254 +#: netbox/dcim/models/modules.py:254 msgid "modules" msgstr "" -#: dcim/models/modules.py:267 +#: netbox/dcim/models/modules.py:267 #, python-brace-format msgid "" "Module must be installed within a module bay belonging to the assigned " "device ({device})." msgstr "" -#: dcim/models/modules.py:277 +#: netbox/dcim/models/modules.py:277 msgid "Cannot install a module in a disabled module bay." msgstr "" -#: dcim/models/power.py:56 +#: netbox/dcim/models/power.py:56 msgid "power panel" msgstr "" -#: dcim/models/power.py:57 +#: netbox/dcim/models/power.py:57 msgid "power panels" msgstr "" -#: dcim/models/power.py:68 +#: netbox/dcim/models/power.py:68 #, python-brace-format msgid "" "Location {location} ({location_site}) is in a different site than {site}" msgstr "" -#: dcim/models/power.py:107 +#: netbox/dcim/models/power.py:107 msgid "supply" msgstr "" -#: dcim/models/power.py:113 +#: netbox/dcim/models/power.py:113 msgid "phase" msgstr "" -#: dcim/models/power.py:119 +#: netbox/dcim/models/power.py:119 msgid "voltage" msgstr "" -#: dcim/models/power.py:124 +#: netbox/dcim/models/power.py:124 msgid "amperage" msgstr "" -#: dcim/models/power.py:129 +#: netbox/dcim/models/power.py:129 msgid "max utilization" msgstr "" -#: dcim/models/power.py:132 +#: netbox/dcim/models/power.py:132 msgid "Maximum permissible draw (percentage)" msgstr "" -#: dcim/models/power.py:135 +#: netbox/dcim/models/power.py:135 msgid "available power" msgstr "" -#: dcim/models/power.py:163 +#: netbox/dcim/models/power.py:163 msgid "power feed" msgstr "" -#: dcim/models/power.py:164 +#: netbox/dcim/models/power.py:164 msgid "power feeds" msgstr "" -#: dcim/models/power.py:175 +#: netbox/dcim/models/power.py:175 #, python-brace-format msgid "" "Rack {rack} ({rack_site}) and power panel {powerpanel} ({powerpanel_site}) " "are in different sites." msgstr "" -#: dcim/models/power.py:186 +#: netbox/dcim/models/power.py:186 msgid "Voltage cannot be negative for AC supply" msgstr "" -#: dcim/models/racks.py:50 +#: netbox/dcim/models/racks.py:50 msgid "rack group" msgstr "" -#: dcim/models/racks.py:51 +#: netbox/dcim/models/racks.py:51 msgid "rack groups" msgstr "" -#: dcim/models/racks.py:65 +#: netbox/dcim/models/racks.py:65 msgid "width" msgstr "" -#: dcim/models/racks.py:66 +#: netbox/dcim/models/racks.py:66 msgid "Rail-to-rail width" msgstr "" -#: dcim/models/racks.py:74 +#: netbox/dcim/models/racks.py:74 msgid "Height in rack units" msgstr "" -#: dcim/models/racks.py:78 +#: netbox/dcim/models/racks.py:78 msgid "starting unit" msgstr "" -#: dcim/models/racks.py:80 +#: netbox/dcim/models/racks.py:80 msgid "Starting unit for rack" msgstr "" -#: dcim/models/racks.py:84 +#: netbox/dcim/models/racks.py:84 msgid "descending units" msgstr "" -#: dcim/models/racks.py:85 +#: netbox/dcim/models/racks.py:85 msgid "Units are numbered top-to-bottom" msgstr "" -#: dcim/models/racks.py:90 +#: netbox/dcim/models/racks.py:90 msgid "outer width" msgstr "" -#: dcim/models/racks.py:93 +#: netbox/dcim/models/racks.py:93 msgid "Outer dimension of rack (width)" msgstr "" -#: dcim/models/racks.py:96 +#: netbox/dcim/models/racks.py:96 msgid "outer height" msgstr "" -#: dcim/models/racks.py:99 +#: netbox/dcim/models/racks.py:99 msgid "Outer dimension of rack (height)" msgstr "" -#: dcim/models/racks.py:102 +#: netbox/dcim/models/racks.py:102 msgid "outer depth" msgstr "" -#: dcim/models/racks.py:105 +#: netbox/dcim/models/racks.py:105 msgid "Outer dimension of rack (depth)" msgstr "" -#: dcim/models/racks.py:108 +#: netbox/dcim/models/racks.py:108 msgid "outer unit" msgstr "" -#: dcim/models/racks.py:115 +#: netbox/dcim/models/racks.py:115 msgid "mounting depth" msgstr "" -#: dcim/models/racks.py:119 +#: netbox/dcim/models/racks.py:119 msgid "" "Maximum depth of a mounted device, in millimeters. For four-post racks, this " "is the distance between the front and rear rails." msgstr "" -#: dcim/models/racks.py:127 +#: netbox/dcim/models/racks.py:127 msgid "max weight" msgstr "" -#: dcim/models/racks.py:130 +#: netbox/dcim/models/racks.py:130 msgid "Maximum load capacity for the rack" msgstr "" -#: dcim/models/racks.py:154 dcim/models/racks.py:280 +#: netbox/dcim/models/racks.py:154 netbox/dcim/models/racks.py:280 msgid "form factor" msgstr "" -#: dcim/models/racks.py:195 +#: netbox/dcim/models/racks.py:195 msgid "rack type" msgstr "" -#: dcim/models/racks.py:196 +#: netbox/dcim/models/racks.py:196 msgid "rack types" msgstr "" -#: dcim/models/racks.py:210 dcim/models/racks.py:413 +#: netbox/dcim/models/racks.py:210 netbox/dcim/models/racks.py:413 msgid "Must specify a unit when setting an outer dimension" msgstr "" -#: dcim/models/racks.py:214 dcim/models/racks.py:417 +#: netbox/dcim/models/racks.py:214 netbox/dcim/models/racks.py:417 msgid "Must specify a unit when setting a maximum weight" msgstr "" -#: dcim/models/racks.py:260 +#: netbox/dcim/models/racks.py:260 msgid "rack role" msgstr "" -#: dcim/models/racks.py:261 +#: netbox/dcim/models/racks.py:261 msgid "rack roles" msgstr "" -#: dcim/models/racks.py:298 +#: netbox/dcim/models/racks.py:298 msgid "facility ID" msgstr "" -#: dcim/models/racks.py:299 +#: netbox/dcim/models/racks.py:299 msgid "Locally-assigned identifier" msgstr "" -#: dcim/models/racks.py:319 +#: netbox/dcim/models/racks.py:319 msgid "physical grouping" msgstr "" -#: dcim/models/racks.py:340 ipam/forms/bulk_import.py:146 -#: ipam/forms/bulk_import.py:214 ipam/forms/bulk_import.py:278 -#: ipam/forms/bulk_import.py:313 ipam/forms/bulk_import.py:545 -#: virtualization/forms/bulk_import.py:151 +#: netbox/dcim/models/racks.py:340 netbox/ipam/forms/bulk_import.py:146 +#: netbox/ipam/forms/bulk_import.py:214 netbox/ipam/forms/bulk_import.py:278 +#: netbox/ipam/forms/bulk_import.py:313 netbox/ipam/forms/bulk_import.py:545 +#: netbox/virtualization/forms/bulk_import.py:151 msgid "Functional role" msgstr "" -#: dcim/models/racks.py:353 +#: netbox/dcim/models/racks.py:353 msgid "A unique tag used to identify this rack" msgstr "" -#: dcim/models/racks.py:396 +#: netbox/dcim/models/racks.py:396 msgid "rack" msgstr "" -#: dcim/models/racks.py:397 +#: netbox/dcim/models/racks.py:397 msgid "racks" msgstr "" -#: dcim/models/racks.py:409 +#: netbox/dcim/models/racks.py:409 #, python-brace-format msgid "Assigned location must belong to parent site ({site})." msgstr "" -#: dcim/models/racks.py:432 +#: netbox/dcim/models/racks.py:432 #, python-brace-format msgid "" "Rack must be at least {min_height}U tall to house currently installed " "devices." msgstr "" -#: dcim/models/racks.py:441 +#: netbox/dcim/models/racks.py:441 #, python-brace-format msgid "" "Rack unit numbering must begin at {position} or less to house currently " "installed devices." msgstr "" -#: dcim/models/racks.py:449 +#: netbox/dcim/models/racks.py:449 #, python-brace-format msgid "Location must be from the same site, {site}." msgstr "" -#: dcim/models/racks.py:712 +#: netbox/dcim/models/racks.py:712 msgid "units" msgstr "" -#: dcim/models/racks.py:747 +#: netbox/dcim/models/racks.py:747 msgid "rack reservation" msgstr "" -#: dcim/models/racks.py:748 +#: netbox/dcim/models/racks.py:748 msgid "rack reservations" msgstr "" -#: dcim/models/racks.py:762 +#: netbox/dcim/models/racks.py:762 #, python-brace-format msgid "Invalid unit(s) for {height}U rack: {unit_list}" msgstr "" -#: dcim/models/racks.py:775 +#: netbox/dcim/models/racks.py:775 #, python-brace-format msgid "The following units have already been reserved: {unit_list}" msgstr "" -#: dcim/models/sites.py:59 +#: netbox/dcim/models/sites.py:59 msgid "A top-level region with this name already exists." msgstr "" -#: dcim/models/sites.py:69 +#: netbox/dcim/models/sites.py:69 msgid "A top-level region with this slug already exists." msgstr "" -#: dcim/models/sites.py:72 +#: netbox/dcim/models/sites.py:72 msgid "region" msgstr "" -#: dcim/models/sites.py:73 +#: netbox/dcim/models/sites.py:73 msgid "regions" msgstr "" -#: dcim/models/sites.py:118 +#: netbox/dcim/models/sites.py:118 msgid "A top-level site group with this name already exists." msgstr "" -#: dcim/models/sites.py:128 +#: netbox/dcim/models/sites.py:128 msgid "A top-level site group with this slug already exists." msgstr "" -#: dcim/models/sites.py:131 +#: netbox/dcim/models/sites.py:131 msgid "site group" msgstr "" -#: dcim/models/sites.py:132 +#: netbox/dcim/models/sites.py:132 msgid "site groups" msgstr "" -#: dcim/models/sites.py:154 +#: netbox/dcim/models/sites.py:154 msgid "Full name of the site" msgstr "" -#: dcim/models/sites.py:190 dcim/models/sites.py:300 +#: netbox/dcim/models/sites.py:190 netbox/dcim/models/sites.py:300 msgid "facility" msgstr "" -#: dcim/models/sites.py:193 dcim/models/sites.py:303 +#: netbox/dcim/models/sites.py:193 netbox/dcim/models/sites.py:303 msgid "Local facility ID or description" msgstr "" -#: dcim/models/sites.py:205 +#: netbox/dcim/models/sites.py:205 msgid "physical address" msgstr "" -#: dcim/models/sites.py:208 +#: netbox/dcim/models/sites.py:208 msgid "Physical location of the building" msgstr "" -#: dcim/models/sites.py:211 +#: netbox/dcim/models/sites.py:211 msgid "shipping address" msgstr "" -#: dcim/models/sites.py:214 +#: netbox/dcim/models/sites.py:214 msgid "If different from the physical address" msgstr "" -#: dcim/models/sites.py:262 +#: netbox/dcim/models/sites.py:262 msgid "site" msgstr "" -#: dcim/models/sites.py:263 +#: netbox/dcim/models/sites.py:263 msgid "sites" msgstr "" -#: dcim/models/sites.py:339 +#: netbox/dcim/models/sites.py:339 msgid "A location with this name already exists within the specified site." msgstr "" -#: dcim/models/sites.py:349 +#: netbox/dcim/models/sites.py:349 msgid "A location with this slug already exists within the specified site." msgstr "" -#: dcim/models/sites.py:352 +#: netbox/dcim/models/sites.py:352 msgid "location" msgstr "" -#: dcim/models/sites.py:353 +#: netbox/dcim/models/sites.py:353 msgid "locations" msgstr "" -#: dcim/models/sites.py:364 +#: netbox/dcim/models/sites.py:364 #, python-brace-format msgid "Parent location ({parent}) must belong to the same site ({site})." msgstr "" -#: dcim/object_actions.py:15 templates/dcim/device/base.html:21 -#: templates/dcim/devicetype/base.html:18 -#: templates/dcim/inc/moduletype_buttons.html:9 templates/dcim/module.html:18 -#: templates/virtualization/buttons/bulk_add_components.html:4 -#: templates/virtualization/virtualmachine/base.html:22 -#: virtualization/object_actions.py:14 +#: netbox/dcim/object_actions.py:15 netbox/templates/dcim/device/base.html:21 +#: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 +#: netbox/templates/dcim/module.html:18 +#: netbox/templates/virtualization/buttons/bulk_add_components.html:4 +#: netbox/templates/virtualization/virtualmachine/base.html:22 +#: netbox/virtualization/object_actions.py:14 msgid "Add Components" msgstr "" -#: dcim/object_actions.py:32 +#: netbox/dcim/object_actions.py:32 msgid "Disconnect Selected" msgstr "" -#: dcim/tables/cables.py:57 dcim/views.py:4322 +#: netbox/dcim/tables/cables.py:57 netbox/dcim/views.py:4322 msgid "Termination A" msgstr "" -#: dcim/tables/cables.py:62 dcim/views.py:4326 +#: netbox/dcim/tables/cables.py:62 netbox/dcim/views.py:4326 msgid "Termination B" msgstr "" -#: dcim/tables/cables.py:68 wireless/forms/bulk_import.py:96 -#: wireless/tables/wirelesslink.py:22 +#: netbox/dcim/tables/cables.py:68 netbox/wireless/forms/bulk_import.py:96 +#: netbox/wireless/tables/wirelesslink.py:22 msgid "Device A" msgstr "" -#: dcim/tables/cables.py:74 wireless/forms/bulk_import.py:117 -#: wireless/tables/wirelesslink.py:31 +#: netbox/dcim/tables/cables.py:74 netbox/wireless/forms/bulk_import.py:117 +#: netbox/wireless/tables/wirelesslink.py:31 msgid "Device B" msgstr "" -#: dcim/tables/cables.py:80 +#: netbox/dcim/tables/cables.py:80 msgid "Location A" msgstr "" -#: dcim/tables/cables.py:86 +#: netbox/dcim/tables/cables.py:86 msgid "Location B" msgstr "" -#: dcim/tables/cables.py:92 +#: netbox/dcim/tables/cables.py:92 msgid "Rack A" msgstr "" -#: dcim/tables/cables.py:98 +#: netbox/dcim/tables/cables.py:98 msgid "Rack B" msgstr "" -#: dcim/tables/cables.py:104 wireless/forms/bulk_import.py:89 +#: netbox/dcim/tables/cables.py:104 netbox/wireless/forms/bulk_import.py:89 msgid "Site A" msgstr "" -#: dcim/tables/cables.py:110 wireless/forms/bulk_import.py:110 +#: netbox/dcim/tables/cables.py:110 netbox/wireless/forms/bulk_import.py:110 msgid "Site B" msgstr "" -#: dcim/tables/cables.py:120 +#: netbox/dcim/tables/cables.py:120 msgid "Color Name" msgstr "" -#: dcim/tables/cables.py:149 netbox/navigation/menu.py:133 -#: templates/dcim/cablebundle.html:37 +#: netbox/dcim/tables/cables.py:149 netbox/netbox/navigation/menu.py:133 +#: netbox/templates/dcim/cablebundle.html:37 msgid "Cables" msgstr "" -#: dcim/tables/connections.py:32 dcim/tables/connections.py:51 -#: dcim/tables/connections.py:72 -#: templates/dcim/inc/connection_endpoints.html:16 -#: templates/dcim/panels/connection.html:26 -#: templates/dcim/panels/interface_connection.html:25 +#: netbox/dcim/tables/connections.py:32 netbox/dcim/tables/connections.py:51 +#: netbox/dcim/tables/connections.py:72 +#: netbox/templates/dcim/inc/connection_endpoints.html:16 +#: netbox/templates/dcim/panels/connection.html:26 +#: netbox/templates/dcim/panels/interface_connection.html:25 msgid "Reachable" msgstr "" -#: dcim/tables/devices.py:67 dcim/tables/devices.py:111 -#: dcim/tables/racks.py:164 dcim/tables/sites.py:84 dcim/tables/sites.py:116 -#: extras/tables/tables.py:730 netbox/navigation/menu.py:78 -#: netbox/navigation/menu.py:82 netbox/navigation/menu.py:84 -#: virtualization/forms/model_forms.py:120 virtualization/tables/clusters.py:88 -#: virtualization/views.py:297 +#: netbox/dcim/tables/devices.py:67 netbox/dcim/tables/devices.py:111 +#: netbox/dcim/tables/racks.py:164 netbox/dcim/tables/sites.py:84 +#: netbox/dcim/tables/sites.py:116 netbox/extras/tables/tables.py:730 +#: netbox/netbox/navigation/menu.py:78 netbox/netbox/navigation/menu.py:82 +#: netbox/netbox/navigation/menu.py:84 +#: netbox/virtualization/forms/model_forms.py:120 +#: netbox/virtualization/tables/clusters.py:88 +#: netbox/virtualization/views.py:297 msgid "Devices" msgstr "" -#: dcim/tables/devices.py:72 dcim/tables/devices.py:116 -#: virtualization/tables/clusters.py:93 +#: netbox/dcim/tables/devices.py:72 netbox/dcim/tables/devices.py:116 +#: netbox/virtualization/tables/clusters.py:93 msgid "VMs" msgstr "" -#: dcim/tables/devices.py:105 dcim/tables/devices.py:225 -#: extras/forms/model_forms.py:823 extras/ui/panels.py:460 -#: templates/extras/object_render_config.html:12 -#: templates/extras/object_render_config.html:15 -#: virtualization/tables/virtualmachines.py:114 +#: netbox/dcim/tables/devices.py:105 netbox/dcim/tables/devices.py:225 +#: netbox/extras/forms/model_forms.py:823 netbox/extras/ui/panels.py:460 +#: netbox/templates/extras/object_render_config.html:12 +#: netbox/templates/extras/object_render_config.html:15 +#: netbox/virtualization/tables/virtualmachines.py:114 msgid "Config Template" msgstr "" -#: dcim/tables/devices.py:186 dcim/tables/devicetypes.py:102 +#: netbox/dcim/tables/devices.py:186 netbox/dcim/tables/devicetypes.py:102 msgid "U Height" msgstr "" -#: dcim/tables/devices.py:196 dcim/tables/devices.py:1193 -#: ipam/forms/bulk_import.py:627 ipam/forms/model_forms.py:333 -#: ipam/forms/model_forms.py:345 ipam/forms/model_forms.py:494 -#: ipam/tables/ip.py:312 ipam/tables/ip.py:376 ipam/tables/ip.py:391 -#: ipam/tables/ip.py:414 virtualization/tables/virtualmachines.py:102 +#: netbox/dcim/tables/devices.py:196 netbox/dcim/tables/devices.py:1193 +#: netbox/ipam/forms/bulk_import.py:627 netbox/ipam/forms/model_forms.py:333 +#: netbox/ipam/forms/model_forms.py:345 netbox/ipam/forms/model_forms.py:494 +#: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:376 +#: netbox/ipam/tables/ip.py:391 netbox/ipam/tables/ip.py:414 +#: netbox/virtualization/tables/virtualmachines.py:102 msgid "IP Address" msgstr "" -#: dcim/tables/devices.py:200 dcim/tables/devices.py:1197 -#: virtualization/tables/virtualmachines.py:93 +#: netbox/dcim/tables/devices.py:200 netbox/dcim/tables/devices.py:1197 +#: netbox/virtualization/tables/virtualmachines.py:93 msgid "IPv4 Address" msgstr "" -#: dcim/tables/devices.py:204 dcim/tables/devices.py:1201 -#: virtualization/tables/virtualmachines.py:97 +#: netbox/dcim/tables/devices.py:204 netbox/dcim/tables/devices.py:1201 +#: netbox/virtualization/tables/virtualmachines.py:97 msgid "IPv6 Address" msgstr "" -#: dcim/tables/devices.py:219 +#: netbox/dcim/tables/devices.py:219 msgid "VC Position" msgstr "" -#: dcim/tables/devices.py:222 +#: netbox/dcim/tables/devices.py:222 msgid "VC Priority" msgstr "" -#: dcim/tables/devices.py:229 templates/dcim/device_edit.html:40 -#: templates/dcim/devicebay_populate.html:16 +#: netbox/dcim/tables/devices.py:229 netbox/templates/dcim/device_edit.html:40 +#: netbox/templates/dcim/devicebay_populate.html:16 msgid "Parent Device" msgstr "" -#: dcim/tables/devices.py:234 +#: netbox/dcim/tables/devices.py:234 msgid "Position (Device Bay)" msgstr "" -#: dcim/tables/devices.py:242 +#: netbox/dcim/tables/devices.py:242 msgid "Console ports" msgstr "" -#: dcim/tables/devices.py:245 +#: netbox/dcim/tables/devices.py:245 msgid "Console server ports" msgstr "" -#: dcim/tables/devices.py:248 +#: netbox/dcim/tables/devices.py:248 msgid "Power ports" msgstr "" -#: dcim/tables/devices.py:251 +#: netbox/dcim/tables/devices.py:251 msgid "Power outlets" msgstr "" -#: dcim/tables/devices.py:254 dcim/tables/devices.py:1206 -#: dcim/tables/devicetypes.py:132 dcim/views.py:1518 dcim/views.py:1872 -#: dcim/views.py:2749 netbox/navigation/menu.py:104 -#: netbox/navigation/menu.py:269 -#: templates/dcim/buttons/bulk_add_components.html:38 -#: templates/dcim/device/base.html:37 templates/dcim/devicetype/base.html:34 -#: templates/dcim/inc/moduletype_buttons.html:25 templates/dcim/module.html:34 -#: templates/virtualization/buttons/bulk_add_components.html:10 -#: templates/virtualization/virtualmachine/base.html:27 -#: virtualization/tables/virtualmachines.py:108 virtualization/views.py:532 -#: wireless/tables/wirelesslan.py:56 +#: netbox/dcim/tables/devices.py:254 netbox/dcim/tables/devices.py:1206 +#: netbox/dcim/tables/devicetypes.py:132 netbox/dcim/views.py:1518 +#: netbox/dcim/views.py:1872 netbox/dcim/views.py:2749 +#: netbox/netbox/navigation/menu.py:104 netbox/netbox/navigation/menu.py:269 +#: netbox/templates/dcim/buttons/bulk_add_components.html:38 +#: netbox/templates/dcim/device/base.html:37 +#: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 +#: netbox/templates/dcim/module.html:34 +#: netbox/templates/virtualization/buttons/bulk_add_components.html:10 +#: netbox/templates/virtualization/virtualmachine/base.html:27 +#: netbox/virtualization/tables/virtualmachines.py:108 +#: netbox/virtualization/views.py:532 netbox/wireless/tables/wirelesslan.py:56 msgid "Interfaces" msgstr "" -#: dcim/tables/devices.py:257 +#: netbox/dcim/tables/devices.py:257 msgid "Front ports" msgstr "" -#: dcim/tables/devices.py:263 +#: netbox/dcim/tables/devices.py:263 msgid "Device bays" msgstr "" -#: dcim/tables/devices.py:266 +#: netbox/dcim/tables/devices.py:266 msgid "Module bays" msgstr "" -#: dcim/tables/devices.py:269 +#: netbox/dcim/tables/devices.py:269 msgid "Inventory items" msgstr "" -#: dcim/tables/devices.py:302 +#: netbox/dcim/tables/devices.py:302 msgid "Device Location" msgstr "" -#: dcim/tables/devices.py:307 +#: netbox/dcim/tables/devices.py:307 msgid "Device Site" msgstr "" -#: dcim/tables/devices.py:322 dcim/tables/modules.py:88 +#: netbox/dcim/tables/devices.py:322 netbox/dcim/tables/modules.py:88 msgid "Module Bay" msgstr "" -#: dcim/tables/devices.py:335 dcim/tables/devicetypes.py:53 -#: dcim/tables/devicetypes.py:147 dcim/ui/panels.py:416 dcim/views.py:1593 -#: dcim/views.py:2835 netbox/navigation/menu.py:113 -#: templates/dcim/buttons/bulk_add_components.html:66 -#: templates/dcim/device/base.html:52 templates/dcim/devicetype/base.html:49 -#: templates/dcim/inc/panels/inventory_items.html:6 +#: netbox/dcim/tables/devices.py:335 netbox/dcim/tables/devicetypes.py:53 +#: netbox/dcim/tables/devicetypes.py:147 netbox/dcim/ui/panels.py:416 +#: netbox/dcim/views.py:1593 netbox/dcim/views.py:2835 +#: netbox/netbox/navigation/menu.py:113 +#: netbox/templates/dcim/buttons/bulk_add_components.html:66 +#: netbox/templates/dcim/device/base.html:52 +#: netbox/templates/dcim/devicetype/base.html:49 +#: netbox/templates/dcim/inc/panels/inventory_items.html:6 msgid "Inventory Items" msgstr "" -#: dcim/tables/devices.py:350 +#: netbox/dcim/tables/devices.py:350 msgid "Cable Color" msgstr "" -#: dcim/tables/devices.py:356 ipam/tables/vlans.py:170 +#: netbox/dcim/tables/devices.py:356 netbox/ipam/tables/vlans.py:170 msgid "Link Peers" msgstr "" -#: dcim/tables/devices.py:359 +#: netbox/dcim/tables/devices.py:359 msgid "Mark Connected" msgstr "" -#: dcim/tables/devices.py:489 +#: netbox/dcim/tables/devices.py:489 msgid "Maximum draw (W)" msgstr "" -#: dcim/tables/devices.py:492 +#: netbox/dcim/tables/devices.py:492 msgid "Allocated draw (W)" msgstr "" -#: dcim/tables/devices.py:597 dcim/views.py:3388 ipam/forms/model_forms.py:805 -#: ipam/tables/fhrp.py:28 ipam/ui/panels.py:252 ipam/views.py:844 -#: ipam/views.py:968 netbox/navigation/menu.py:175 -#: netbox/navigation/menu.py:177 vpn/tables/tunnels.py:98 +#: netbox/dcim/tables/devices.py:597 netbox/dcim/views.py:3388 +#: netbox/ipam/forms/model_forms.py:805 netbox/ipam/tables/fhrp.py:28 +#: netbox/ipam/ui/panels.py:252 netbox/ipam/views.py:844 +#: netbox/ipam/views.py:968 netbox/netbox/navigation/menu.py:175 +#: netbox/netbox/navigation/menu.py:177 netbox/vpn/tables/tunnels.py:98 msgid "IP Addresses" msgstr "" -#: dcim/tables/devices.py:600 +#: netbox/dcim/tables/devices.py:600 msgid "Primary MAC" msgstr "" -#: dcim/tables/devices.py:606 dcim/views.py:3394 netbox/navigation/menu.py:120 +#: netbox/dcim/tables/devices.py:606 netbox/dcim/views.py:3394 +#: netbox/netbox/navigation/menu.py:120 msgid "MAC Addresses" msgstr "" -#: dcim/tables/devices.py:612 ipam/ui/panels.py:15 -#: netbox/navigation/menu.py:221 templates/ipam/inc/panels/fhrp_groups.html:6 +#: netbox/dcim/tables/devices.py:612 netbox/ipam/ui/panels.py:15 +#: netbox/netbox/navigation/menu.py:221 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:6 msgid "FHRP Groups" msgstr "" -#: dcim/tables/devices.py:624 dcim/ui/panels.py:500 -#: virtualization/ui/panels.py:97 vpn/forms/bulk_edit.py:64 -#: vpn/forms/bulk_import.py:75 vpn/forms/filtersets.py:50 -#: vpn/forms/filtersets.py:92 vpn/forms/model_forms.py:58 -#: vpn/forms/model_forms.py:143 vpn/tables/tunnels.py:77 +#: netbox/dcim/tables/devices.py:624 netbox/dcim/ui/panels.py:500 +#: netbox/virtualization/ui/panels.py:97 netbox/vpn/forms/bulk_edit.py:64 +#: netbox/vpn/forms/bulk_import.py:75 netbox/vpn/forms/filtersets.py:50 +#: netbox/vpn/forms/filtersets.py:92 netbox/vpn/forms/model_forms.py:58 +#: netbox/vpn/forms/model_forms.py:143 netbox/vpn/tables/tunnels.py:77 msgid "Tunnel" msgstr "" -#: dcim/tables/devices.py:656 dcim/tables/devicetypes.py:236 +#: netbox/dcim/tables/devices.py:656 netbox/dcim/tables/devicetypes.py:236 msgid "Management Only" msgstr "" -#: dcim/tables/devices.py:675 +#: netbox/dcim/tables/devices.py:675 msgid "VDCs" msgstr "" -#: dcim/tables/devices.py:682 dcim/ui/panels.py:542 +#: netbox/dcim/tables/devices.py:682 netbox/dcim/ui/panels.py:542 msgid "Virtual Circuit" msgstr "" -#: dcim/tables/devices.py:809 dcim/tables/devices.py:862 -#: dcim/tables/devicetypes.py:258 dcim/tables/devicetypes.py:277 +#: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:862 +#: netbox/dcim/tables/devicetypes.py:258 netbox/dcim/tables/devicetypes.py:277 msgid "Mappings" msgstr "" -#: dcim/tables/devices.py:920 dcim/ui/panels.py:287 +#: netbox/dcim/tables/devices.py:920 netbox/dcim/ui/panels.py:287 msgid "Installed Device" msgstr "" -#: dcim/tables/devices.py:925 +#: netbox/dcim/tables/devices.py:925 msgid "Installed Role" msgstr "" -#: dcim/tables/devices.py:930 +#: netbox/dcim/tables/devices.py:930 msgid "Installed Type" msgstr "" -#: dcim/tables/devices.py:934 +#: netbox/dcim/tables/devices.py:934 msgid "Installed Description" msgstr "" -#: dcim/tables/devices.py:938 +#: netbox/dcim/tables/devices.py:938 msgid "Installed Serial" msgstr "" -#: dcim/tables/devices.py:942 +#: netbox/dcim/tables/devices.py:942 msgid "Installed Asset Tag" msgstr "" -#: dcim/tables/devices.py:998 dcim/ui/panels.py:271 +#: netbox/dcim/tables/devices.py:998 netbox/dcim/ui/panels.py:271 msgid "Installed Module" msgstr "" -#: dcim/tables/devices.py:1001 +#: netbox/dcim/tables/devices.py:1001 msgid "Module Serial" msgstr "" -#: dcim/tables/devices.py:1005 +#: netbox/dcim/tables/devices.py:1005 msgid "Module Asset Tag" msgstr "" -#: dcim/tables/devices.py:1014 +#: netbox/dcim/tables/devices.py:1014 msgid "Module Status" msgstr "" -#: dcim/tables/devices.py:1071 dcim/tables/devicetypes.py:332 +#: netbox/dcim/tables/devices.py:1071 netbox/dcim/tables/devicetypes.py:332 msgid "Component" msgstr "" -#: dcim/tables/devices.py:1129 +#: netbox/dcim/tables/devices.py:1129 msgid "Items" msgstr "" -#: dcim/tables/devicetypes.py:38 netbox/navigation/menu.py:69 -#: netbox/navigation/menu.py:71 +#: netbox/dcim/tables/devicetypes.py:38 netbox/netbox/navigation/menu.py:69 +#: netbox/netbox/navigation/menu.py:71 msgid "Rack Types" msgstr "" -#: dcim/tables/devicetypes.py:43 netbox/navigation/menu.py:93 -#: netbox/navigation/menu.py:95 +#: netbox/dcim/tables/devicetypes.py:43 netbox/netbox/navigation/menu.py:93 +#: netbox/netbox/navigation/menu.py:95 msgid "Device Types" msgstr "" -#: dcim/tables/devicetypes.py:48 dcim/views.py:1690 -#: netbox/navigation/menu.py:96 +#: netbox/dcim/tables/devicetypes.py:48 netbox/dcim/views.py:1690 +#: netbox/netbox/navigation/menu.py:96 msgid "Module Types" msgstr "" -#: dcim/tables/devicetypes.py:58 extras/forms/filtersets.py:466 -#: extras/forms/model_forms.py:730 extras/tables/tables.py:725 -#: netbox/navigation/menu.py:87 +#: netbox/dcim/tables/devicetypes.py:58 netbox/extras/forms/filtersets.py:466 +#: netbox/extras/forms/model_forms.py:730 netbox/extras/tables/tables.py:725 +#: netbox/netbox/navigation/menu.py:87 msgid "Platforms" msgstr "" -#: dcim/tables/devicetypes.py:91 +#: netbox/dcim/tables/devicetypes.py:91 msgid "Default Platform" msgstr "" -#: dcim/tables/devicetypes.py:95 +#: netbox/dcim/tables/devicetypes.py:95 msgid "Full Depth" msgstr "" -#: dcim/tables/devicetypes.py:117 +#: netbox/dcim/tables/devicetypes.py:117 msgid "Device Count" msgstr "" -#: dcim/tables/devicetypes.py:120 dcim/views.py:1458 dcim/views.py:1812 -#: dcim/views.py:2684 netbox/navigation/menu.py:107 -#: templates/dcim/buttons/bulk_add_components.html:10 -#: templates/dcim/device/base.html:25 templates/dcim/devicetype/base.html:22 -#: templates/dcim/inc/moduletype_buttons.html:13 templates/dcim/module.html:22 +#: netbox/dcim/tables/devicetypes.py:120 netbox/dcim/views.py:1458 +#: netbox/dcim/views.py:1812 netbox/dcim/views.py:2684 +#: netbox/netbox/navigation/menu.py:107 +#: netbox/templates/dcim/buttons/bulk_add_components.html:10 +#: netbox/templates/dcim/device/base.html:25 +#: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 +#: netbox/templates/dcim/module.html:22 msgid "Console Ports" msgstr "" -#: dcim/tables/devicetypes.py:123 dcim/views.py:1473 dcim/views.py:1827 -#: dcim/views.py:2700 netbox/navigation/menu.py:108 -#: templates/dcim/buttons/bulk_add_components.html:17 -#: templates/dcim/device/base.html:28 templates/dcim/devicetype/base.html:25 -#: templates/dcim/inc/moduletype_buttons.html:16 templates/dcim/module.html:25 +#: netbox/dcim/tables/devicetypes.py:123 netbox/dcim/views.py:1473 +#: netbox/dcim/views.py:1827 netbox/dcim/views.py:2700 +#: netbox/netbox/navigation/menu.py:108 +#: netbox/templates/dcim/buttons/bulk_add_components.html:17 +#: netbox/templates/dcim/device/base.html:28 +#: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 +#: netbox/templates/dcim/module.html:25 msgid "Console Server Ports" msgstr "" -#: dcim/tables/devicetypes.py:126 dcim/views.py:1488 dcim/views.py:1842 -#: dcim/views.py:2716 netbox/navigation/menu.py:109 -#: templates/dcim/buttons/bulk_add_components.html:24 -#: templates/dcim/device/base.html:31 templates/dcim/devicetype/base.html:28 -#: templates/dcim/inc/moduletype_buttons.html:19 templates/dcim/module.html:28 +#: netbox/dcim/tables/devicetypes.py:126 netbox/dcim/views.py:1488 +#: netbox/dcim/views.py:1842 netbox/dcim/views.py:2716 +#: netbox/netbox/navigation/menu.py:109 +#: netbox/templates/dcim/buttons/bulk_add_components.html:24 +#: netbox/templates/dcim/device/base.html:31 +#: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 +#: netbox/templates/dcim/module.html:28 msgid "Power Ports" msgstr "" -#: dcim/tables/devicetypes.py:129 dcim/views.py:1503 dcim/views.py:1857 -#: dcim/views.py:2732 netbox/navigation/menu.py:110 -#: templates/dcim/buttons/bulk_add_components.html:31 -#: templates/dcim/device/base.html:34 templates/dcim/devicetype/base.html:31 -#: templates/dcim/inc/moduletype_buttons.html:22 templates/dcim/module.html:31 +#: netbox/dcim/tables/devicetypes.py:129 netbox/dcim/views.py:1503 +#: netbox/dcim/views.py:1857 netbox/dcim/views.py:2732 +#: netbox/netbox/navigation/menu.py:110 +#: netbox/templates/dcim/buttons/bulk_add_components.html:31 +#: netbox/templates/dcim/device/base.html:34 +#: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 +#: netbox/templates/dcim/module.html:31 msgid "Power Outlets" msgstr "" -#: dcim/tables/devicetypes.py:135 dcim/views.py:1533 dcim/views.py:1887 -#: dcim/views.py:2771 netbox/navigation/menu.py:105 -#: templates/dcim/device/base.html:40 templates/dcim/devicetype/base.html:37 -#: templates/dcim/inc/moduletype_buttons.html:28 templates/dcim/module.html:37 +#: netbox/dcim/tables/devicetypes.py:135 netbox/dcim/views.py:1533 +#: netbox/dcim/views.py:1887 netbox/dcim/views.py:2771 +#: netbox/netbox/navigation/menu.py:105 +#: netbox/templates/dcim/device/base.html:40 +#: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 +#: netbox/templates/dcim/module.html:37 msgid "Front Ports" msgstr "" -#: dcim/tables/devicetypes.py:138 dcim/views.py:1548 dcim/views.py:1902 -#: dcim/views.py:2787 netbox/navigation/menu.py:106 -#: templates/dcim/buttons/bulk_add_components.html:45 -#: templates/dcim/device/base.html:43 templates/dcim/devicetype/base.html:40 -#: templates/dcim/inc/moduletype_buttons.html:31 templates/dcim/module.html:40 +#: netbox/dcim/tables/devicetypes.py:138 netbox/dcim/views.py:1548 +#: netbox/dcim/views.py:1902 netbox/dcim/views.py:2787 +#: netbox/netbox/navigation/menu.py:106 +#: netbox/templates/dcim/buttons/bulk_add_components.html:45 +#: netbox/templates/dcim/device/base.html:43 +#: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 +#: netbox/templates/dcim/module.html:40 msgid "Rear Ports" msgstr "" -#: dcim/tables/devicetypes.py:141 dcim/views.py:1578 dcim/views.py:2819 -#: netbox/navigation/menu.py:112 -#: templates/dcim/buttons/bulk_add_components.html:52 -#: templates/dcim/device/base.html:49 templates/dcim/devicetype/base.html:46 +#: netbox/dcim/tables/devicetypes.py:141 netbox/dcim/views.py:1578 +#: netbox/dcim/views.py:2819 netbox/netbox/navigation/menu.py:112 +#: netbox/templates/dcim/buttons/bulk_add_components.html:52 +#: netbox/templates/dcim/device/base.html:49 +#: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "" -#: dcim/tables/devicetypes.py:144 dcim/views.py:1563 dcim/views.py:1917 -#: dcim/views.py:2803 netbox/navigation/menu.py:111 -#: templates/dcim/buttons/bulk_add_components.html:59 -#: templates/dcim/device/base.html:46 templates/dcim/devicetype/base.html:43 -#: templates/dcim/inc/moduletype_buttons.html:34 templates/dcim/module.html:43 +#: netbox/dcim/tables/devicetypes.py:144 netbox/dcim/views.py:1563 +#: netbox/dcim/views.py:1917 netbox/dcim/views.py:2803 +#: netbox/netbox/navigation/menu.py:111 +#: netbox/templates/dcim/buttons/bulk_add_components.html:59 +#: netbox/templates/dcim/device/base.html:46 +#: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 +#: netbox/templates/dcim/module.html:43 msgid "Module Bays" msgstr "" -#: dcim/tables/modules.py:65 +#: netbox/dcim/tables/modules.py:65 msgid "Module Count" msgstr "" -#: dcim/tables/power.py:36 netbox/navigation/menu.py:330 +#: netbox/dcim/tables/power.py:36 netbox/netbox/navigation/menu.py:330 msgid "Power Feeds" msgstr "" -#: dcim/tables/power.py:77 +#: netbox/dcim/tables/power.py:77 msgid "Max Utilization" msgstr "" -#: dcim/tables/power.py:81 +#: netbox/dcim/tables/power.py:81 msgid "Available Power (VA)" msgstr "" -#: dcim/tables/racks.py:28 dcim/tables/racks.py:51 dcim/tables/sites.py:111 -#: netbox/navigation/menu.py:46 netbox/navigation/menu.py:50 -#: netbox/navigation/menu.py:52 +#: netbox/dcim/tables/racks.py:28 netbox/dcim/tables/racks.py:51 +#: netbox/dcim/tables/sites.py:111 netbox/netbox/navigation/menu.py:46 +#: netbox/netbox/navigation/menu.py:50 netbox/netbox/navigation/menu.py:52 msgid "Racks" msgstr "" -#: dcim/tables/racks.py:80 dcim/tables/racks.py:159 dcim/ui/panels.py:31 -#: templates/dcim/inc/panels/racktype_dimensions.html:14 +#: netbox/dcim/tables/racks.py:80 netbox/dcim/tables/racks.py:159 +#: netbox/dcim/ui/panels.py:31 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:14 msgid "Height" msgstr "" -#: dcim/tables/racks.py:84 dcim/tables/racks.py:179 -#: templates/dcim/inc/panels/racktype_dimensions.html:18 +#: netbox/dcim/tables/racks.py:84 netbox/dcim/tables/racks.py:179 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:18 msgid "Outer Width" msgstr "" -#: dcim/tables/racks.py:88 dcim/tables/racks.py:183 -#: templates/dcim/inc/panels/racktype_dimensions.html:28 +#: netbox/dcim/tables/racks.py:88 netbox/dcim/tables/racks.py:183 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:28 msgid "Outer Height" msgstr "" -#: dcim/tables/racks.py:92 dcim/tables/racks.py:187 -#: templates/dcim/inc/panels/racktype_dimensions.html:38 +#: netbox/dcim/tables/racks.py:92 netbox/dcim/tables/racks.py:187 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:38 msgid "Outer Depth" msgstr "" -#: dcim/tables/racks.py:100 dcim/tables/racks.py:195 +#: netbox/dcim/tables/racks.py:100 netbox/dcim/tables/racks.py:195 msgid "Max Weight" msgstr "" -#: dcim/tables/racks.py:107 +#: netbox/dcim/tables/racks.py:107 msgid "Rack Count" msgstr "" -#: dcim/tables/racks.py:168 +#: netbox/dcim/tables/racks.py:168 msgid "Space" msgstr "" -#: dcim/tables/racks.py:245 dcim/ui/panels.py:74 +#: netbox/dcim/tables/racks.py:245 netbox/dcim/ui/panels.py:74 msgid "Total U's" msgstr "" -#: dcim/tables/sites.py:22 dcim/tables/sites.py:41 -#: extras/forms/filtersets.py:446 extras/forms/model_forms.py:710 -#: ipam/forms/bulk_edit.py:115 ipam/forms/model_forms.py:164 -#: ipam/tables/asn.py:80 netbox/navigation/menu.py:18 -#: netbox/navigation/menu.py:22 +#: netbox/dcim/tables/sites.py:22 netbox/dcim/tables/sites.py:41 +#: netbox/extras/forms/filtersets.py:446 netbox/extras/forms/model_forms.py:710 +#: netbox/ipam/forms/bulk_edit.py:115 netbox/ipam/forms/model_forms.py:164 +#: netbox/ipam/tables/asn.py:80 netbox/netbox/navigation/menu.py:18 +#: netbox/netbox/navigation/menu.py:22 msgid "Sites" msgstr "" -#: dcim/tables/sites.py:121 netbox/navigation/menu.py:213 +#: netbox/dcim/tables/sites.py:121 netbox/netbox/navigation/menu.py:213 msgid "VLAN Groups" msgstr "" -#: dcim/tests/test_api.py:59 +#: netbox/dcim/tests/test_api.py:59 msgid "Test case must set peer_termination_type" msgstr "" -#: dcim/ui/panels.py:35 +#: netbox/dcim/ui/panels.py:35 msgid "{} millimeters" msgstr "" -#: dcim/ui/panels.py:55 dcim/ui/panels.py:98 dcim/ui/panels.py:171 -#: dcim/ui/panels.py:275 virtualization/forms/filtersets.py:250 -#: virtualization/ui/panels.py:46 +#: netbox/dcim/ui/panels.py:55 netbox/dcim/ui/panels.py:98 +#: netbox/dcim/ui/panels.py:171 netbox/dcim/ui/panels.py:275 +#: netbox/virtualization/forms/filtersets.py:250 +#: netbox/virtualization/ui/panels.py:46 msgid "Serial number" msgstr "" -#: dcim/ui/panels.py:64 +#: netbox/dcim/ui/panels.py:64 msgid "Maximum weight" msgstr "" -#: dcim/ui/panels.py:104 templates/dcim/device_edit.html:66 -#: virtualization/forms/model_forms.py:267 +#: netbox/dcim/ui/panels.py:104 netbox/templates/dcim/device_edit.html:66 +#: netbox/virtualization/forms/model_forms.py:267 msgid "Management" msgstr "" -#: dcim/ui/panels.py:121 +#: netbox/dcim/ui/panels.py:121 msgid "Out-of-band IP" msgstr "" -#: dcim/ui/panels.py:159 +#: netbox/dcim/ui/panels.py:159 msgid "Parent/child" msgstr "" -#: dcim/ui/panels.py:183 +#: netbox/dcim/ui/panels.py:183 msgid "Model name" msgstr "" -#: dcim/ui/panels.py:294 +#: netbox/dcim/ui/panels.py:294 msgid "Parent item" msgstr "" -#: dcim/ui/panels.py:301 +#: netbox/dcim/ui/panels.py:301 msgid "Part ID" msgstr "" -#: dcim/ui/panels.py:344 +#: netbox/dcim/ui/panels.py:344 msgid "Connected device" msgstr "" -#: dcim/ui/panels.py:349 +#: netbox/dcim/ui/panels.py:349 msgid "Utilization (allocated)" msgstr "" -#: dcim/ui/panels.py:355 +#: netbox/dcim/ui/panels.py:355 msgid "Electrical Characteristics" msgstr "" -#: dcim/ui/panels.py:358 +#: netbox/dcim/ui/panels.py:358 msgid "{}V" msgstr "" -#: dcim/ui/panels.py:359 +#: netbox/dcim/ui/panels.py:359 msgid "{}A" msgstr "" -#: dcim/ui/panels.py:386 +#: netbox/dcim/ui/panels.py:386 msgid "Primary for interface" msgstr "" -#: dcim/ui/panels.py:434 +#: netbox/dcim/ui/panels.py:434 msgid "Virtual Chassis Members" msgstr "" -#: dcim/ui/panels.py:469 +#: netbox/dcim/ui/panels.py:469 msgid "Power Utilization" msgstr "" -#: dcim/ui/panels.py:499 +#: netbox/dcim/ui/panels.py:499 msgid "Transmit power" msgstr "" -#: dcim/ui/panels.py:522 +#: netbox/dcim/ui/panels.py:522 msgid "VLAN translation" msgstr "" -#: dcim/utils.py:54 +#: netbox/dcim/utils.py:54 #, python-brace-format msgid "" "Cannot install module with placeholder values in a module bay tree {level} " "levels deep but {tokens} placeholders given." msgstr "" -#: dcim/views.py:150 +#: netbox/dcim/views.py:150 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "" -#: dcim/views.py:258 +#: netbox/dcim/views.py:258 msgid "Child Regions" msgstr "" -#: dcim/views.py:391 tenancy/views.py:59 tenancy/views.py:232 -#: wireless/views.py:54 +#: netbox/dcim/views.py:391 netbox/tenancy/views.py:59 +#: netbox/tenancy/views.py:232 netbox/wireless/views.py:54 msgid "Child Groups" msgstr "" -#: dcim/views.py:551 dcim/views.py:693 dcim/views.py:1180 +#: netbox/dcim/views.py:551 netbox/dcim/views.py:693 netbox/dcim/views.py:1180 msgid "Non-Racked Devices" msgstr "" -#: dcim/views.py:678 +#: netbox/dcim/views.py:678 msgid "Child Locations" msgstr "" -#: dcim/views.py:1161 netbox/navigation/menu.py:53 +#: netbox/dcim/views.py:1161 netbox/netbox/navigation/menu.py:53 msgid "Reservations" msgstr "" -#: dcim/views.py:2434 +#: netbox/dcim/views.py:2434 msgid "Child Device Roles" msgstr "" -#: dcim/views.py:2535 +#: netbox/dcim/views.py:2535 msgid "Child Platforms" msgstr "" -#: dcim/views.py:2627 netbox/navigation/menu.py:223 virtualization/views.py:493 +#: netbox/dcim/views.py:2627 netbox/netbox/navigation/menu.py:223 +#: netbox/virtualization/views.py:493 msgid "Application Services" msgstr "" -#: dcim/views.py:2848 extras/forms/filtersets.py:407 -#: extras/forms/model_forms.py:770 extras/ui/panels.py:435 -#: virtualization/forms/model_forms.py:269 virtualization/views.py:569 +#: netbox/dcim/views.py:2848 netbox/extras/forms/filtersets.py:407 +#: netbox/extras/forms/model_forms.py:770 netbox/extras/ui/panels.py:435 +#: netbox/virtualization/forms/model_forms.py:269 +#: netbox/virtualization/views.py:569 msgid "Config Context" msgstr "" -#: dcim/views.py:2859 virtualization/views.py:580 +#: netbox/dcim/views.py:2859 netbox/virtualization/views.py:580 msgid "Render Config" msgstr "" -#: dcim/views.py:2872 extras/tables/tables.py:735 netbox/navigation/menu.py:266 -#: netbox/navigation/menu.py:268 virtualization/views.py:278 +#: netbox/dcim/views.py:2872 netbox/extras/tables/tables.py:735 +#: netbox/netbox/navigation/menu.py:266 netbox/netbox/navigation/menu.py:268 +#: netbox/virtualization/views.py:278 msgid "Virtual Machines" msgstr "" -#: dcim/views.py:3375 netbox/navigation/menu.py:89 +#: netbox/dcim/views.py:3375 netbox/netbox/navigation/menu.py:89 msgid "Virtual Device Contexts" msgstr "" -#: dcim/views.py:3400 ipam/forms/filtersets.py:463 ipam/models/vlans.py:293 -#: ipam/tables/ip.py:121 ipam/tables/vlans.py:52 ipam/views.py:1302 -#: netbox/navigation/menu.py:210 netbox/navigation/menu.py:212 +#: netbox/dcim/views.py:3400 netbox/ipam/forms/filtersets.py:463 +#: netbox/ipam/models/vlans.py:293 netbox/ipam/tables/ip.py:121 +#: netbox/ipam/tables/vlans.py:52 netbox/ipam/views.py:1302 +#: netbox/netbox/navigation/menu.py:210 netbox/netbox/navigation/menu.py:212 msgid "VLANs" msgstr "" -#: dcim/views.py:3402 +#: netbox/dcim/views.py:3402 msgid "LAG Members" msgstr "" -#: dcim/views.py:3403 virtualization/ui/panels.py:108 -#: virtualization/views.py:680 +#: netbox/dcim/views.py:3403 netbox/virtualization/ui/panels.py:108 +#: netbox/virtualization/views.py:680 msgid "VLAN Translation" msgstr "" -#: dcim/views.py:3404 +#: netbox/dcim/views.py:3404 msgid "Bridged Interfaces" msgstr "" -#: dcim/views.py:3405 virtualization/views.py:681 +#: netbox/dcim/views.py:3405 netbox/virtualization/views.py:681 msgid "Child Interfaces" msgstr "" -#: dcim/views.py:3874 +#: netbox/dcim/views.py:3874 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "" -#: dcim/views.py:3915 +#: netbox/dcim/views.py:3915 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "" -#: dcim/views.py:4035 ipam/tables/ip.py:184 +#: netbox/dcim/views.py:4035 netbox/ipam/tables/ip.py:184 msgid "Children" msgstr "" -#: dcim/views.py:4605 +#: netbox/dcim/views.py:4605 #, python-brace-format msgid "Added member {device}" msgstr "" -#: dcim/views.py:4650 +#: netbox/dcim/views.py:4650 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" -#: dcim/views.py:4661 +#: netbox/dcim/views.py:4661 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "" -#: extras/api/customfields.py:94 +#: netbox/extras/api/customfields.py:94 #, python-brace-format msgid "Custom field '{name}' does not exist for this object type." msgstr "" -#: extras/api/customfields.py:110 +#: netbox/extras/api/customfields.py:110 #, python-brace-format msgid "Unknown related object(s): {name}" msgstr "" -#: extras/api/mixins.py:97 extras/views.py:1298 +#: netbox/extras/api/mixins.py:97 netbox/extras/views.py:1298 #, python-brace-format msgid "Config template with ID {id} not found." msgstr "" -#: extras/api/mixins.py:103 +#: netbox/extras/api/mixins.py:103 #, python-brace-format msgid "No config template found for this {object_type}." msgstr "" -#: extras/api/serializers_/customfields.py:79 +#: netbox/extras/api/serializers_/customfields.py:79 msgid "Changing the type of custom fields is not supported." msgstr "" -#: extras/api/serializers_/scripts.py:50 extras/forms/scripts.py:91 +#: netbox/extras/api/serializers_/scripts.py:50 +#: netbox/extras/forms/scripts.py:91 #, python-brace-format msgid "Error loading script: {error}" msgstr "" -#: extras/api/serializers_/scripts.py:67 +#: netbox/extras/api/serializers_/scripts.py:67 msgid "A script module with this file name already exists." msgstr "" -#: extras/api/serializers_/scripts.py:147 -#: extras/api/serializers_/scripts.py:157 +#: netbox/extras/api/serializers_/scripts.py:147 +#: netbox/extras/api/serializers_/scripts.py:157 msgid "Scheduling is not enabled for this script." msgstr "" -#: extras/api/serializers_/scripts.py:149 extras/forms/reports.py:45 -#: extras/forms/scripts.py:62 +#: netbox/extras/api/serializers_/scripts.py:149 +#: netbox/extras/forms/reports.py:45 netbox/extras/forms/scripts.py:62 msgid "Scheduled time must be in the future." msgstr "" -#: extras/choices.py:30 extras/forms/misc.py:14 +#: netbox/extras/choices.py:30 netbox/extras/forms/misc.py:14 msgid "Text" msgstr "" -#: extras/choices.py:31 +#: netbox/extras/choices.py:31 msgid "Text (long)" msgstr "" -#: extras/choices.py:32 +#: netbox/extras/choices.py:32 msgid "Integer" msgstr "" -#: extras/choices.py:33 +#: netbox/extras/choices.py:33 msgid "Decimal" msgstr "" -#: extras/choices.py:34 +#: netbox/extras/choices.py:34 msgid "Boolean (true/false)" msgstr "" -#: extras/choices.py:35 +#: netbox/extras/choices.py:35 msgid "Date" msgstr "" -#: extras/choices.py:36 +#: netbox/extras/choices.py:36 msgid "Date & time" msgstr "" -#: extras/choices.py:38 +#: netbox/extras/choices.py:38 msgid "JSON" msgstr "" -#: extras/choices.py:39 +#: netbox/extras/choices.py:39 msgid "Selection" msgstr "" -#: extras/choices.py:40 +#: netbox/extras/choices.py:40 msgid "Multiple selection" msgstr "" -#: extras/choices.py:42 +#: netbox/extras/choices.py:42 msgid "Multiple objects" msgstr "" -#: extras/choices.py:54 +#: netbox/extras/choices.py:54 msgid "Loose" msgstr "" -#: extras/choices.py:55 +#: netbox/extras/choices.py:55 msgid "Exact" msgstr "" -#: extras/choices.py:67 +#: netbox/extras/choices.py:67 msgid "If set" msgstr "" -#: extras/choices.py:68 extras/choices.py:81 +#: netbox/extras/choices.py:68 netbox/extras/choices.py:81 msgid "Hidden" msgstr "" -#: extras/choices.py:79 +#: netbox/extras/choices.py:79 msgid "Yes" msgstr "" -#: extras/choices.py:80 +#: netbox/extras/choices.py:80 msgid "No" msgstr "" -#: extras/choices.py:115 extras/choices.py:255 netbox/choices.py:59 -#: netbox/choices.py:104 +#: netbox/extras/choices.py:115 netbox/extras/choices.py:255 +#: netbox/netbox/choices.py:59 netbox/netbox/choices.py:104 msgid "Blue" msgstr "" -#: extras/choices.py:116 extras/choices.py:256 netbox/choices.py:58 -#: netbox/choices.py:105 +#: netbox/extras/choices.py:116 netbox/extras/choices.py:256 +#: netbox/netbox/choices.py:58 netbox/netbox/choices.py:105 msgid "Indigo" msgstr "" -#: extras/choices.py:117 extras/choices.py:257 netbox/choices.py:56 -#: netbox/choices.py:106 +#: netbox/extras/choices.py:117 netbox/extras/choices.py:257 +#: netbox/netbox/choices.py:56 netbox/netbox/choices.py:106 msgid "Purple" msgstr "" -#: extras/choices.py:118 extras/choices.py:258 netbox/choices.py:53 -#: netbox/choices.py:107 +#: netbox/extras/choices.py:118 netbox/extras/choices.py:258 +#: netbox/netbox/choices.py:53 netbox/netbox/choices.py:107 msgid "Pink" msgstr "" -#: extras/choices.py:119 extras/choices.py:259 netbox/choices.py:52 -#: netbox/choices.py:108 +#: netbox/extras/choices.py:119 netbox/extras/choices.py:259 +#: netbox/netbox/choices.py:52 netbox/netbox/choices.py:108 msgid "Red" msgstr "" -#: extras/choices.py:120 extras/choices.py:260 netbox/choices.py:70 -#: netbox/choices.py:109 +#: netbox/extras/choices.py:120 netbox/extras/choices.py:260 +#: netbox/netbox/choices.py:70 netbox/netbox/choices.py:109 msgid "Orange" msgstr "" -#: extras/choices.py:121 extras/choices.py:261 netbox/choices.py:68 -#: netbox/choices.py:110 +#: netbox/extras/choices.py:121 netbox/extras/choices.py:261 +#: netbox/netbox/choices.py:68 netbox/netbox/choices.py:110 msgid "Yellow" msgstr "" -#: extras/choices.py:122 extras/choices.py:262 netbox/choices.py:65 -#: netbox/choices.py:111 +#: netbox/extras/choices.py:122 netbox/extras/choices.py:262 +#: netbox/netbox/choices.py:65 netbox/netbox/choices.py:111 msgid "Green" msgstr "" -#: extras/choices.py:123 extras/choices.py:263 netbox/choices.py:62 -#: netbox/choices.py:112 +#: netbox/extras/choices.py:123 netbox/extras/choices.py:263 +#: netbox/netbox/choices.py:62 netbox/netbox/choices.py:112 msgid "Teal" msgstr "" -#: extras/choices.py:124 extras/choices.py:264 netbox/choices.py:61 -#: netbox/choices.py:113 +#: netbox/extras/choices.py:124 netbox/extras/choices.py:264 +#: netbox/netbox/choices.py:61 netbox/netbox/choices.py:113 msgid "Cyan" msgstr "" -#: extras/choices.py:125 extras/choices.py:265 netbox/choices.py:114 +#: netbox/extras/choices.py:125 netbox/extras/choices.py:265 +#: netbox/netbox/choices.py:114 msgid "Gray" msgstr "" -#: extras/choices.py:126 extras/choices.py:266 netbox/choices.py:76 -#: netbox/choices.py:115 +#: netbox/extras/choices.py:126 netbox/extras/choices.py:266 +#: netbox/netbox/choices.py:76 netbox/netbox/choices.py:115 msgid "Black" msgstr "" -#: extras/choices.py:127 extras/choices.py:267 netbox/choices.py:77 -#: netbox/choices.py:116 +#: netbox/extras/choices.py:127 netbox/extras/choices.py:267 +#: netbox/netbox/choices.py:77 netbox/netbox/choices.py:116 msgid "White" msgstr "" -#: extras/choices.py:141 tenancy/forms/bulk_edit.py:113 -#: tenancy/forms/bulk_import.py:91 tenancy/forms/model_forms.py:98 -#: tenancy/ui/panels.py:18 wireless/forms/model_forms.py:169 +#: netbox/extras/choices.py:141 netbox/tenancy/forms/bulk_edit.py:113 +#: netbox/tenancy/forms/bulk_import.py:91 +#: netbox/tenancy/forms/model_forms.py:98 netbox/tenancy/ui/panels.py:18 +#: netbox/wireless/forms/model_forms.py:169 msgid "Link" msgstr "" -#: extras/choices.py:157 +#: netbox/extras/choices.py:157 msgid "Newest" msgstr "" -#: extras/choices.py:158 +#: netbox/extras/choices.py:158 msgid "Oldest" msgstr "" -#: extras/choices.py:159 +#: netbox/extras/choices.py:159 msgid "Alphabetical (A-Z)" msgstr "" -#: extras/choices.py:160 +#: netbox/extras/choices.py:160 msgid "Alphabetical (Z-A)" msgstr "" -#: extras/choices.py:178 extras/choices.py:199 +#: netbox/extras/choices.py:178 netbox/extras/choices.py:199 msgid "Success" msgstr "" -#: extras/choices.py:180 +#: netbox/extras/choices.py:180 msgid "Danger" msgstr "" -#: extras/choices.py:201 +#: netbox/extras/choices.py:201 msgid "Failure" msgstr "" -#: extras/choices.py:282 extras/forms/model_forms.py:516 -#: extras/forms/model_forms.py:593 extras/ui/panels.py:329 +#: netbox/extras/choices.py:282 netbox/extras/forms/model_forms.py:516 +#: netbox/extras/forms/model_forms.py:593 netbox/extras/ui/panels.py:329 msgid "Webhook" msgstr "" -#: extras/choices.py:283 extras/forms/model_forms.py:581 -#: templates/extras/script/base.html:29 +#: netbox/extras/choices.py:283 netbox/extras/forms/model_forms.py:581 +#: netbox/templates/extras/script/base.html:29 msgid "Script" msgstr "" -#: extras/choices.py:284 +#: netbox/extras/choices.py:284 msgid "Notification" msgstr "" -#: extras/conditions.py:60 +#: netbox/extras/conditions.py:60 #, python-brace-format msgid "Unknown operator: {op}. Must be one of: {operators}" msgstr "" -#: extras/conditions.py:64 +#: netbox/extras/conditions.py:64 #, python-brace-format msgid "Unsupported value type: {value}" msgstr "" -#: extras/conditions.py:66 +#: netbox/extras/conditions.py:66 #, python-brace-format msgid "Invalid type for {op} operation: {value}" msgstr "" -#: extras/conditions.py:145 +#: netbox/extras/conditions.py:145 #, python-brace-format msgid "Ruleset must be a dictionary, not {ruleset}." msgstr "" -#: extras/conditions.py:150 +#: netbox/extras/conditions.py:150 msgid "Invalid logic type: must be 'AND' or 'OR'. Please check documentation." msgstr "" -#: extras/conditions.py:162 +#: netbox/extras/conditions.py:162 msgid "Incorrect key(s) informed. Please check documentation." msgstr "" -#: extras/dashboard/forms.py:38 +#: netbox/extras/dashboard/forms.py:38 msgid "Widget type" msgstr "" -#: extras/dashboard/utils.py:36 +#: netbox/extras/dashboard/utils.py:36 #, python-brace-format msgid "Unregistered widget class: {name}" msgstr "" -#: extras/dashboard/widgets.py:150 +#: netbox/extras/dashboard/widgets.py:150 #, python-brace-format msgid "{class_name} must define a render() method." msgstr "" -#: extras/dashboard/widgets.py:169 +#: netbox/extras/dashboard/widgets.py:169 msgid "Note" msgstr "" -#: extras/dashboard/widgets.py:170 +#: netbox/extras/dashboard/widgets.py:170 msgid "Display some arbitrary custom content. Markdown is supported." msgstr "" -#: extras/dashboard/widgets.py:183 templates/core/system.html:35 -#: templates/core/system.html:169 +#: netbox/extras/dashboard/widgets.py:183 netbox/templates/core/system.html:35 +#: netbox/templates/core/system.html:169 msgid "Object Counts" msgstr "" -#: extras/dashboard/widgets.py:184 +#: netbox/extras/dashboard/widgets.py:184 msgid "" "Display a set of NetBox models and the number of objects created for each " "type." msgstr "" -#: extras/dashboard/widgets.py:194 +#: netbox/extras/dashboard/widgets.py:194 msgid "Filters to apply when counting the number of objects" msgstr "" -#: extras/dashboard/widgets.py:202 +#: netbox/extras/dashboard/widgets.py:202 msgid "Invalid format. Object filters must be passed as a dictionary." msgstr "" -#: extras/dashboard/widgets.py:236 +#: netbox/extras/dashboard/widgets.py:236 msgid "Object List" msgstr "" -#: extras/dashboard/widgets.py:237 +#: netbox/extras/dashboard/widgets.py:237 msgid "Display an arbitrary list of objects." msgstr "" -#: extras/dashboard/widgets.py:250 +#: netbox/extras/dashboard/widgets.py:250 msgid "The default number of objects to display" msgstr "" -#: extras/dashboard/widgets.py:262 +#: netbox/extras/dashboard/widgets.py:262 msgid "Invalid format. URL parameters must be passed as a dictionary." msgstr "" -#: extras/dashboard/widgets.py:271 +#: netbox/extras/dashboard/widgets.py:271 msgid "Invalid model selection: {self['model'].data} is not supported." msgstr "" -#: extras/dashboard/widgets.py:311 +#: netbox/extras/dashboard/widgets.py:311 msgid "RSS Feed" msgstr "" -#: extras/dashboard/widgets.py:318 +#: netbox/extras/dashboard/widgets.py:318 msgid "Embed an RSS feed from an external website." msgstr "" -#: extras/dashboard/widgets.py:325 +#: netbox/extras/dashboard/widgets.py:325 msgid "Feed URL" msgstr "" -#: extras/dashboard/widgets.py:329 +#: netbox/extras/dashboard/widgets.py:329 msgid "Requires external connection" msgstr "" -#: extras/dashboard/widgets.py:335 +#: netbox/extras/dashboard/widgets.py:335 msgid "The maximum number of objects to display" msgstr "" -#: extras/dashboard/widgets.py:340 +#: netbox/extras/dashboard/widgets.py:340 msgid "How long to stored the cached content (in seconds)" msgstr "" -#: extras/dashboard/widgets.py:346 +#: netbox/extras/dashboard/widgets.py:346 msgid "Timeout value for fetching the feed (in seconds)" msgstr "" -#: extras/dashboard/widgets.py:403 templates/account/base.html:10 -#: templates/account/bookmarks.html:7 templates/inc/user_menu.html:41 +#: netbox/extras/dashboard/widgets.py:403 netbox/templates/account/base.html:10 +#: netbox/templates/account/bookmarks.html:7 +#: netbox/templates/inc/user_menu.html:41 msgid "Bookmarks" msgstr "" -#: extras/dashboard/widgets.py:407 +#: netbox/extras/dashboard/widgets.py:407 msgid "Show your personal bookmarks" msgstr "" -#: extras/events.py:194 +#: netbox/extras/events.py:194 #, python-brace-format msgid "Ignoring invalid action_data on event rule \"{rule}\" (got {data_type})" msgstr "" -#: extras/events.py:270 +#: netbox/extras/events.py:270 #, python-brace-format msgid "Unknown action type for an event rule: {action_type}" msgstr "" -#: extras/events.py:313 +#: netbox/extras/events.py:313 #, python-brace-format msgid "Cannot import events pipeline {name} error: {error}" msgstr "" -#: extras/filtersets.py:52 +#: netbox/extras/filtersets.py:52 msgid "Script module (ID)" msgstr "" -#: extras/filtersets.py:206 extras/forms/filtersets.py:144 +#: netbox/extras/filtersets.py:206 netbox/extras/forms/filtersets.py:144 msgid "Choice colors" msgstr "" -#: extras/filtersets.py:300 extras/filtersets.py:670 extras/filtersets.py:846 -#: extras/filtersets.py:877 +#: netbox/extras/filtersets.py:300 netbox/extras/filtersets.py:670 +#: netbox/extras/filtersets.py:846 netbox/extras/filtersets.py:877 msgid "Data file (ID)" msgstr "" -#: extras/filtersets.py:481 users/filtersets.py:83 users/filtersets.py:234 -#: users/filtersets.py:292 +#: netbox/extras/filtersets.py:481 netbox/users/filtersets.py:83 +#: netbox/users/filtersets.py:234 netbox/users/filtersets.py:292 msgid "Group (name)" msgstr "" -#: extras/filtersets.py:781 virtualization/forms/filtersets.py:180 +#: netbox/extras/filtersets.py:781 +#: netbox/virtualization/forms/filtersets.py:180 msgid "Cluster type" msgstr "" -#: extras/filtersets.py:787 virtualization/filtersets.py:73 -#: virtualization/filtersets.py:188 +#: netbox/extras/filtersets.py:787 netbox/virtualization/filtersets.py:73 +#: netbox/virtualization/filtersets.py:188 msgid "Cluster type (slug)" msgstr "" -#: extras/filtersets.py:808 tenancy/forms/forms.py:17 tenancy/forms/forms.py:41 +#: netbox/extras/filtersets.py:808 netbox/tenancy/forms/forms.py:17 +#: netbox/tenancy/forms/forms.py:41 msgid "Tenant group" msgstr "" -#: extras/filtersets.py:814 tenancy/filtersets.py:212 tenancy/filtersets.py:233 +#: netbox/extras/filtersets.py:814 netbox/tenancy/filtersets.py:212 +#: netbox/tenancy/filtersets.py:233 msgid "Tenant group (slug)" msgstr "" -#: extras/filtersets.py:830 extras/forms/model_forms.py:658 -#: extras/ui/panels.py:391 +#: netbox/extras/filtersets.py:830 netbox/extras/forms/model_forms.py:658 +#: netbox/extras/ui/panels.py:391 msgid "Tag" msgstr "" -#: extras/filtersets.py:836 +#: netbox/extras/filtersets.py:836 msgid "Tag (slug)" msgstr "" -#: extras/filtersets.py:905 extras/forms/filtersets.py:560 +#: netbox/extras/filtersets.py:905 netbox/extras/forms/filtersets.py:560 msgid "Has local config context data" msgstr "" -#: extras/forms/bulk_edit.py:39 extras/forms/filtersets.py:70 -#: extras/ui/panels.py:130 +#: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/filtersets.py:70 +#: netbox/extras/ui/panels.py:130 msgid "Group name" msgstr "" -#: extras/forms/bulk_edit.py:47 extras/forms/filtersets.py:78 -#: extras/tables/tables.py:83 templates/generic/bulk_import.html:149 +#: netbox/extras/forms/bulk_edit.py:47 netbox/extras/forms/filtersets.py:78 +#: netbox/extras/tables/tables.py:83 +#: netbox/templates/generic/bulk_import.html:149 msgid "Required" msgstr "" -#: extras/forms/bulk_edit.py:52 extras/forms/filtersets.py:85 -#: extras/ui/panels.py:133 +#: netbox/extras/forms/bulk_edit.py:52 netbox/extras/forms/filtersets.py:85 +#: netbox/extras/ui/panels.py:133 msgid "Must be unique" msgstr "" -#: extras/forms/bulk_edit.py:65 extras/forms/bulk_import.py:66 -#: extras/forms/filtersets.py:99 extras/models/customfields.py:247 -#: extras/ui/panels.py:155 +#: netbox/extras/forms/bulk_edit.py:65 netbox/extras/forms/bulk_import.py:66 +#: netbox/extras/forms/filtersets.py:99 +#: netbox/extras/models/customfields.py:247 netbox/extras/ui/panels.py:155 msgid "UI visible" msgstr "" -#: extras/forms/bulk_edit.py:70 extras/forms/bulk_import.py:72 -#: extras/forms/filtersets.py:104 extras/models/customfields.py:254 -#: extras/ui/panels.py:156 +#: netbox/extras/forms/bulk_edit.py:70 netbox/extras/forms/bulk_import.py:72 +#: netbox/extras/forms/filtersets.py:104 +#: netbox/extras/models/customfields.py:254 netbox/extras/ui/panels.py:156 msgid "UI editable" msgstr "" -#: extras/forms/bulk_edit.py:75 extras/forms/filtersets.py:107 +#: netbox/extras/forms/bulk_edit.py:75 netbox/extras/forms/filtersets.py:107 msgid "Is cloneable" msgstr "" -#: extras/forms/bulk_edit.py:80 extras/forms/filtersets.py:114 -#: extras/ui/panels.py:162 +#: netbox/extras/forms/bulk_edit.py:80 netbox/extras/forms/filtersets.py:114 +#: netbox/extras/ui/panels.py:162 msgid "Minimum value" msgstr "" -#: extras/forms/bulk_edit.py:84 extras/forms/filtersets.py:118 -#: extras/ui/panels.py:163 +#: netbox/extras/forms/bulk_edit.py:84 netbox/extras/forms/filtersets.py:118 +#: netbox/extras/ui/panels.py:163 msgid "Maximum value" msgstr "" -#: extras/forms/bulk_edit.py:88 extras/forms/filtersets.py:122 +#: netbox/extras/forms/bulk_edit.py:88 netbox/extras/forms/filtersets.py:122 msgid "Validation regex" msgstr "" -#: extras/forms/bulk_edit.py:92 extras/forms/model_forms.py:80 +#: netbox/extras/forms/bulk_edit.py:92 netbox/extras/forms/model_forms.py:80 msgid "Validation schema" msgstr "" -#: extras/forms/bulk_edit.py:99 extras/forms/filtersets.py:50 -#: extras/forms/model_forms.py:92 extras/ui/panels.py:147 +#: netbox/extras/forms/bulk_edit.py:99 netbox/extras/forms/filtersets.py:50 +#: netbox/extras/forms/model_forms.py:92 netbox/extras/ui/panels.py:147 msgid "Behavior" msgstr "" -#: extras/forms/bulk_edit.py:139 extras/forms/filtersets.py:168 +#: netbox/extras/forms/bulk_edit.py:139 netbox/extras/forms/filtersets.py:168 msgid "New window" msgstr "" -#: extras/forms/bulk_edit.py:148 +#: netbox/extras/forms/bulk_edit.py:148 msgid "Button class" msgstr "" -#: extras/forms/bulk_edit.py:165 extras/forms/bulk_edit.py:384 -#: extras/forms/filtersets.py:208 extras/forms/filtersets.py:531 -#: extras/models/mixins.py:101 extras/ui/panels.py:238 extras/ui/panels.py:464 +#: netbox/extras/forms/bulk_edit.py:165 netbox/extras/forms/bulk_edit.py:384 +#: netbox/extras/forms/filtersets.py:208 netbox/extras/forms/filtersets.py:531 +#: netbox/extras/models/mixins.py:101 netbox/extras/ui/panels.py:238 +#: netbox/extras/ui/panels.py:464 msgid "MIME type" msgstr "" -#: extras/forms/bulk_edit.py:170 extras/forms/bulk_edit.py:389 -#: extras/forms/filtersets.py:211 extras/forms/filtersets.py:534 +#: netbox/extras/forms/bulk_edit.py:170 netbox/extras/forms/bulk_edit.py:389 +#: netbox/extras/forms/filtersets.py:211 netbox/extras/forms/filtersets.py:534 msgid "File name" msgstr "" -#: extras/forms/bulk_edit.py:174 extras/forms/bulk_edit.py:393 -#: extras/forms/filtersets.py:215 extras/forms/filtersets.py:538 +#: netbox/extras/forms/bulk_edit.py:174 netbox/extras/forms/bulk_edit.py:393 +#: netbox/extras/forms/filtersets.py:215 netbox/extras/forms/filtersets.py:538 msgid "File extension" msgstr "" -#: extras/forms/bulk_edit.py:179 extras/forms/bulk_edit.py:398 -#: extras/forms/filtersets.py:219 extras/forms/filtersets.py:542 +#: netbox/extras/forms/bulk_edit.py:179 netbox/extras/forms/bulk_edit.py:398 +#: netbox/extras/forms/filtersets.py:219 netbox/extras/forms/filtersets.py:542 msgid "As attachment" msgstr "" -#: extras/forms/bulk_edit.py:207 extras/forms/bulk_edit.py:235 -#: extras/forms/filtersets.py:264 extras/forms/filtersets.py:295 -#: extras/tables/tables.py:326 extras/tables/tables.py:363 +#: netbox/extras/forms/bulk_edit.py:207 netbox/extras/forms/bulk_edit.py:235 +#: netbox/extras/forms/filtersets.py:264 netbox/extras/forms/filtersets.py:295 +#: netbox/extras/tables/tables.py:326 netbox/extras/tables/tables.py:363 msgid "Shared" msgstr "" -#: extras/forms/bulk_edit.py:258 extras/forms/filtersets.py:325 -#: extras/models/models.py:197 extras/ui/panels.py:338 +#: netbox/extras/forms/bulk_edit.py:258 netbox/extras/forms/filtersets.py:325 +#: netbox/extras/models/models.py:197 netbox/extras/ui/panels.py:338 msgid "HTTP method" msgstr "" -#: extras/forms/bulk_edit.py:262 extras/forms/filtersets.py:319 -#: extras/ui/panels.py:339 +#: netbox/extras/forms/bulk_edit.py:262 netbox/extras/forms/filtersets.py:319 +#: netbox/extras/ui/panels.py:339 msgid "Payload URL" msgstr "" -#: extras/forms/bulk_edit.py:267 extras/models/models.py:237 -#: extras/ui/panels.py:347 +#: netbox/extras/forms/bulk_edit.py:267 netbox/extras/models/models.py:237 +#: netbox/extras/ui/panels.py:347 msgid "SSL verification" msgstr "" -#: extras/forms/bulk_edit.py:270 +#: netbox/extras/forms/bulk_edit.py:270 msgid "Secret" msgstr "" -#: extras/forms/bulk_edit.py:275 extras/ui/panels.py:348 +#: netbox/extras/forms/bulk_edit.py:275 netbox/extras/ui/panels.py:348 msgid "CA file path" msgstr "" -#: extras/forms/bulk_edit.py:296 extras/forms/bulk_import.py:269 -#: extras/forms/model_forms.py:540 +#: netbox/extras/forms/bulk_edit.py:296 netbox/extras/forms/bulk_import.py:269 +#: netbox/extras/forms/model_forms.py:540 msgid "Event types" msgstr "" -#: extras/forms/bulk_edit.py:357 +#: netbox/extras/forms/bulk_edit.py:357 msgid "Is active" msgstr "" -#: extras/forms/bulk_edit.py:408 extras/forms/bulk_import.py:216 -#: extras/forms/filtersets.py:522 +#: netbox/extras/forms/bulk_edit.py:408 netbox/extras/forms/bulk_import.py:216 +#: netbox/extras/forms/filtersets.py:522 msgid "Auto sync enabled" msgstr "" -#: extras/forms/bulk_import.py:43 extras/forms/bulk_import.py:156 -#: extras/forms/bulk_import.py:177 extras/forms/bulk_import.py:239 -#: extras/forms/bulk_import.py:263 extras/forms/bulk_import.py:313 -#: extras/forms/filtersets.py:57 extras/forms/filtersets.py:156 -#: extras/forms/filtersets.py:252 extras/forms/filtersets.py:283 -#: extras/forms/model_forms.py:58 extras/forms/model_forms.py:306 -#: extras/forms/model_forms.py:338 extras/forms/model_forms.py:381 -#: extras/forms/model_forms.py:535 extras/forms/model_forms.py:652 -#: users/forms/model_forms.py:327 +#: netbox/extras/forms/bulk_import.py:43 netbox/extras/forms/bulk_import.py:156 +#: netbox/extras/forms/bulk_import.py:177 +#: netbox/extras/forms/bulk_import.py:239 +#: netbox/extras/forms/bulk_import.py:263 +#: netbox/extras/forms/bulk_import.py:313 netbox/extras/forms/filtersets.py:57 +#: netbox/extras/forms/filtersets.py:156 netbox/extras/forms/filtersets.py:252 +#: netbox/extras/forms/filtersets.py:283 netbox/extras/forms/model_forms.py:58 +#: netbox/extras/forms/model_forms.py:306 +#: netbox/extras/forms/model_forms.py:338 +#: netbox/extras/forms/model_forms.py:381 +#: netbox/extras/forms/model_forms.py:535 +#: netbox/extras/forms/model_forms.py:652 netbox/users/forms/model_forms.py:318 msgid "Object types" msgstr "" -#: extras/forms/bulk_import.py:45 extras/forms/bulk_import.py:158 -#: extras/forms/bulk_import.py:179 extras/forms/bulk_import.py:241 -#: extras/forms/bulk_import.py:265 extras/forms/bulk_import.py:315 -#: tenancy/forms/bulk_import.py:106 +#: netbox/extras/forms/bulk_import.py:45 netbox/extras/forms/bulk_import.py:158 +#: netbox/extras/forms/bulk_import.py:179 +#: netbox/extras/forms/bulk_import.py:241 +#: netbox/extras/forms/bulk_import.py:265 +#: netbox/extras/forms/bulk_import.py:315 +#: netbox/tenancy/forms/bulk_import.py:106 msgid "One or more assigned object types" msgstr "" -#: extras/forms/bulk_import.py:50 +#: netbox/extras/forms/bulk_import.py:50 msgid "Field data type (e.g. text, integer, etc.)" msgstr "" -#: extras/forms/bulk_import.py:56 +#: netbox/extras/forms/bulk_import.py:56 msgid "Object type (for object or multi-object fields)" msgstr "" -#: extras/forms/bulk_import.py:59 extras/forms/filtersets.py:94 +#: netbox/extras/forms/bulk_import.py:59 netbox/extras/forms/filtersets.py:94 msgid "Choice set" msgstr "" -#: extras/forms/bulk_import.py:63 +#: netbox/extras/forms/bulk_import.py:63 msgid "Choice set (for selection fields)" msgstr "" -#: extras/forms/bulk_import.py:69 +#: netbox/extras/forms/bulk_import.py:69 msgid "Whether the custom field is displayed in the UI" msgstr "" -#: extras/forms/bulk_import.py:75 +#: netbox/extras/forms/bulk_import.py:75 msgid "Whether the custom field is editable in the UI" msgstr "" -#: extras/forms/bulk_import.py:92 +#: netbox/extras/forms/bulk_import.py:92 msgid "The base set of predefined choices to use (if any)" msgstr "" -#: extras/forms/bulk_import.py:98 +#: netbox/extras/forms/bulk_import.py:98 msgid "" "Quoted string of comma-separated field choices with optional labels " "separated by colon: \"choice1:First Choice,choice2:Second Choice\"" msgstr "" -#: extras/forms/bulk_import.py:106 +#: netbox/extras/forms/bulk_import.py:106 #, python-brace-format msgid "" "Quoted string of comma-separated color mappings in the format \"choice1:red," "choice2:green\". Supported colors: {colors}" msgstr "" -#: extras/forms/bulk_import.py:140 extras/forms/model_forms.py:291 +#: netbox/extras/forms/bulk_import.py:140 +#: netbox/extras/forms/model_forms.py:291 #, python-brace-format msgid "Invalid color mapping '{line}'. Use the format value:color." msgstr "" -#: extras/forms/bulk_import.py:147 extras/forms/model_forms.py:298 +#: netbox/extras/forms/bulk_import.py:147 +#: netbox/extras/forms/model_forms.py:298 #, python-brace-format msgid "Duplicate color mapping defined for choice '{value}'." msgstr "" -#: extras/forms/bulk_import.py:161 extras/models/models.py:345 +#: netbox/extras/forms/bulk_import.py:161 netbox/extras/models/models.py:345 msgid "button class" msgstr "" -#: extras/forms/bulk_import.py:164 extras/models/models.py:349 +#: netbox/extras/forms/bulk_import.py:164 netbox/extras/models/models.py:349 msgid "" "The class of the first link in a group will be used for the dropdown button" msgstr "" -#: extras/forms/bulk_import.py:205 +#: netbox/extras/forms/bulk_import.py:205 msgid "Data source which provides the data file" msgstr "" -#: extras/forms/bulk_import.py:208 extras/forms/filtersets.py:196 -#: extras/forms/filtersets.py:396 extras/forms/filtersets.py:428 -#: extras/forms/filtersets.py:516 netbox/choices.py:132 -#: utilities/forms/bulk_import.py:28 +#: netbox/extras/forms/bulk_import.py:208 netbox/extras/forms/filtersets.py:196 +#: netbox/extras/forms/filtersets.py:396 netbox/extras/forms/filtersets.py:428 +#: netbox/extras/forms/filtersets.py:516 netbox/netbox/choices.py:132 +#: netbox/utilities/forms/bulk_import.py:28 msgid "Data file" msgstr "" -#: extras/forms/bulk_import.py:212 +#: netbox/extras/forms/bulk_import.py:212 msgid "Data file containing the template code" msgstr "" -#: extras/forms/bulk_import.py:217 +#: netbox/extras/forms/bulk_import.py:217 msgid "" "Enable automatic synchronization of template content when the data file is " "updated" msgstr "" -#: extras/forms/bulk_import.py:233 extras/forms/model_forms.py:373 -#: extras/forms/model_forms.py:852 +#: netbox/extras/forms/bulk_import.py:233 +#: netbox/extras/forms/model_forms.py:373 +#: netbox/extras/forms/model_forms.py:852 msgid "Must specify either local content or a data file" msgstr "" -#: extras/forms/bulk_import.py:270 +#: netbox/extras/forms/bulk_import.py:270 msgid "The event type(s) which will trigger this rule" msgstr "" -#: extras/forms/bulk_import.py:273 +#: netbox/extras/forms/bulk_import.py:273 msgid "Action object" msgstr "" -#: extras/forms/bulk_import.py:275 +#: netbox/extras/forms/bulk_import.py:275 msgid "Webhook name or script as dotted path module.Class" msgstr "" -#: extras/forms/bulk_import.py:296 +#: netbox/extras/forms/bulk_import.py:296 #, python-brace-format msgid "Webhook {name} not found" msgstr "" -#: extras/forms/bulk_import.py:305 +#: netbox/extras/forms/bulk_import.py:305 #, python-brace-format msgid "Script {name} not found" msgstr "" -#: extras/forms/bulk_import.py:329 +#: netbox/extras/forms/bulk_import.py:329 msgid "Assigned object type" msgstr "" -#: extras/forms/bulk_import.py:334 +#: netbox/extras/forms/bulk_import.py:334 msgid "The classification of entry" msgstr "" -#: extras/forms/bulk_import.py:337 extras/tables/tables.py:768 -#: netbox/tables/tables.py:314 netbox/tables/tables.py:329 -#: netbox/tables/tables.py:352 netbox/ui/panels.py:239 -#: templates/dcim/htmx/cable_edit.html:100 templates/generic/bulk_edit.html:99 -#: templates/inc/panels/comments.html:5 utilities/forms/fields/fields.py:63 +#: netbox/extras/forms/bulk_import.py:337 netbox/extras/tables/tables.py:768 +#: netbox/netbox/tables/tables.py:314 netbox/netbox/tables/tables.py:329 +#: netbox/netbox/tables/tables.py:352 netbox/netbox/ui/panels.py:239 +#: netbox/templates/dcim/htmx/cable_edit.html:100 +#: netbox/templates/generic/bulk_edit.html:99 +#: netbox/templates/inc/panels/comments.html:5 +#: netbox/utilities/forms/fields/fields.py:63 msgid "Comments" msgstr "" -#: extras/forms/bulk_import.py:350 extras/forms/model_forms.py:483 -#: extras/ui/panels.py:321 netbox/navigation/menu.py:423 -#: users/forms/filtersets.py:181 users/forms/model_forms.py:266 -#: users/forms/model_forms.py:278 users/forms/model_forms.py:353 -#: users/forms/model_forms.py:549 users/forms/model_forms.py:564 -#: users/tables.py:136 users/tables.py:194 +#: netbox/extras/forms/bulk_import.py:350 +#: netbox/extras/forms/model_forms.py:483 netbox/extras/ui/panels.py:321 +#: netbox/netbox/navigation/menu.py:423 netbox/users/forms/filtersets.py:181 +#: netbox/users/forms/model_forms.py:257 netbox/users/forms/model_forms.py:269 +#: netbox/users/forms/model_forms.py:344 netbox/users/forms/model_forms.py:540 +#: netbox/users/forms/model_forms.py:555 netbox/users/tables.py:136 +#: netbox/users/tables.py:194 msgid "Users" msgstr "" -#: extras/forms/bulk_import.py:354 +#: netbox/extras/forms/bulk_import.py:354 msgid "User names separated by commas, encased with double quotes" msgstr "" -#: extras/forms/bulk_import.py:357 extras/forms/model_forms.py:478 -#: extras/ui/panels.py:316 netbox/navigation/menu.py:306 -#: netbox/navigation/menu.py:424 tenancy/forms/bulk_edit.py:121 -#: tenancy/forms/filtersets.py:107 tenancy/forms/model_forms.py:93 -#: tenancy/tables/contacts.py:57 tenancy/tables/contacts.py:101 -#: tenancy/ui/panels.py:12 users/forms/filtersets.py:176 -#: users/forms/model_forms.py:211 users/forms/model_forms.py:223 -#: users/forms/model_forms.py:358 users/forms/model_forms.py:548 -#: users/tables.py:68 users/tables.py:140 users/tables.py:190 +#: netbox/extras/forms/bulk_import.py:357 +#: netbox/extras/forms/model_forms.py:478 netbox/extras/ui/panels.py:316 +#: netbox/netbox/navigation/menu.py:306 netbox/netbox/navigation/menu.py:424 +#: netbox/tenancy/forms/bulk_edit.py:121 netbox/tenancy/forms/filtersets.py:107 +#: netbox/tenancy/forms/model_forms.py:93 netbox/tenancy/tables/contacts.py:57 +#: netbox/tenancy/tables/contacts.py:101 netbox/tenancy/ui/panels.py:12 +#: netbox/users/forms/filtersets.py:176 netbox/users/forms/model_forms.py:202 +#: netbox/users/forms/model_forms.py:214 netbox/users/forms/model_forms.py:349 +#: netbox/users/forms/model_forms.py:539 netbox/users/tables.py:68 +#: netbox/users/tables.py:140 netbox/users/tables.py:190 msgid "Groups" msgstr "" -#: extras/forms/bulk_import.py:361 +#: netbox/extras/forms/bulk_import.py:361 msgid "Group names separated by commas, encased with double quotes" msgstr "" -#: extras/forms/filtersets.py:49 +#: netbox/extras/forms/filtersets.py:49 msgid "Type Options" msgstr "" -#: extras/forms/filtersets.py:62 extras/forms/model_forms.py:67 +#: netbox/extras/forms/filtersets.py:62 netbox/extras/forms/model_forms.py:67 msgid "Related object type" msgstr "" -#: extras/forms/filtersets.py:67 +#: netbox/extras/forms/filtersets.py:67 msgid "Field type" msgstr "" -#: extras/forms/filtersets.py:131 extras/forms/model_forms.py:183 -#: extras/tables/tables.py:109 templates/generic/bulk_import.html:185 +#: netbox/extras/forms/filtersets.py:131 netbox/extras/forms/model_forms.py:183 +#: netbox/extras/tables/tables.py:109 +#: netbox/templates/generic/bulk_import.html:185 msgid "Choices" msgstr "" -#: extras/forms/filtersets.py:185 extras/forms/filtersets.py:505 -#: extras/forms/model_forms.py:351 extras/forms/model_forms.py:827 +#: netbox/extras/forms/filtersets.py:185 netbox/extras/forms/filtersets.py:505 +#: netbox/extras/forms/model_forms.py:351 +#: netbox/extras/forms/model_forms.py:827 msgid "Rendering" msgstr "" -#: extras/forms/filtersets.py:204 +#: netbox/extras/forms/filtersets.py:204 msgid "Content types" msgstr "" -#: extras/forms/filtersets.py:315 extras/models/models.py:202 -#: extras/ui/panels.py:340 +#: netbox/extras/forms/filtersets.py:315 netbox/extras/models/models.py:202 +#: netbox/extras/ui/panels.py:340 msgid "HTTP content type" msgstr "" -#: extras/forms/filtersets.py:345 +#: netbox/extras/forms/filtersets.py:345 msgid "Event type" msgstr "" -#: extras/forms/filtersets.py:350 +#: netbox/extras/forms/filtersets.py:350 msgid "Action type" msgstr "" -#: extras/forms/filtersets.py:372 +#: netbox/extras/forms/filtersets.py:372 msgid "Tagged object type" msgstr "" -#: extras/forms/filtersets.py:377 +#: netbox/extras/forms/filtersets.py:377 msgid "Allowed object type" msgstr "" -#: extras/forms/filtersets.py:436 extras/forms/model_forms.py:700 -#: netbox/navigation/menu.py:20 +#: netbox/extras/forms/filtersets.py:436 netbox/extras/forms/model_forms.py:700 +#: netbox/netbox/navigation/menu.py:20 msgid "Regions" msgstr "" -#: extras/forms/filtersets.py:441 extras/forms/model_forms.py:705 +#: netbox/extras/forms/filtersets.py:441 netbox/extras/forms/model_forms.py:705 msgid "Site groups" msgstr "" -#: extras/forms/filtersets.py:451 extras/forms/model_forms.py:715 -#: netbox/navigation/menu.py:23 +#: netbox/extras/forms/filtersets.py:451 netbox/extras/forms/model_forms.py:715 +#: netbox/netbox/navigation/menu.py:23 msgid "Locations" msgstr "" -#: extras/forms/filtersets.py:456 extras/forms/model_forms.py:720 +#: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/model_forms.py:720 msgid "Device types" msgstr "" -#: extras/forms/filtersets.py:461 extras/forms/model_forms.py:725 +#: netbox/extras/forms/filtersets.py:461 netbox/extras/forms/model_forms.py:725 msgid "Roles" msgstr "" -#: extras/forms/filtersets.py:471 extras/forms/model_forms.py:735 +#: netbox/extras/forms/filtersets.py:471 netbox/extras/forms/model_forms.py:735 msgid "Cluster types" msgstr "" -#: extras/forms/filtersets.py:476 extras/forms/model_forms.py:740 +#: netbox/extras/forms/filtersets.py:476 netbox/extras/forms/model_forms.py:740 msgid "Cluster groups" msgstr "" -#: extras/forms/filtersets.py:481 extras/forms/model_forms.py:745 -#: netbox/navigation/menu.py:275 netbox/navigation/menu.py:277 -#: virtualization/tables/clusters.py:23 virtualization/tables/clusters.py:46 +#: netbox/extras/forms/filtersets.py:481 netbox/extras/forms/model_forms.py:745 +#: netbox/netbox/navigation/menu.py:275 netbox/netbox/navigation/menu.py:277 +#: netbox/virtualization/tables/clusters.py:23 +#: netbox/virtualization/tables/clusters.py:46 msgid "Clusters" msgstr "" -#: extras/forms/filtersets.py:486 extras/forms/model_forms.py:750 +#: netbox/extras/forms/filtersets.py:486 netbox/extras/forms/model_forms.py:750 msgid "Tenant groups" msgstr "" -#: extras/forms/model_forms.py:60 +#: netbox/extras/forms/model_forms.py:60 msgid "The type(s) of object that have this custom field" msgstr "" -#: extras/forms/model_forms.py:63 extras/ui/panels.py:139 +#: netbox/extras/forms/model_forms.py:63 netbox/extras/ui/panels.py:139 msgid "Default value" msgstr "" -#: extras/forms/model_forms.py:69 +#: netbox/extras/forms/model_forms.py:69 msgid "Type of the related object (for object/multi-object fields only)" msgstr "" -#: extras/forms/model_forms.py:72 +#: netbox/extras/forms/model_forms.py:72 msgid "Related object filter" msgstr "" -#: extras/forms/model_forms.py:74 +#: netbox/extras/forms/model_forms.py:74 msgid "Specify query parameters as a JSON object." msgstr "" -#: extras/forms/model_forms.py:82 extras/models/customfields.py:233 +#: netbox/extras/forms/model_forms.py:82 +#: netbox/extras/models/customfields.py:233 msgid "A JSON schema definition for validating the custom field value" msgstr "" -#: extras/forms/model_forms.py:89 extras/ui/panels.py:125 +#: netbox/extras/forms/model_forms.py:89 netbox/extras/ui/panels.py:125 msgid "Custom Field" msgstr "" -#: extras/forms/model_forms.py:101 +#: netbox/extras/forms/model_forms.py:101 msgid "" "The type of data stored in this field. For object/multi-object fields, " "select the related object type below." msgstr "" -#: extras/forms/model_forms.py:104 +#: netbox/extras/forms/model_forms.py:104 msgid "" "This will be displayed as help text for the form field. Markdown is " "supported." msgstr "" -#: extras/forms/model_forms.py:169 +#: netbox/extras/forms/model_forms.py:169 msgid "Related Object" msgstr "" -#: extras/forms/model_forms.py:196 +#: netbox/extras/forms/model_forms.py:196 msgid "" "Enter one choice per line. An optional label may be specified for each " "choice by appending it with a colon. Example:" msgstr "" -#: extras/forms/model_forms.py:205 +#: netbox/extras/forms/model_forms.py:205 msgid "" "Bind an optional color to a choice by its value. Enter one mapping per line " "as value:color. Example:" msgstr "" -#: extras/forms/model_forms.py:209 +#: netbox/extras/forms/model_forms.py:209 #, python-brace-format msgid "Supported colors: {colors}" msgstr "" -#: extras/forms/model_forms.py:218 extras/ui/panels.py:192 +#: netbox/extras/forms/model_forms.py:218 netbox/extras/ui/panels.py:192 msgid "Custom Field Choice Set" msgstr "" -#: extras/forms/model_forms.py:313 extras/ui/panels.py:219 +#: netbox/extras/forms/model_forms.py:313 netbox/extras/ui/panels.py:219 msgid "Custom Link" msgstr "" -#: extras/forms/model_forms.py:315 +#: netbox/extras/forms/model_forms.py:315 msgid "Templates" msgstr "" -#: extras/forms/model_forms.py:327 +#: netbox/extras/forms/model_forms.py:327 #, python-brace-format msgid "" "Jinja2 template code for the link text. Reference the object as {example}. " "Links which render as empty text will not be displayed." msgstr "" -#: extras/forms/model_forms.py:331 +#: netbox/extras/forms/model_forms.py:331 #, python-brace-format msgid "" "Jinja2 template code for the link URL. Reference the object as {example}." msgstr "" -#: extras/forms/model_forms.py:342 extras/forms/model_forms.py:817 +#: netbox/extras/forms/model_forms.py:342 +#: netbox/extras/forms/model_forms.py:817 msgid "Template code" msgstr "" -#: extras/forms/model_forms.py:348 extras/ui/panels.py:234 +#: netbox/extras/forms/model_forms.py:348 netbox/extras/ui/panels.py:234 msgid "Export Template" msgstr "" -#: extras/forms/model_forms.py:366 extras/forms/model_forms.py:845 +#: netbox/extras/forms/model_forms.py:366 +#: netbox/extras/forms/model_forms.py:845 msgid "Template content is populated from the remote source selected below." msgstr "" -#: extras/forms/model_forms.py:387 extras/ui/panels.py:249 -#: netbox/forms/mixins.py:103 +#: netbox/extras/forms/model_forms.py:387 netbox/extras/ui/panels.py:249 +#: netbox/netbox/forms/mixins.py:103 msgid "Saved Filter" msgstr "" -#: extras/forms/model_forms.py:413 extras/ui/panels.py:294 -#: templates/account/preferences.html:50 +#: netbox/extras/forms/model_forms.py:413 netbox/extras/ui/panels.py:294 +#: netbox/templates/account/preferences.html:50 msgid "Ordering" msgstr "" -#: extras/forms/model_forms.py:415 +#: netbox/extras/forms/model_forms.py:415 msgid "" "Enter a comma-separated list of column names. Prepend a name with a hyphen " "to reverse the order." msgstr "" -#: extras/forms/model_forms.py:424 utilities/forms/forms.py:164 +#: netbox/extras/forms/model_forms.py:424 netbox/utilities/forms/forms.py:164 msgid "Available Columns" msgstr "" -#: extras/forms/model_forms.py:431 utilities/forms/forms.py:172 +#: netbox/extras/forms/model_forms.py:431 netbox/utilities/forms/forms.py:172 msgid "Selected Columns" msgstr "" -#: extras/forms/model_forms.py:497 +#: netbox/extras/forms/model_forms.py:497 msgid "A notification group specify at least one user or group." msgstr "" -#: extras/forms/model_forms.py:519 extras/ui/panels.py:336 +#: netbox/extras/forms/model_forms.py:519 netbox/extras/ui/panels.py:336 msgid "HTTP Request" msgstr "" -#: extras/forms/model_forms.py:521 extras/ui/panels.py:345 +#: netbox/extras/forms/model_forms.py:521 netbox/extras/ui/panels.py:345 msgid "SSL" msgstr "" -#: extras/forms/model_forms.py:543 +#: netbox/extras/forms/model_forms.py:543 msgid "Action choice" msgstr "" -#: extras/forms/model_forms.py:548 +#: netbox/extras/forms/model_forms.py:548 msgid "Enter conditions in JSON format." msgstr "" -#: extras/forms/model_forms.py:552 +#: netbox/extras/forms/model_forms.py:552 msgid "" "Enter parameters to pass to the action in JSON format." msgstr "" -#: extras/forms/model_forms.py:557 extras/ui/panels.py:356 +#: netbox/extras/forms/model_forms.py:557 netbox/extras/ui/panels.py:356 msgid "Event Rule" msgstr "" -#: extras/forms/model_forms.py:558 +#: netbox/extras/forms/model_forms.py:558 msgid "Triggers" msgstr "" -#: extras/forms/model_forms.py:605 +#: netbox/extras/forms/model_forms.py:605 msgid "Notification group" msgstr "" -#: extras/forms/model_forms.py:681 extras/ui/panels.py:424 +#: netbox/extras/forms/model_forms.py:681 netbox/extras/ui/panels.py:424 msgid "Config Context Profile" msgstr "" -#: extras/forms/model_forms.py:755 netbox/navigation/menu.py:29 -#: tenancy/tables/tenants.py:18 +#: netbox/extras/forms/model_forms.py:755 netbox/netbox/navigation/menu.py:29 +#: netbox/tenancy/tables/tenants.py:18 msgid "Tenants" msgstr "" -#: extras/forms/model_forms.py:799 +#: netbox/extras/forms/model_forms.py:799 msgid "Data is populated from the remote source selected below." msgstr "" -#: extras/forms/model_forms.py:805 +#: netbox/extras/forms/model_forms.py:805 msgid "Must specify either local data or a data file" msgstr "" -#: extras/forms/reports.py:17 extras/forms/scripts.py:27 +#: netbox/extras/forms/reports.py:17 netbox/extras/forms/scripts.py:27 msgid "Schedule at" msgstr "" -#: extras/forms/reports.py:18 +#: netbox/extras/forms/reports.py:18 msgid "Schedule execution of report to a set time" msgstr "" -#: extras/forms/reports.py:23 extras/forms/scripts.py:33 +#: netbox/extras/forms/reports.py:23 netbox/extras/forms/scripts.py:33 msgid "Recurs every" msgstr "" -#: extras/forms/reports.py:27 +#: netbox/extras/forms/reports.py:27 msgid "Interval at which this report is re-run (in minutes)" msgstr "" -#: extras/forms/reports.py:35 extras/forms/scripts.py:52 +#: netbox/extras/forms/reports.py:35 netbox/extras/forms/scripts.py:52 #, python-brace-format msgid " (current time: {now})" msgstr "" -#: extras/forms/scripts.py:21 +#: netbox/extras/forms/scripts.py:21 msgid "Commit changes" msgstr "" -#: extras/forms/scripts.py:22 +#: netbox/extras/forms/scripts.py:22 msgid "Commit changes to the database (uncheck for a dry-run)" msgstr "" -#: extras/forms/scripts.py:28 +#: netbox/extras/forms/scripts.py:28 msgid "Schedule execution of script to a set time" msgstr "" -#: extras/forms/scripts.py:37 +#: netbox/extras/forms/scripts.py:37 msgid "Interval at which this script is re-run (in minutes)" msgstr "" -#: extras/forms/scripts.py:43 templates/account/base.html:13 -#: templates/account/notifications.html:7 templates/inc/user_menu.html:15 +#: netbox/extras/forms/scripts.py:43 netbox/templates/account/base.html:13 +#: netbox/templates/account/notifications.html:7 +#: netbox/templates/inc/user_menu.html:15 msgid "Notifications" msgstr "" -#: extras/forms/scripts.py:44 +#: netbox/extras/forms/scripts.py:44 msgid "When to notify the user of job completion" msgstr "" -#: extras/jobs.py:64 +#: netbox/extras/jobs.py:64 msgid "Database changes have been reverted automatically." msgstr "" -#: extras/jobs.py:70 +#: netbox/extras/jobs.py:70 msgid "Script aborted with error: " msgstr "" -#: extras/jobs.py:81 +#: netbox/extras/jobs.py:81 msgid "An exception occurred: " msgstr "" -#: extras/jobs.py:87 +#: netbox/extras/jobs.py:87 msgid "Database changes have been reverted due to error." msgstr "" -#: extras/management/commands/reindex.py:67 +#: netbox/extras/management/commands/reindex.py:67 msgid "No indexers found!" msgstr "" -#: extras/models/configs.py:51 +#: netbox/extras/models/configs.py:51 msgid "" "A JSON schema specifying the structure of the context data for this profile" msgstr "" -#: extras/models/configs.py:58 +#: netbox/extras/models/configs.py:58 msgid "config context profile" msgstr "" -#: extras/models/configs.py:59 +#: netbox/extras/models/configs.py:59 msgid "config context profiles" msgstr "" -#: extras/models/configs.py:91 extras/models/models.py:335 -#: extras/models/models.py:507 extras/models/models.py:589 -#: extras/models/search.py:49 extras/models/tags.py:45 ipam/models/ip.py:200 -#: netbox/models/mixins.py:32 +#: netbox/extras/models/configs.py:91 netbox/extras/models/models.py:335 +#: netbox/extras/models/models.py:507 netbox/extras/models/models.py:589 +#: netbox/extras/models/search.py:49 netbox/extras/models/tags.py:45 +#: netbox/ipam/models/ip.py:200 netbox/netbox/models/mixins.py:32 msgid "weight" msgstr "" -#: extras/models/configs.py:182 +#: netbox/extras/models/configs.py:182 msgid "config context" msgstr "" -#: extras/models/configs.py:183 +#: netbox/extras/models/configs.py:183 msgid "config contexts" msgstr "" -#: extras/models/configs.py:201 extras/models/configs.py:264 +#: netbox/extras/models/configs.py:201 netbox/extras/models/configs.py:264 msgid "JSON data must be in object form. Example:" msgstr "" -#: extras/models/configs.py:209 +#: netbox/extras/models/configs.py:209 #, python-brace-format msgid "Data does not conform to profile schema: {error}" msgstr "" -#: extras/models/configs.py:228 +#: netbox/extras/models/configs.py:228 msgid "" "Local config context data takes precedence over source contexts in the final " "rendered config context" msgstr "" -#: extras/models/configs.py:291 +#: netbox/extras/models/configs.py:291 msgid "debug" msgstr "" -#: extras/models/configs.py:294 +#: netbox/extras/models/configs.py:294 msgid "" "Enable verbose error output when rendering this template. Not recommended " "for production use." msgstr "" -#: extras/models/configs.py:303 +#: netbox/extras/models/configs.py:303 msgid "config template" msgstr "" -#: extras/models/configs.py:304 +#: netbox/extras/models/configs.py:304 msgid "config templates" msgstr "" -#: extras/models/configs.py:330 +#: netbox/extras/models/configs.py:330 #, python-brace-format msgid "Template: {name}" msgstr "" -#: extras/models/configs.py:332 +#: netbox/extras/models/configs.py:332 #, python-brace-format msgid "Line: {lineno}" msgstr "" -#: extras/models/customfields.py:102 +#: netbox/extras/models/customfields.py:102 msgid "The object(s) to which this field applies." msgstr "" -#: extras/models/customfields.py:109 +#: netbox/extras/models/customfields.py:109 msgid "The type of data this custom field holds" msgstr "" -#: extras/models/customfields.py:116 +#: netbox/extras/models/customfields.py:116 msgid "The type of NetBox object this field maps to (for object fields)" msgstr "" -#: extras/models/customfields.py:122 +#: netbox/extras/models/customfields.py:122 msgid "Internal field name" msgstr "" -#: extras/models/customfields.py:126 +#: netbox/extras/models/customfields.py:126 msgid "Only alphanumeric characters and underscores are allowed." msgstr "" -#: extras/models/customfields.py:131 +#: netbox/extras/models/customfields.py:131 msgid "Double underscores are not permitted in custom field names." msgstr "" -#: extras/models/customfields.py:142 +#: netbox/extras/models/customfields.py:142 msgid "" "Name of the field as displayed to users (if not provided, 'the field's name " "will be used)" msgstr "" -#: extras/models/customfields.py:146 extras/models/models.py:339 +#: netbox/extras/models/customfields.py:146 netbox/extras/models/models.py:339 msgid "group name" msgstr "" -#: extras/models/customfields.py:149 +#: netbox/extras/models/customfields.py:149 msgid "Custom fields within the same group will be displayed together" msgstr "" -#: extras/models/customfields.py:157 +#: netbox/extras/models/customfields.py:157 msgid "required" msgstr "" -#: extras/models/customfields.py:159 +#: netbox/extras/models/customfields.py:159 msgid "" "This field is required when creating new objects or editing an existing " "object." msgstr "" -#: extras/models/customfields.py:162 +#: netbox/extras/models/customfields.py:162 msgid "must be unique" msgstr "" -#: extras/models/customfields.py:164 +#: netbox/extras/models/customfields.py:164 msgid "The value of this field must be unique for the assigned object" msgstr "" -#: extras/models/customfields.py:167 +#: netbox/extras/models/customfields.py:167 msgid "search weight" msgstr "" -#: extras/models/customfields.py:170 +#: netbox/extras/models/customfields.py:170 msgid "" "Weighting for search. Lower values are considered more important. Fields " "with a search weight of zero will be ignored." msgstr "" -#: extras/models/customfields.py:175 +#: netbox/extras/models/customfields.py:175 msgid "filter logic" msgstr "" -#: extras/models/customfields.py:179 +#: netbox/extras/models/customfields.py:179 msgid "" "Loose matches any instance of a given string; exact matches the entire field." msgstr "" -#: extras/models/customfields.py:182 +#: netbox/extras/models/customfields.py:182 msgid "default" msgstr "" -#: extras/models/customfields.py:186 +#: netbox/extras/models/customfields.py:186 msgid "" "Default value for the field (must be a JSON value). Encapsulate strings with " "double quotes (e.g. \"Foo\")." msgstr "" -#: extras/models/customfields.py:193 +#: netbox/extras/models/customfields.py:193 msgid "" "Filter the object selection choices using a query_params dict (must be a " "JSON value).Encapsulate strings with double quotes (e.g. \"Foo\")." msgstr "" -#: extras/models/customfields.py:199 +#: netbox/extras/models/customfields.py:199 msgid "display weight" msgstr "" -#: extras/models/customfields.py:200 +#: netbox/extras/models/customfields.py:200 msgid "Fields with higher weights appear lower in a form." msgstr "" -#: extras/models/customfields.py:207 +#: netbox/extras/models/customfields.py:207 msgid "minimum value" msgstr "" -#: extras/models/customfields.py:208 +#: netbox/extras/models/customfields.py:208 msgid "Minimum allowed value (for numeric fields)" msgstr "" -#: extras/models/customfields.py:215 +#: netbox/extras/models/customfields.py:215 msgid "maximum value" msgstr "" -#: extras/models/customfields.py:216 +#: netbox/extras/models/customfields.py:216 msgid "Maximum allowed value (for numeric fields)" msgstr "" -#: extras/models/customfields.py:222 +#: netbox/extras/models/customfields.py:222 msgid "validation regex" msgstr "" -#: extras/models/customfields.py:224 +#: netbox/extras/models/customfields.py:224 #, python-brace-format msgid "" "Regular expression to enforce on text field values. Use ^ and $ to force " @@ -9034,337 +9483,342 @@ msgid "" "values to exactly three uppercase letters." msgstr "" -#: extras/models/customfields.py:232 +#: netbox/extras/models/customfields.py:232 msgid "validation schema" msgstr "" -#: extras/models/customfields.py:239 +#: netbox/extras/models/customfields.py:239 msgid "choice set" msgstr "" -#: extras/models/customfields.py:248 +#: netbox/extras/models/customfields.py:248 msgid "Specifies whether the custom field is displayed in the UI" msgstr "" -#: extras/models/customfields.py:255 +#: netbox/extras/models/customfields.py:255 msgid "Specifies whether the custom field value can be edited in the UI" msgstr "" -#: extras/models/customfields.py:259 +#: netbox/extras/models/customfields.py:259 msgid "is cloneable" msgstr "" -#: extras/models/customfields.py:260 +#: netbox/extras/models/customfields.py:260 msgid "Replicate this value when cloning objects" msgstr "" -#: extras/models/customfields.py:280 +#: netbox/extras/models/customfields.py:280 msgid "custom field" msgstr "" -#: extras/models/customfields.py:281 +#: netbox/extras/models/customfields.py:281 msgid "custom fields" msgstr "" -#: extras/models/customfields.py:388 +#: netbox/extras/models/customfields.py:388 #, python-brace-format msgid "Invalid default value \"{value}\": {error}" msgstr "" -#: extras/models/customfields.py:395 +#: netbox/extras/models/customfields.py:395 msgid "A minimum value may be set only for numeric fields" msgstr "" -#: extras/models/customfields.py:397 +#: netbox/extras/models/customfields.py:397 msgid "A maximum value may be set only for numeric fields" msgstr "" -#: extras/models/customfields.py:407 +#: netbox/extras/models/customfields.py:407 msgid "Regular expression validation is supported only for text and URL fields" msgstr "" -#: extras/models/customfields.py:413 +#: netbox/extras/models/customfields.py:413 msgid "JSON schema validation is supported only for JSON fields" msgstr "" -#: extras/models/customfields.py:419 +#: netbox/extras/models/customfields.py:419 msgid "Uniqueness cannot be enforced for boolean fields" msgstr "" -#: extras/models/customfields.py:429 +#: netbox/extras/models/customfields.py:429 msgid "Selection fields must specify a set of choices." msgstr "" -#: extras/models/customfields.py:433 +#: netbox/extras/models/customfields.py:433 msgid "Choices may be set only on selection fields." msgstr "" -#: extras/models/customfields.py:440 +#: netbox/extras/models/customfields.py:440 msgid "Object fields must define an object type." msgstr "" -#: extras/models/customfields.py:444 +#: netbox/extras/models/customfields.py:444 #, python-brace-format msgid "{type} fields may not define an object type." msgstr "" -#: extras/models/customfields.py:451 +#: netbox/extras/models/customfields.py:451 msgid "A related object filter can be defined only for object fields." msgstr "" -#: extras/models/customfields.py:455 +#: netbox/extras/models/customfields.py:455 msgid "Filter must be defined as a dictionary mapping attributes to values." msgstr "" -#: extras/models/customfields.py:542 +#: netbox/extras/models/customfields.py:542 msgid "True" msgstr "" -#: extras/models/customfields.py:543 +#: netbox/extras/models/customfields.py:543 msgid "False" msgstr "" -#: extras/models/customfields.py:596 extras/models/customfields.py:649 +#: netbox/extras/models/customfields.py:596 +#: netbox/extras/models/customfields.py:649 #, python-brace-format msgid "Values must match this regex: {regex}" msgstr "" -#: extras/models/customfields.py:751 extras/models/customfields.py:758 +#: netbox/extras/models/customfields.py:751 +#: netbox/extras/models/customfields.py:758 msgid "Value must be a string." msgstr "" -#: extras/models/customfields.py:753 extras/models/customfields.py:760 +#: netbox/extras/models/customfields.py:753 +#: netbox/extras/models/customfields.py:760 #, python-brace-format msgid "Value must match regex '{regex}'" msgstr "" -#: extras/models/customfields.py:765 +#: netbox/extras/models/customfields.py:765 msgid "Value must be an integer." msgstr "" -#: extras/models/customfields.py:768 extras/models/customfields.py:783 +#: netbox/extras/models/customfields.py:768 +#: netbox/extras/models/customfields.py:783 #, python-brace-format msgid "Value must be at least {minimum}" msgstr "" -#: extras/models/customfields.py:772 extras/models/customfields.py:787 +#: netbox/extras/models/customfields.py:772 +#: netbox/extras/models/customfields.py:787 #, python-brace-format msgid "Value must not exceed {maximum}" msgstr "" -#: extras/models/customfields.py:780 +#: netbox/extras/models/customfields.py:780 msgid "Value must be a decimal." msgstr "" -#: extras/models/customfields.py:792 +#: netbox/extras/models/customfields.py:792 msgid "Value must be true or false." msgstr "" -#: extras/models/customfields.py:800 +#: netbox/extras/models/customfields.py:800 msgid "Date values must be in ISO 8601 format (YYYY-MM-DD)." msgstr "" -#: extras/models/customfields.py:809 +#: netbox/extras/models/customfields.py:809 msgid "Date and time values must be in ISO 8601 format (YYYY-MM-DD HH:MM:SS)." msgstr "" -#: extras/models/customfields.py:816 +#: netbox/extras/models/customfields.py:816 #, python-brace-format msgid "Invalid choice ({value}) for choice set {choiceset}." msgstr "" -#: extras/models/customfields.py:826 +#: netbox/extras/models/customfields.py:826 #, python-brace-format msgid "Invalid choice(s) ({value}) for choice set {choiceset}." msgstr "" -#: extras/models/customfields.py:835 +#: netbox/extras/models/customfields.py:835 #, python-brace-format msgid "Value must be an object ID, not {type}" msgstr "" -#: extras/models/customfields.py:841 +#: netbox/extras/models/customfields.py:841 #, python-brace-format msgid "Value must be a list of object IDs, not {type}" msgstr "" -#: extras/models/customfields.py:845 +#: netbox/extras/models/customfields.py:845 #, python-brace-format msgid "Found invalid object ID: {id}" msgstr "" -#: extras/models/customfields.py:854 +#: netbox/extras/models/customfields.py:854 #, python-brace-format msgid "Value does not conform to the assigned schema: {error}" msgstr "" -#: extras/models/customfields.py:858 +#: netbox/extras/models/customfields.py:858 msgid "Required field cannot be empty." msgstr "" -#: extras/models/customfields.py:878 +#: netbox/extras/models/customfields.py:878 msgid "Base set of predefined choices (optional)" msgstr "" -#: extras/models/customfields.py:894 +#: netbox/extras/models/customfields.py:894 msgid "Choices are automatically ordered alphabetically" msgstr "" -#: extras/models/customfields.py:901 +#: netbox/extras/models/customfields.py:901 msgid "custom field choice set" msgstr "" -#: extras/models/customfields.py:902 +#: netbox/extras/models/customfields.py:902 msgid "custom field choice sets" msgstr "" -#: extras/models/customfields.py:962 +#: netbox/extras/models/customfields.py:962 msgid "Must define base or extra choices." msgstr "" -#: extras/models/customfields.py:968 +#: netbox/extras/models/customfields.py:968 msgid "Color mappings must be defined as a JSON object." msgstr "" -#: extras/models/customfields.py:980 +#: netbox/extras/models/customfields.py:980 #, python-brace-format msgid "Duplicate value '{value}' found in extra choices." msgstr "" -#: extras/models/customfields.py:997 +#: netbox/extras/models/customfields.py:997 #, python-brace-format msgid "" "Color mappings must reference an existing choice value. Invalid value(s): " "{values}." msgstr "" -#: extras/models/customfields.py:1004 +#: netbox/extras/models/customfields.py:1004 #, python-brace-format msgid "Invalid color value(s): {colors}. Use a supported named color." msgstr "" -#: extras/models/customfields.py:1027 +#: netbox/extras/models/customfields.py:1027 #, python-brace-format msgid "" "Cannot remove choice {choice} as there are {model} objects which reference " "it." msgstr "" -#: extras/models/dashboard.py:18 +#: netbox/extras/models/dashboard.py:18 msgid "layout" msgstr "" -#: extras/models/dashboard.py:22 +#: netbox/extras/models/dashboard.py:22 msgid "config" msgstr "" -#: extras/models/dashboard.py:27 +#: netbox/extras/models/dashboard.py:27 msgid "dashboard" msgstr "" -#: extras/models/dashboard.py:28 +#: netbox/extras/models/dashboard.py:28 msgid "dashboards" msgstr "" -#: extras/models/mixins.py:86 +#: netbox/extras/models/mixins.py:86 msgid "template code" msgstr "" -#: extras/models/mixins.py:87 +#: netbox/extras/models/mixins.py:87 msgid "Jinja template code." msgstr "" -#: extras/models/mixins.py:90 +#: netbox/extras/models/mixins.py:90 msgid "environment parameters" msgstr "" -#: extras/models/mixins.py:95 +#: netbox/extras/models/mixins.py:95 #, python-brace-format msgid "" "Any additional parameters to pass when constructing " "the Jinja environment" msgstr "" -#: extras/models/mixins.py:102 +#: netbox/extras/models/mixins.py:102 #, python-brace-format msgid "Defaults to {default}" msgstr "" -#: extras/models/mixins.py:107 +#: netbox/extras/models/mixins.py:107 msgid "Filename to give to the rendered export file" msgstr "" -#: extras/models/mixins.py:110 +#: netbox/extras/models/mixins.py:110 msgid "file extension" msgstr "" -#: extras/models/mixins.py:113 +#: netbox/extras/models/mixins.py:113 msgid "Extension to append to the rendered filename" msgstr "" -#: extras/models/mixins.py:116 +#: netbox/extras/models/mixins.py:116 msgid "as attachment" msgstr "" -#: extras/models/mixins.py:118 +#: netbox/extras/models/mixins.py:118 msgid "Download file as attachment" msgstr "" -#: extras/models/models.py:64 +#: netbox/extras/models/models.py:64 msgid "The object(s) to which this rule applies." msgstr "" -#: extras/models/models.py:78 +#: netbox/extras/models/models.py:78 msgid "The types of event which will trigger this rule." msgstr "" -#: extras/models/models.py:85 +#: netbox/extras/models/models.py:85 msgid "conditions" msgstr "" -#: extras/models/models.py:88 +#: netbox/extras/models/models.py:88 msgid "" "A set of conditions which determine whether the event will be generated." msgstr "" -#: extras/models/models.py:96 +#: netbox/extras/models/models.py:96 msgid "action type" msgstr "" -#: extras/models/models.py:115 +#: netbox/extras/models/models.py:115 msgid "Additional data to pass to the action object" msgstr "" -#: extras/models/models.py:127 +#: netbox/extras/models/models.py:127 msgid "event rule" msgstr "" -#: extras/models/models.py:128 +#: netbox/extras/models/models.py:128 msgid "event rules" msgstr "" -#: extras/models/models.py:148 +#: netbox/extras/models/models.py:148 msgid "Action data must be a JSON object or null." msgstr "" -#: extras/models/models.py:189 +#: netbox/extras/models/models.py:189 msgid "" "This URL will be called using the HTTP method defined when the webhook is " "called. Jinja2 template processing is supported with the same context as the " "request body." msgstr "" -#: extras/models/models.py:204 +#: netbox/extras/models/models.py:204 msgid "" "The complete list of official content types is available here." msgstr "" -#: extras/models/models.py:209 +#: netbox/extras/models/models.py:209 msgid "additional headers" msgstr "" -#: extras/models/models.py:212 +#: netbox/extras/models/models.py:212 msgid "" "User-supplied HTTP headers to be sent with the request in addition to the " "HTTP content type. Headers should be defined in the format Name: " @@ -9372,11 +9826,11 @@ msgid "" "as the request body (below)." msgstr "" -#: extras/models/models.py:218 +#: netbox/extras/models/models.py:218 msgid "body template" msgstr "" -#: extras/models/models.py:221 +#: netbox/extras/models/models.py:221 msgid "" "Jinja2 template for a custom request body. If blank, a JSON object " "representing the change will be included. Available context data includes: " @@ -9384,4562 +9838,4666 @@ msgid "" "username, request_id, and data." msgstr "" -#: extras/models/models.py:227 +#: netbox/extras/models/models.py:227 msgid "secret" msgstr "" -#: extras/models/models.py:231 +#: netbox/extras/models/models.py:231 msgid "" "When provided, the request will include a X-Hook-Signature " "header containing a HMAC hex digest of the payload body using the secret as " "the key. The secret is not transmitted in the request." msgstr "" -#: extras/models/models.py:238 +#: netbox/extras/models/models.py:238 msgid "Enable SSL certificate verification. Disable with caution!" msgstr "" -#: extras/models/models.py:244 +#: netbox/extras/models/models.py:244 msgid "CA File Path" msgstr "" -#: extras/models/models.py:246 +#: netbox/extras/models/models.py:246 msgid "" "The specific CA certificate file to use for SSL verification. Leave blank to " "use the system defaults." msgstr "" -#: extras/models/models.py:257 +#: netbox/extras/models/models.py:257 msgid "webhook" msgstr "" -#: extras/models/models.py:258 +#: netbox/extras/models/models.py:258 msgid "webhooks" msgstr "" -#: extras/models/models.py:276 +#: netbox/extras/models/models.py:276 msgid "Do not specify a CA certificate file if SSL verification is disabled." msgstr "" -#: extras/models/models.py:315 +#: netbox/extras/models/models.py:315 msgid "The object type(s) to which this link applies." msgstr "" -#: extras/models/models.py:327 +#: netbox/extras/models/models.py:327 msgid "link text" msgstr "" -#: extras/models/models.py:328 +#: netbox/extras/models/models.py:328 msgid "Jinja2 template code for link text" msgstr "" -#: extras/models/models.py:331 +#: netbox/extras/models/models.py:331 msgid "link URL" msgstr "" -#: extras/models/models.py:332 +#: netbox/extras/models/models.py:332 msgid "Jinja2 template code for link URL" msgstr "" -#: extras/models/models.py:342 +#: netbox/extras/models/models.py:342 msgid "Links with the same group will appear as a dropdown menu" msgstr "" -#: extras/models/models.py:352 +#: netbox/extras/models/models.py:352 msgid "new window" msgstr "" -#: extras/models/models.py:354 +#: netbox/extras/models/models.py:354 msgid "Force link to open in a new window" msgstr "" -#: extras/models/models.py:366 +#: netbox/extras/models/models.py:366 msgid "custom link" msgstr "" -#: extras/models/models.py:367 +#: netbox/extras/models/models.py:367 msgid "custom links" msgstr "" -#: extras/models/models.py:421 +#: netbox/extras/models/models.py:421 msgid "The object type(s) to which this template applies." msgstr "" -#: extras/models/models.py:442 +#: netbox/extras/models/models.py:442 msgid "export template" msgstr "" -#: extras/models/models.py:443 +#: netbox/extras/models/models.py:443 msgid "export templates" msgstr "" -#: extras/models/models.py:460 +#: netbox/extras/models/models.py:460 #, python-brace-format msgid "\"{name}\" is a reserved name. Please choose a different name." msgstr "" -#: extras/models/models.py:483 +#: netbox/extras/models/models.py:483 msgid "The object type(s) to which this filter applies." msgstr "" -#: extras/models/models.py:515 extras/models/models.py:597 +#: netbox/extras/models/models.py:515 netbox/extras/models/models.py:597 msgid "shared" msgstr "" -#: extras/models/models.py:531 +#: netbox/extras/models/models.py:531 msgid "saved filter" msgstr "" -#: extras/models/models.py:532 +#: netbox/extras/models/models.py:532 msgid "saved filters" msgstr "" -#: extras/models/models.py:550 +#: netbox/extras/models/models.py:550 msgid "Filter parameters must be stored as a dictionary of keyword arguments." msgstr "" -#: extras/models/models.py:567 +#: netbox/extras/models/models.py:567 msgid "The table's object type" msgstr "" -#: extras/models/models.py:570 +#: netbox/extras/models/models.py:570 msgid "table" msgstr "" -#: extras/models/models.py:616 +#: netbox/extras/models/models.py:616 msgid "table config" msgstr "" -#: extras/models/models.py:617 +#: netbox/extras/models/models.py:617 msgid "table configs" msgstr "" -#: extras/models/models.py:655 +#: netbox/extras/models/models.py:655 #, python-brace-format msgid "Unknown table: {name}" msgstr "" -#: extras/models/models.py:666 extras/models/models.py:673 +#: netbox/extras/models/models.py:666 netbox/extras/models/models.py:673 #, python-brace-format msgid "Unknown column: {name}" msgstr "" -#: extras/models/models.py:696 +#: netbox/extras/models/models.py:696 msgid "image height" msgstr "" -#: extras/models/models.py:699 +#: netbox/extras/models/models.py:699 msgid "image width" msgstr "" -#: extras/models/models.py:722 +#: netbox/extras/models/models.py:722 msgid "image attachment" msgstr "" -#: extras/models/models.py:723 +#: netbox/extras/models/models.py:723 msgid "image attachments" msgstr "" -#: extras/models/models.py:737 +#: netbox/extras/models/models.py:737 #, python-brace-format msgid "Image attachments cannot be assigned to this object type ({type})." msgstr "" -#: extras/models/models.py:818 +#: netbox/extras/models/models.py:818 msgid "kind" msgstr "" -#: extras/models/models.py:833 +#: netbox/extras/models/models.py:833 msgid "journal entry" msgstr "" -#: extras/models/models.py:834 +#: netbox/extras/models/models.py:834 msgid "journal entries" msgstr "" -#: extras/models/models.py:852 +#: netbox/extras/models/models.py:852 #, python-brace-format msgid "Journaling is not supported for this object type ({type})." msgstr "" -#: extras/models/models.py:895 +#: netbox/extras/models/models.py:895 msgid "bookmark" msgstr "" -#: extras/models/models.py:896 +#: netbox/extras/models/models.py:896 msgid "bookmarks" msgstr "" -#: extras/models/models.py:912 +#: netbox/extras/models/models.py:912 #, python-brace-format msgid "Bookmarks cannot be assigned to this object type ({type})." msgstr "" -#: extras/models/notifications.py:43 +#: netbox/extras/models/notifications.py:43 msgid "read" msgstr "" -#: extras/models/notifications.py:66 +#: netbox/extras/models/notifications.py:66 msgid "event" msgstr "" -#: extras/models/notifications.py:85 +#: netbox/extras/models/notifications.py:85 msgid "notification" msgstr "" -#: extras/models/notifications.py:100 extras/models/notifications.py:245 +#: netbox/extras/models/notifications.py:100 +#: netbox/extras/models/notifications.py:245 #, python-brace-format msgid "Objects of this type ({type}) do not support notifications." msgstr "" -#: extras/models/notifications.py:138 users/models/owners.py:52 -#: users/models/users.py:66 users/models/users.py:151 +#: netbox/extras/models/notifications.py:138 netbox/users/models/owners.py:52 +#: netbox/users/models/users.py:66 netbox/users/models/users.py:151 msgid "groups" msgstr "" -#: extras/models/notifications.py:144 users/models/owners.py:59 -#: users/models/users.py:172 +#: netbox/extras/models/notifications.py:144 netbox/users/models/owners.py:59 +#: netbox/users/models/users.py:172 msgid "users" msgstr "" -#: extras/models/notifications.py:159 +#: netbox/extras/models/notifications.py:159 msgid "notification group" msgstr "" -#: extras/models/notifications.py:160 +#: netbox/extras/models/notifications.py:160 msgid "notification groups" msgstr "" -#: extras/models/notifications.py:228 +#: netbox/extras/models/notifications.py:228 msgid "subscription" msgstr "" -#: extras/models/notifications.py:229 +#: netbox/extras/models/notifications.py:229 msgid "subscriptions" msgstr "" -#: extras/models/scripts.py:41 +#: netbox/extras/models/scripts.py:41 msgid "is executable" msgstr "" -#: extras/models/scripts.py:66 +#: netbox/extras/models/scripts.py:66 msgid "script" msgstr "" -#: extras/models/scripts.py:67 +#: netbox/extras/models/scripts.py:67 msgid "scripts" msgstr "" -#: extras/models/scripts.py:113 +#: netbox/extras/models/scripts.py:113 msgid "script module" msgstr "" -#: extras/models/scripts.py:114 +#: netbox/extras/models/scripts.py:114 msgid "script modules" msgstr "" -#: extras/models/search.py:23 +#: netbox/extras/models/search.py:23 msgid "timestamp" msgstr "" -#: extras/models/search.py:38 +#: netbox/extras/models/search.py:38 msgid "field" msgstr "" -#: extras/models/search.py:46 +#: netbox/extras/models/search.py:46 msgid "value" msgstr "" -#: extras/models/search.py:57 +#: netbox/extras/models/search.py:57 msgid "cached value" msgstr "" -#: extras/models/search.py:58 +#: netbox/extras/models/search.py:58 msgid "cached values" msgstr "" -#: extras/models/tags.py:42 +#: netbox/extras/models/tags.py:42 msgid "The object type(s) to which this tag can be applied." msgstr "" -#: extras/models/tags.py:58 +#: netbox/extras/models/tags.py:58 msgid "tag" msgstr "" -#: extras/models/tags.py:59 +#: netbox/extras/models/tags.py:59 msgid "tags" msgstr "" -#: extras/models/tags.py:88 +#: netbox/extras/models/tags.py:88 msgid "tagged item" msgstr "" -#: extras/models/tags.py:89 +#: netbox/extras/models/tags.py:89 msgid "tagged items" msgstr "" -#: extras/scripts.py:496 +#: netbox/extras/scripts.py:496 msgid "Script Data" msgstr "" -#: extras/scripts.py:503 +#: netbox/extras/scripts.py:503 msgid "Script Execution Parameters" msgstr "" -#: extras/tables/columns.py:12 templates/htmx/notifications.html:29 +#: netbox/extras/tables/columns.py:12 +#: netbox/templates/htmx/notifications.html:29 msgid "Dismiss" msgstr "" -#: extras/tables/tables.py:80 extras/tables/tables.py:189 -#: extras/tables/tables.py:218 extras/tables/tables.py:320 -#: extras/tables/tables.py:523 extras/tables/tables.py:561 -#: extras/ui/panels.py:117 extras/ui/panels.py:173 -#: templates/users/panels/object_types.html:3 users/tables.py:110 +#: netbox/extras/tables/tables.py:80 netbox/extras/tables/tables.py:189 +#: netbox/extras/tables/tables.py:218 netbox/extras/tables/tables.py:320 +#: netbox/extras/tables/tables.py:523 netbox/extras/tables/tables.py:561 +#: netbox/extras/ui/panels.py:117 netbox/extras/ui/panels.py:173 +#: netbox/templates/users/panels/object_types.html:3 netbox/users/tables.py:110 msgid "Object Types" msgstr "" -#: extras/tables/tables.py:87 +#: netbox/extras/tables/tables.py:87 msgid "Validate Uniqueness" msgstr "" -#: extras/tables/tables.py:91 +#: netbox/extras/tables/tables.py:91 msgid "Visible" msgstr "" -#: extras/tables/tables.py:94 +#: netbox/extras/tables/tables.py:94 msgid "Editable" msgstr "" -#: extras/tables/tables.py:100 +#: netbox/extras/tables/tables.py:100 msgid "Related Object Type" msgstr "" -#: extras/tables/tables.py:104 +#: netbox/extras/tables/tables.py:104 msgid "Choice Set" msgstr "" -#: extras/tables/tables.py:112 +#: netbox/extras/tables/tables.py:112 msgid "Is Cloneable" msgstr "" -#: extras/tables/tables.py:116 +#: netbox/extras/tables/tables.py:116 msgid "Minimum Value" msgstr "" -#: extras/tables/tables.py:119 +#: netbox/extras/tables/tables.py:119 msgid "Maximum Value" msgstr "" -#: extras/tables/tables.py:122 +#: netbox/extras/tables/tables.py:122 msgid "Validation Regex" msgstr "" -#: extras/tables/tables.py:125 +#: netbox/extras/tables/tables.py:125 msgid "Validation Schema" msgstr "" -#: extras/tables/tables.py:130 extras/tables/tables.py:171 -#: extras/tables/tables.py:200 extras/tables/tables.py:247 -#: extras/tables/tables.py:331 extras/tables/tables.py:492 -#: extras/tables/tables.py:535 extras/tables/tables.py:565 -#: extras/tables/tables.py:656 extras/tables/tables.py:712 -#: netbox/forms/mixins.py:162 netbox/forms/mixins.py:187 -#: netbox/tables/tables.py:311 netbox/tables/tables.py:326 -#: netbox/tables/tables.py:341 templates/generic/object.html:61 -#: users/forms/model_forms.py:547 +#: netbox/extras/tables/tables.py:130 netbox/extras/tables/tables.py:171 +#: netbox/extras/tables/tables.py:200 netbox/extras/tables/tables.py:247 +#: netbox/extras/tables/tables.py:331 netbox/extras/tables/tables.py:492 +#: netbox/extras/tables/tables.py:535 netbox/extras/tables/tables.py:565 +#: netbox/extras/tables/tables.py:656 netbox/extras/tables/tables.py:712 +#: netbox/netbox/forms/mixins.py:162 netbox/netbox/forms/mixins.py:187 +#: netbox/netbox/tables/tables.py:311 netbox/netbox/tables/tables.py:326 +#: netbox/netbox/tables/tables.py:341 netbox/templates/generic/object.html:61 +#: netbox/users/forms/model_forms.py:538 msgid "Owner" msgstr "" -#: extras/tables/tables.py:163 +#: netbox/extras/tables/tables.py:163 msgid "Count" msgstr "" -#: extras/tables/tables.py:166 +#: netbox/extras/tables/tables.py:166 msgid "Order Alphabetically" msgstr "" -#: extras/tables/tables.py:195 +#: netbox/extras/tables/tables.py:195 msgid "New Window" msgstr "" -#: extras/tables/tables.py:221 extras/tables/tables.py:694 +#: netbox/extras/tables/tables.py:221 netbox/extras/tables/tables.py:694 msgid "MIME Type" msgstr "" -#: extras/tables/tables.py:224 extras/tables/tables.py:697 +#: netbox/extras/tables/tables.py:224 netbox/extras/tables/tables.py:697 msgid "File Name" msgstr "" -#: extras/tables/tables.py:227 extras/tables/tables.py:700 +#: netbox/extras/tables/tables.py:227 netbox/extras/tables/tables.py:700 msgid "File Extension" msgstr "" -#: extras/tables/tables.py:230 extras/tables/tables.py:703 +#: netbox/extras/tables/tables.py:230 netbox/extras/tables/tables.py:703 msgid "As Attachment" msgstr "" -#: extras/tables/tables.py:243 extras/tables/tables.py:615 -#: extras/tables/tables.py:652 extras/tables/tables.py:687 +#: netbox/extras/tables/tables.py:243 netbox/extras/tables/tables.py:615 +#: netbox/extras/tables/tables.py:652 netbox/extras/tables/tables.py:687 msgid "Synced" msgstr "" -#: extras/tables/tables.py:268 extras/ui/panels.py:497 +#: netbox/extras/tables/tables.py:268 netbox/extras/ui/panels.py:497 msgid "Image" msgstr "" -#: extras/tables/tables.py:277 -#: templates/extras/panels/imageattachment_file.html:7 +#: netbox/extras/tables/tables.py:277 +#: netbox/templates/extras/panels/imageattachment_file.html:7 msgid "Filename" msgstr "" -#: extras/tables/tables.py:296 -#: templates/extras/panels/imageattachment_file.html:18 -#: virtualization/forms/bulk_edit.py:359 virtualization/forms/filtersets.py:332 -#: virtualization/tables/virtualmachines.py:210 +#: netbox/extras/tables/tables.py:296 +#: netbox/templates/extras/panels/imageattachment_file.html:18 +#: netbox/virtualization/forms/bulk_edit.py:363 +#: netbox/virtualization/forms/filtersets.py:332 +#: netbox/virtualization/tables/virtualmachines.py:210 msgid "Size" msgstr "" -#: extras/tables/tables.py:357 +#: netbox/extras/tables/tables.py:357 msgid "Table Name" msgstr "" -#: extras/tables/tables.py:445 +#: netbox/extras/tables/tables.py:445 msgid "Read" msgstr "" -#: extras/tables/tables.py:488 +#: netbox/extras/tables/tables.py:488 msgid "SSL Verification" msgstr "" -#: extras/tables/tables.py:529 extras/ui/panels.py:365 +#: netbox/extras/tables/tables.py:529 netbox/extras/ui/panels.py:365 msgid "Event Types" msgstr "" -#: extras/tables/tables.py:690 +#: netbox/extras/tables/tables.py:690 msgid "Auto Sync Enabled" msgstr "" -#: extras/tables/tables.py:720 netbox/navigation/menu.py:86 -#: templates/dcim/devicerole.html:8 +#: netbox/extras/tables/tables.py:720 netbox/netbox/navigation/menu.py:86 +#: netbox/templates/dcim/devicerole.html:8 msgid "Device Roles" msgstr "" -#: extras/tables/tables.py:773 +#: netbox/extras/tables/tables.py:773 msgid "Comments (Short)" msgstr "" -#: extras/tables/tables.py:792 extras/tables/tables.py:844 +#: netbox/extras/tables/tables.py:792 netbox/extras/tables/tables.py:844 msgid "Line" msgstr "" -#: extras/tables/tables.py:847 +#: netbox/extras/tables/tables.py:847 msgid "Method" msgstr "" -#: extras/templatetags/dashboard.py:15 +#: netbox/extras/templatetags/dashboard.py:15 msgid "An error was encountered when attempting to render this widget:" msgstr "" -#: extras/templatetags/dashboard.py:16 +#: netbox/extras/templatetags/dashboard.py:16 msgid "Please try reconfiguring the widget, or remove it from your dashboard." msgstr "" -#: extras/ui/panels.py:58 netbox/navigation/menu.py:359 -#: templates/circuits/panels/circuit_circuit_termination.html:41 -#: templates/dcim/device_edit.html:113 templates/dcim/htmx/cable_edit.html:93 -#: templates/dcim/virtualchassis_edit.html:48 -#: templates/generic/bulk_edit.html:89 templates/htmx/form.html:19 -#: templates/inc/filter_list.html:30 templates/inc/panels/custom_fields.html:7 -#: templates/ipam/vlan_edit.html:79 +#: netbox/extras/ui/panels.py:58 netbox/netbox/navigation/menu.py:359 +#: netbox/templates/circuits/panels/circuit_circuit_termination.html:41 +#: netbox/templates/dcim/device_edit.html:113 +#: netbox/templates/dcim/htmx/cable_edit.html:93 +#: netbox/templates/dcim/virtualchassis_edit.html:48 +#: netbox/templates/generic/bulk_edit.html:89 +#: netbox/templates/htmx/form.html:19 netbox/templates/inc/filter_list.html:30 +#: netbox/templates/inc/panels/custom_fields.html:7 +#: netbox/templates/ipam/vlan_edit.html:79 msgid "Custom Fields" msgstr "" -#: extras/ui/panels.py:83 templates/inc/panels/image_attachments.html:10 +#: netbox/extras/ui/panels.py:83 +#: netbox/templates/inc/panels/image_attachments.html:10 msgid "Attach an image" msgstr "" -#: extras/ui/panels.py:134 +#: netbox/extras/ui/panels.py:134 msgid "Cloneable" msgstr "" -#: extras/ui/panels.py:154 +#: netbox/extras/ui/panels.py:154 msgid "Display weight" msgstr "" -#: extras/ui/panels.py:160 +#: netbox/extras/ui/panels.py:160 msgid "Validation Rules" msgstr "" -#: extras/ui/panels.py:166 +#: netbox/extras/ui/panels.py:166 msgid "Regular expression" msgstr "" -#: extras/ui/panels.py:178 netbox/ui/panels.py:288 -#: templates/inc/panels/related_objects.html:5 +#: netbox/extras/ui/panels.py:178 netbox/netbox/ui/panels.py:288 +#: netbox/templates/inc/panels/related_objects.html:5 msgid "Related Objects" msgstr "" -#: extras/ui/panels.py:198 +#: netbox/extras/ui/panels.py:198 msgid "Used by" msgstr "" -#: extras/ui/panels.py:241 extras/ui/panels.py:467 -#: templates/dcim/trace/attachment.html:5 +#: netbox/extras/ui/panels.py:241 netbox/extras/ui/panels.py:467 +#: netbox/templates/dcim/trace/attachment.html:5 msgid "Attachment" msgstr "" -#: extras/ui/panels.py:261 extras/views.py:248 extras/views.py:319 +#: netbox/extras/ui/panels.py:261 netbox/extras/views.py:248 +#: netbox/extras/views.py:319 msgid "Assigned Models" msgstr "" -#: extras/ui/panels.py:269 +#: netbox/extras/ui/panels.py:269 msgid "Table Config" msgstr "" -#: extras/ui/panels.py:283 +#: netbox/extras/ui/panels.py:283 msgid "Columns Displayed" msgstr "" -#: extras/ui/panels.py:308 +#: netbox/extras/ui/panels.py:308 msgid "Notification Group" msgstr "" -#: extras/ui/panels.py:405 +#: netbox/extras/ui/panels.py:405 msgid "Allowed Object Types" msgstr "" -#: extras/ui/panels.py:410 +#: netbox/extras/ui/panels.py:410 msgid "Tagged Item Types" msgstr "" -#: extras/ui/panels.py:483 +#: netbox/extras/ui/panels.py:483 msgid "Image Attachment" msgstr "" -#: extras/ui/panels.py:485 +#: netbox/extras/ui/panels.py:485 msgid "Parent object" msgstr "" -#: extras/ui/panels.py:505 +#: netbox/extras/ui/panels.py:505 msgid "Journal Entry" msgstr "" -#: extras/validators.py:15 +#: netbox/extras/validators.py:15 #, python-format msgid "Ensure this value is equal to %(limit_value)s." msgstr "" -#: extras/validators.py:26 +#: netbox/extras/validators.py:26 #, python-format msgid "Ensure this value does not equal %(limit_value)s." msgstr "" -#: extras/validators.py:37 +#: netbox/extras/validators.py:37 msgid "This field must be empty." msgstr "" -#: extras/validators.py:52 +#: netbox/extras/validators.py:52 msgid "This field must not be empty." msgstr "" -#: extras/validators.py:94 +#: netbox/extras/validators.py:94 msgid "Validation rules must be passed as a dictionary" msgstr "" -#: extras/validators.py:119 +#: netbox/extras/validators.py:119 #, python-brace-format msgid "Custom validation failed for {attribute}: {exception}" msgstr "" -#: extras/validators.py:133 +#: netbox/extras/validators.py:133 #, python-brace-format msgid "Invalid attribute \"{name}\" for request" msgstr "" -#: extras/validators.py:150 +#: netbox/extras/validators.py:150 #, python-brace-format msgid "Invalid attribute \"{name}\" for {model}" msgstr "" -#: extras/views.py:251 +#: netbox/extras/views.py:251 msgid "Link Text" msgstr "" -#: extras/views.py:252 +#: netbox/extras/views.py:252 msgid "Link URL" msgstr "" -#: extras/views.py:320 extras/views.py:1202 +#: netbox/extras/views.py:320 netbox/extras/views.py:1202 msgid "Environment Parameters" msgstr "" -#: extras/views.py:323 extras/views.py:1205 +#: netbox/extras/views.py:323 netbox/extras/views.py:1205 msgid "Template" msgstr "" -#: extras/views.py:764 +#: netbox/extras/views.py:764 msgid "Additional Headers" msgstr "" -#: extras/views.py:765 +#: netbox/extras/views.py:765 msgid "Body Template" msgstr "" -#: extras/views.py:834 +#: netbox/extras/views.py:834 msgid "Conditions" msgstr "" -#: extras/views.py:908 +#: netbox/extras/views.py:908 msgid "Tagged Objects" msgstr "" -#: extras/views.py:1000 +#: netbox/extras/views.py:1000 msgid "JSON Schema" msgstr "" -#: extras/views.py:1493 +#: netbox/extras/views.py:1493 msgid "Your dashboard has been reset." msgstr "" -#: extras/views.py:1539 +#: netbox/extras/views.py:1539 msgid "Added widget: " msgstr "" -#: extras/views.py:1580 +#: netbox/extras/views.py:1580 msgid "Updated widget: " msgstr "" -#: extras/views.py:1616 +#: netbox/extras/views.py:1616 msgid "Deleted widget: " msgstr "" -#: extras/views.py:1618 +#: netbox/extras/views.py:1618 msgid "Error deleting widget: " msgstr "" -#: extras/views.py:1733 +#: netbox/extras/views.py:1733 msgid "Unable to run script: RQ worker process not running." msgstr "" -#: ipam/api/field_serializers.py:16 +#: netbox/ipam/api/field_serializers.py:16 msgid "Enter a valid IPv4 or IPv6 address with optional mask." msgstr "" -#: ipam/api/field_serializers.py:23 +#: netbox/ipam/api/field_serializers.py:23 #, python-brace-format msgid "Invalid IP address format: {data}" msgstr "" -#: ipam/api/field_serializers.py:36 +#: netbox/ipam/api/field_serializers.py:36 msgid "Enter a valid IPv4 or IPv6 prefix and mask in CIDR notation." msgstr "" -#: ipam/api/field_serializers.py:43 +#: netbox/ipam/api/field_serializers.py:43 #, python-brace-format msgid "Invalid IP prefix format: {data}" msgstr "" -#: ipam/api/views.py:384 +#: netbox/ipam/api/views.py:384 msgid "" "Insufficient space is available to accommodate the requested prefix size(s)" msgstr "" -#: ipam/choices.py:30 +#: netbox/ipam/choices.py:30 msgid "Container" msgstr "" -#: ipam/choices.py:72 +#: netbox/ipam/choices.py:72 msgid "DHCP" msgstr "" -#: ipam/choices.py:73 +#: netbox/ipam/choices.py:73 msgid "SLAAC" msgstr "" -#: ipam/choices.py:89 +#: netbox/ipam/choices.py:89 msgid "Loopback" msgstr "" -#: ipam/choices.py:91 +#: netbox/ipam/choices.py:91 msgid "Anycast" msgstr "" -#: ipam/choices.py:115 +#: netbox/ipam/choices.py:115 msgid "Standard" msgstr "" -#: ipam/choices.py:120 +#: netbox/ipam/choices.py:120 msgid "CheckPoint" msgstr "" -#: ipam/choices.py:123 +#: netbox/ipam/choices.py:123 msgid "Cisco" msgstr "" -#: ipam/choices.py:137 +#: netbox/ipam/choices.py:137 msgid "Plaintext" msgstr "" -#: ipam/choices.py:166 +#: netbox/ipam/choices.py:166 msgid "Service" msgstr "" -#: ipam/choices.py:167 +#: netbox/ipam/choices.py:167 msgid "Customer" msgstr "" -#: ipam/fields.py:40 +#: netbox/ipam/fields.py:40 #, python-brace-format msgid "Invalid IP address format: {address}" msgstr "" -#: ipam/filtersets.py:63 vpn/filtersets.py:345 +#: netbox/ipam/filtersets.py:63 netbox/vpn/filtersets.py:345 msgid "Import target" msgstr "" -#: ipam/filtersets.py:69 vpn/filtersets.py:351 +#: netbox/ipam/filtersets.py:69 netbox/vpn/filtersets.py:351 msgid "Import target (name)" msgstr "" -#: ipam/filtersets.py:74 vpn/filtersets.py:356 +#: netbox/ipam/filtersets.py:74 netbox/vpn/filtersets.py:356 msgid "Export target" msgstr "" -#: ipam/filtersets.py:80 vpn/filtersets.py:362 +#: netbox/ipam/filtersets.py:80 netbox/vpn/filtersets.py:362 msgid "Export target (name)" msgstr "" -#: ipam/filtersets.py:102 +#: netbox/ipam/filtersets.py:102 msgid "Importing VRF" msgstr "" -#: ipam/filtersets.py:108 +#: netbox/ipam/filtersets.py:108 msgid "Import VRF (RD)" msgstr "" -#: ipam/filtersets.py:113 +#: netbox/ipam/filtersets.py:113 msgid "Exporting VRF" msgstr "" -#: ipam/filtersets.py:119 +#: netbox/ipam/filtersets.py:119 msgid "Export VRF (RD)" msgstr "" -#: ipam/filtersets.py:124 +#: netbox/ipam/filtersets.py:124 msgid "Importing L2VPN" msgstr "" -#: ipam/filtersets.py:130 +#: netbox/ipam/filtersets.py:130 msgid "Importing L2VPN (identifier)" msgstr "" -#: ipam/filtersets.py:135 +#: netbox/ipam/filtersets.py:135 msgid "Exporting L2VPN" msgstr "" -#: ipam/filtersets.py:141 +#: netbox/ipam/filtersets.py:141 msgid "Exporting L2VPN (identifier)" msgstr "" -#: ipam/filtersets.py:173 ipam/filtersets.py:336 ipam/forms/model_forms.py:230 -#: ipam/forms/model_forms.py:262 ipam/tables/ip.py:162 -#: templates/ipam/inc/prefix_edit_header.html:7 +#: netbox/ipam/filtersets.py:173 netbox/ipam/filtersets.py:336 +#: netbox/ipam/forms/model_forms.py:230 netbox/ipam/forms/model_forms.py:262 +#: netbox/ipam/tables/ip.py:162 +#: netbox/templates/ipam/inc/prefix_edit_header.html:7 msgid "Prefix" msgstr "" -#: ipam/filtersets.py:178 ipam/filtersets.py:220 ipam/filtersets.py:248 +#: netbox/ipam/filtersets.py:178 netbox/ipam/filtersets.py:220 +#: netbox/ipam/filtersets.py:248 msgid "RIR (ID)" msgstr "" -#: ipam/filtersets.py:185 ipam/filtersets.py:227 ipam/filtersets.py:255 +#: netbox/ipam/filtersets.py:185 netbox/ipam/filtersets.py:227 +#: netbox/ipam/filtersets.py:255 msgid "RIR (slug)" msgstr "" -#: ipam/filtersets.py:340 +#: netbox/ipam/filtersets.py:340 msgid "Within prefix" msgstr "" -#: ipam/filtersets.py:344 +#: netbox/ipam/filtersets.py:344 msgid "Within and including prefix" msgstr "" -#: ipam/filtersets.py:348 +#: netbox/ipam/filtersets.py:348 msgid "Prefixes which contain this prefix or IP" msgstr "" -#: ipam/filtersets.py:359 ipam/filtersets.py:617 ipam/forms/bulk_edit.py:289 -#: ipam/forms/filtersets.py:225 ipam/forms/filtersets.py:377 +#: netbox/ipam/filtersets.py:359 netbox/ipam/filtersets.py:617 +#: netbox/ipam/forms/bulk_edit.py:289 netbox/ipam/forms/filtersets.py:225 +#: netbox/ipam/forms/filtersets.py:377 msgid "Mask length" msgstr "" -#: ipam/filtersets.py:397 +#: netbox/ipam/filtersets.py:397 msgid "VLAN Group (ID)" msgstr "" -#: ipam/filtersets.py:404 +#: netbox/ipam/filtersets.py:404 msgid "VLAN Group (slug)" msgstr "" -#: ipam/filtersets.py:409 vpn/filtersets.py:471 +#: netbox/ipam/filtersets.py:409 netbox/vpn/filtersets.py:471 msgid "VLAN (ID)" msgstr "" -#: ipam/filtersets.py:413 vpn/filtersets.py:466 +#: netbox/ipam/filtersets.py:413 netbox/vpn/filtersets.py:466 msgid "VLAN number (1-4094)" msgstr "" -#: ipam/filtersets.py:510 ipam/filtersets.py:514 ipam/filtersets.py:612 -#: ipam/forms/model_forms.py:528 tenancy/forms/bulk_edit.py:108 +#: netbox/ipam/filtersets.py:510 netbox/ipam/filtersets.py:514 +#: netbox/ipam/filtersets.py:612 netbox/ipam/forms/model_forms.py:528 +#: netbox/tenancy/forms/bulk_edit.py:108 msgid "Address" msgstr "" -#: ipam/filtersets.py:518 +#: netbox/ipam/filtersets.py:518 msgid "Ranges which contain this prefix or IP" msgstr "" -#: ipam/filtersets.py:551 ipam/filtersets.py:608 +#: netbox/ipam/filtersets.py:551 netbox/ipam/filtersets.py:608 msgid "Parent prefix" msgstr "" -#: ipam/filtersets.py:696 +#: netbox/ipam/filtersets.py:696 msgid "FHRP group (ID)" msgstr "" -#: ipam/filtersets.py:700 +#: netbox/ipam/filtersets.py:700 msgid "Is assigned to an interface" msgstr "" -#: ipam/filtersets.py:718 +#: netbox/ipam/filtersets.py:718 msgid "Application Service (ID)" msgstr "" -#: ipam/filtersets.py:724 +#: netbox/ipam/filtersets.py:724 msgid "NAT inside IP address (ID)" msgstr "" -#: ipam/filtersets.py:1087 +#: netbox/ipam/filtersets.py:1087 msgid "Q-in-Q SVLAN (ID)" msgstr "" -#: ipam/filtersets.py:1091 +#: netbox/ipam/filtersets.py:1091 msgid "Q-in-Q SVLAN number (1-4094)" msgstr "" -#: ipam/filtersets.py:1112 +#: netbox/ipam/filtersets.py:1112 msgid "Assigned VM interface" msgstr "" -#: ipam/filtersets.py:1189 +#: netbox/ipam/filtersets.py:1189 msgid "VLAN Translation Policy (name)" msgstr "" -#: ipam/filtersets.py:1258 +#: netbox/ipam/filtersets.py:1258 msgid "FHRP Group (name)" msgstr "" -#: ipam/filtersets.py:1263 +#: netbox/ipam/filtersets.py:1263 msgid "FHRP Group (ID)" msgstr "" -#: ipam/filtersets.py:1268 +#: netbox/ipam/filtersets.py:1268 msgid "IP address (ID)" msgstr "" -#: ipam/filtersets.py:1274 ipam/models/ip.py:846 +#: netbox/ipam/filtersets.py:1274 netbox/ipam/models/ip.py:846 msgid "IP address" msgstr "" -#: ipam/filtersets.py:1327 +#: netbox/ipam/filtersets.py:1327 msgid "Primary IPv4 (ID)" msgstr "" -#: ipam/filtersets.py:1334 +#: netbox/ipam/filtersets.py:1334 msgid "Primary IPv4 (address)" msgstr "" -#: ipam/filtersets.py:1340 +#: netbox/ipam/filtersets.py:1340 msgid "Primary IPv6 (ID)" msgstr "" -#: ipam/filtersets.py:1347 +#: netbox/ipam/filtersets.py:1347 msgid "Primary IPv6 (address)" msgstr "" -#: ipam/formfields.py:14 +#: netbox/ipam/formfields.py:14 msgid "Enter a valid IPv4 or IPv6 address (without a mask)." msgstr "" -#: ipam/formfields.py:32 +#: netbox/ipam/formfields.py:32 #, python-brace-format msgid "Invalid IPv4/IPv6 address format: {address}" msgstr "" -#: ipam/formfields.py:37 +#: netbox/ipam/formfields.py:37 msgid "This field requires an IP address without a mask." msgstr "" -#: ipam/formfields.py:39 ipam/formfields.py:61 +#: netbox/ipam/formfields.py:39 netbox/ipam/formfields.py:61 msgid "Please specify a valid IPv4 or IPv6 address." msgstr "" -#: ipam/formfields.py:44 +#: netbox/ipam/formfields.py:44 msgid "Enter a valid IPv4 or IPv6 address (with CIDR mask)." msgstr "" -#: ipam/formfields.py:56 +#: netbox/ipam/formfields.py:56 msgid "CIDR mask (e.g. /24) is required." msgstr "" -#: ipam/forms/bulk_create.py:16 templates/generic/bulk_add.html:26 +#: netbox/ipam/forms/bulk_create.py:16 +#: netbox/templates/generic/bulk_add.html:26 msgid "Pattern" msgstr "" -#: ipam/forms/bulk_edit.py:56 +#: netbox/ipam/forms/bulk_edit.py:56 msgid "Enforce unique space" msgstr "" -#: ipam/forms/bulk_edit.py:82 +#: netbox/ipam/forms/bulk_edit.py:82 msgid "Is private" msgstr "" -#: ipam/forms/bulk_edit.py:98 ipam/forms/bulk_edit.py:122 -#: ipam/forms/bulk_edit.py:146 ipam/forms/bulk_import.py:96 -#: ipam/forms/bulk_import.py:116 ipam/forms/bulk_import.py:136 -#: ipam/forms/filtersets.py:91 ipam/forms/filtersets.py:121 -#: ipam/forms/filtersets.py:137 ipam/forms/filtersets.py:161 -#: ipam/forms/model_forms.py:100 ipam/forms/model_forms.py:113 -#: ipam/forms/model_forms.py:135 ipam/forms/model_forms.py:153 -#: ipam/models/asns.py:32 ipam/models/asns.py:132 ipam/models/ip.py:72 -#: ipam/models/ip.py:88 ipam/tables/asn.py:20 ipam/tables/asn.py:55 -#: ipam/ui/panels.py:60 ipam/ui/panels.py:68 ipam/ui/panels.py:76 +#: netbox/ipam/forms/bulk_edit.py:98 netbox/ipam/forms/bulk_edit.py:122 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_import.py:96 +#: netbox/ipam/forms/bulk_import.py:116 netbox/ipam/forms/bulk_import.py:136 +#: netbox/ipam/forms/filtersets.py:91 netbox/ipam/forms/filtersets.py:121 +#: netbox/ipam/forms/filtersets.py:137 netbox/ipam/forms/filtersets.py:161 +#: netbox/ipam/forms/model_forms.py:100 netbox/ipam/forms/model_forms.py:113 +#: netbox/ipam/forms/model_forms.py:135 netbox/ipam/forms/model_forms.py:153 +#: netbox/ipam/models/asns.py:32 netbox/ipam/models/asns.py:132 +#: netbox/ipam/models/ip.py:72 netbox/ipam/models/ip.py:88 +#: netbox/ipam/tables/asn.py:20 netbox/ipam/tables/asn.py:55 +#: netbox/ipam/ui/panels.py:60 netbox/ipam/ui/panels.py:68 +#: netbox/ipam/ui/panels.py:76 msgid "RIR" msgstr "" -#: ipam/forms/bulk_edit.py:154 +#: netbox/ipam/forms/bulk_edit.py:154 msgid "Date added" msgstr "" -#: ipam/forms/bulk_edit.py:182 ipam/forms/filtersets.py:286 -#: ipam/forms/model_forms.py:641 ipam/forms/model_forms.py:690 -#: ipam/tables/ip.py:205 templates/ipam/vlan_edit.html:49 +#: netbox/ipam/forms/bulk_edit.py:182 netbox/ipam/forms/filtersets.py:286 +#: netbox/ipam/forms/model_forms.py:641 netbox/ipam/forms/model_forms.py:690 +#: netbox/ipam/tables/ip.py:205 netbox/templates/ipam/vlan_edit.html:49 msgid "VLAN Group" msgstr "" -#: ipam/forms/bulk_edit.py:187 ipam/forms/bulk_import.py:198 -#: ipam/forms/filtersets.py:291 ipam/forms/model_forms.py:219 -#: ipam/models/vlans.py:292 ipam/tables/ip.py:210 ipam/ui/panels.py:148 -#: templates/ipam/vlan/base.html:6 templates/ipam/vlan_edit.html:14 -#: vpn/forms/bulk_import.py:309 vpn/forms/filtersets.py:306 -#: vpn/forms/model_forms.py:431 vpn/forms/model_forms.py:450 -#: wireless/forms/bulk_edit.py:52 wireless/forms/bulk_import.py:49 -#: wireless/forms/model_forms.py:50 wireless/models.py:106 -#: wireless/ui/panels.py:16 +#: netbox/ipam/forms/bulk_edit.py:187 netbox/ipam/forms/bulk_import.py:198 +#: netbox/ipam/forms/filtersets.py:291 netbox/ipam/forms/model_forms.py:219 +#: netbox/ipam/models/vlans.py:292 netbox/ipam/tables/ip.py:210 +#: netbox/ipam/ui/panels.py:148 netbox/templates/ipam/vlan/base.html:6 +#: netbox/templates/ipam/vlan_edit.html:14 netbox/vpn/forms/bulk_import.py:309 +#: netbox/vpn/forms/filtersets.py:306 netbox/vpn/forms/model_forms.py:431 +#: netbox/vpn/forms/model_forms.py:450 netbox/wireless/forms/bulk_edit.py:52 +#: netbox/wireless/forms/bulk_import.py:49 +#: netbox/wireless/forms/model_forms.py:50 netbox/wireless/models.py:106 +#: netbox/wireless/ui/panels.py:16 msgid "VLAN" msgstr "" -#: ipam/forms/bulk_edit.py:198 +#: netbox/ipam/forms/bulk_edit.py:198 msgid "Prefix length" msgstr "" -#: ipam/forms/bulk_edit.py:221 ipam/forms/filtersets.py:271 -#: ipam/ui/panels.py:152 +#: netbox/ipam/forms/bulk_edit.py:221 netbox/ipam/forms/filtersets.py:271 +#: netbox/ipam/ui/panels.py:152 msgid "Is a pool" msgstr "" -#: ipam/forms/bulk_edit.py:226 ipam/forms/bulk_edit.py:270 -#: ipam/forms/filtersets.py:278 ipam/forms/filtersets.py:337 -#: ipam/models/ip.py:271 +#: netbox/ipam/forms/bulk_edit.py:226 netbox/ipam/forms/bulk_edit.py:270 +#: netbox/ipam/forms/filtersets.py:278 netbox/ipam/forms/filtersets.py:337 +#: netbox/ipam/models/ip.py:271 msgid "Treat as fully utilized" msgstr "" -#: ipam/forms/bulk_edit.py:234 ipam/forms/filtersets.py:198 -#: ipam/forms/model_forms.py:233 ipam/forms/model_forms.py:265 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/filtersets.py:198 +#: netbox/ipam/forms/model_forms.py:233 netbox/ipam/forms/model_forms.py:265 msgid "VLAN Assignment" msgstr "" -#: ipam/forms/bulk_edit.py:265 ipam/forms/filtersets.py:330 +#: netbox/ipam/forms/bulk_edit.py:265 netbox/ipam/forms/filtersets.py:330 msgid "Treat as populated" msgstr "" -#: ipam/forms/bulk_edit.py:312 ipam/models/ip.py:829 +#: netbox/ipam/forms/bulk_edit.py:312 netbox/ipam/models/ip.py:829 msgid "DNS name" msgstr "" -#: ipam/forms/bulk_edit.py:327 ipam/forms/bulk_edit.py:501 -#: ipam/forms/bulk_import.py:470 ipam/forms/bulk_import.py:591 -#: ipam/forms/bulk_import.py:619 ipam/forms/filtersets.py:437 -#: ipam/forms/filtersets.py:641 templates/ipam/inc/panels/fhrp_groups.html:24 -#: templates/ipam/panels/fhrp_groups.html:10 +#: netbox/ipam/forms/bulk_edit.py:327 netbox/ipam/forms/bulk_edit.py:501 +#: netbox/ipam/forms/bulk_import.py:470 netbox/ipam/forms/bulk_import.py:591 +#: netbox/ipam/forms/bulk_import.py:619 netbox/ipam/forms/filtersets.py:437 +#: netbox/ipam/forms/filtersets.py:641 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 +#: netbox/templates/ipam/panels/fhrp_groups.html:10 msgid "Protocol" msgstr "" -#: ipam/forms/bulk_edit.py:334 ipam/forms/filtersets.py:444 -#: ipam/tables/fhrp.py:22 ipam/ui/panels.py:182 +#: netbox/ipam/forms/bulk_edit.py:334 netbox/ipam/forms/filtersets.py:444 +#: netbox/ipam/tables/fhrp.py:22 netbox/ipam/ui/panels.py:182 msgid "Group ID" msgstr "" -#: ipam/forms/bulk_edit.py:339 ipam/forms/filtersets.py:449 -#: wireless/forms/bulk_edit.py:65 wireless/forms/bulk_edit.py:107 -#: wireless/forms/bulk_import.py:63 wireless/forms/bulk_import.py:66 -#: wireless/forms/bulk_import.py:143 wireless/forms/bulk_import.py:146 -#: wireless/forms/filtersets.py:63 wireless/forms/filtersets.py:123 +#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/filtersets.py:449 +#: netbox/wireless/forms/bulk_edit.py:65 netbox/wireless/forms/bulk_edit.py:107 +#: netbox/wireless/forms/bulk_import.py:63 +#: netbox/wireless/forms/bulk_import.py:66 +#: netbox/wireless/forms/bulk_import.py:143 +#: netbox/wireless/forms/bulk_import.py:146 +#: netbox/wireless/forms/filtersets.py:63 +#: netbox/wireless/forms/filtersets.py:123 msgid "Authentication type" msgstr "" -#: ipam/forms/bulk_edit.py:344 ipam/forms/filtersets.py:453 +#: netbox/ipam/forms/bulk_edit.py:344 netbox/ipam/forms/filtersets.py:453 msgid "Authentication key" msgstr "" -#: ipam/forms/bulk_edit.py:355 ipam/forms/filtersets.py:429 -#: ipam/forms/model_forms.py:538 ipam/ui/panels.py:189 -#: netbox/navigation/menu.py:421 wireless/forms/bulk_edit.py:83 -#: wireless/forms/bulk_edit.py:135 wireless/forms/filtersets.py:43 -#: wireless/forms/filtersets.py:109 wireless/forms/model_forms.py:57 -#: wireless/forms/model_forms.py:172 wireless/ui/panels.py:21 +#: netbox/ipam/forms/bulk_edit.py:355 netbox/ipam/forms/filtersets.py:429 +#: netbox/ipam/forms/model_forms.py:538 netbox/ipam/ui/panels.py:189 +#: netbox/netbox/navigation/menu.py:421 netbox/wireless/forms/bulk_edit.py:83 +#: netbox/wireless/forms/bulk_edit.py:135 +#: netbox/wireless/forms/filtersets.py:43 +#: netbox/wireless/forms/filtersets.py:109 +#: netbox/wireless/forms/model_forms.py:57 +#: netbox/wireless/forms/model_forms.py:172 netbox/wireless/ui/panels.py:21 msgid "Authentication" msgstr "" -#: ipam/forms/bulk_edit.py:375 ipam/models/vlans.py:60 +#: netbox/ipam/forms/bulk_edit.py:375 netbox/ipam/models/vlans.py:60 msgid "VLAN ID ranges" msgstr "" -#: ipam/forms/bulk_edit.py:451 ipam/forms/bulk_import.py:548 -#: ipam/forms/filtersets.py:615 ipam/models/vlans.py:249 -#: ipam/tables/vlans.py:110 +#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_import.py:548 +#: netbox/ipam/forms/filtersets.py:615 netbox/ipam/models/vlans.py:249 +#: netbox/ipam/tables/vlans.py:110 msgid "Q-in-Q role" msgstr "" -#: ipam/forms/bulk_edit.py:467 +#: netbox/ipam/forms/bulk_edit.py:467 msgid "Q-in-Q" msgstr "" -#: ipam/forms/bulk_edit.py:468 +#: netbox/ipam/forms/bulk_edit.py:468 msgid "Site & Group" msgstr "" -#: ipam/forms/bulk_edit.py:485 ipam/forms/bulk_import.py:578 -#: ipam/forms/model_forms.py:745 ipam/tables/vlans.py:234 -#: vpn/forms/model_forms.py:319 vpn/forms/model_forms.py:356 +#: netbox/ipam/forms/bulk_edit.py:485 netbox/ipam/forms/bulk_import.py:578 +#: netbox/ipam/forms/model_forms.py:745 netbox/ipam/tables/vlans.py:234 +#: netbox/vpn/forms/model_forms.py:319 netbox/vpn/forms/model_forms.py:356 msgid "Policy" msgstr "" -#: ipam/forms/bulk_edit.py:506 ipam/forms/model_forms.py:763 -#: ipam/forms/model_forms.py:795 ipam/tables/services.py:20 -#: ipam/tables/services.py:47 ipam/ui/panels.py:240 ipam/ui/panels.py:248 +#: netbox/ipam/forms/bulk_edit.py:506 netbox/ipam/forms/model_forms.py:763 +#: netbox/ipam/forms/model_forms.py:795 netbox/ipam/tables/services.py:20 +#: netbox/ipam/tables/services.py:47 netbox/ipam/ui/panels.py:240 +#: netbox/ipam/ui/panels.py:248 msgid "Ports" msgstr "" -#: ipam/forms/bulk_import.py:55 ipam/views.py:71 +#: netbox/ipam/forms/bulk_import.py:55 netbox/ipam/views.py:71 msgid "Import route targets" msgstr "" -#: ipam/forms/bulk_import.py:61 ipam/views.py:74 +#: netbox/ipam/forms/bulk_import.py:61 netbox/ipam/views.py:74 msgid "Export route targets" msgstr "" -#: ipam/forms/bulk_import.py:99 ipam/forms/bulk_import.py:119 -#: ipam/forms/bulk_import.py:139 +#: netbox/ipam/forms/bulk_import.py:99 netbox/ipam/forms/bulk_import.py:119 +#: netbox/ipam/forms/bulk_import.py:139 msgid "Assigned RIR" msgstr "" -#: ipam/forms/bulk_import.py:188 +#: netbox/ipam/forms/bulk_import.py:188 msgid "VLAN's group (if any)" msgstr "" -#: ipam/forms/bulk_import.py:191 +#: netbox/ipam/forms/bulk_import.py:191 msgid "VLAN Site" msgstr "" -#: ipam/forms/bulk_import.py:195 +#: netbox/ipam/forms/bulk_import.py:195 msgid "VLAN's site (if any)" msgstr "" -#: ipam/forms/bulk_import.py:224 ipam/forms/bulk_import.py:509 -#: virtualization/forms/bulk_import.py:83 wireless/forms/bulk_import.py:82 +#: netbox/ipam/forms/bulk_import.py:224 netbox/ipam/forms/bulk_import.py:509 +#: netbox/virtualization/forms/bulk_import.py:83 +#: netbox/wireless/forms/bulk_import.py:82 msgid "Scope ID" msgstr "" -#: ipam/forms/bulk_import.py:337 ipam/forms/filtersets.py:674 -#: ipam/forms/model_forms.py:322 ipam/forms/model_forms.py:351 -#: ipam/forms/model_forms.py:537 +#: netbox/ipam/forms/bulk_import.py:337 netbox/ipam/forms/filtersets.py:674 +#: netbox/ipam/forms/model_forms.py:322 netbox/ipam/forms/model_forms.py:351 +#: netbox/ipam/forms/model_forms.py:537 msgid "FHRP Group" msgstr "" -#: ipam/forms/bulk_import.py:341 +#: netbox/ipam/forms/bulk_import.py:341 msgid "Assigned FHRP Group name" msgstr "" -#: ipam/forms/bulk_import.py:345 +#: netbox/ipam/forms/bulk_import.py:345 msgid "Make this the primary IP for the assigned device" msgstr "" -#: ipam/forms/bulk_import.py:349 +#: netbox/ipam/forms/bulk_import.py:349 msgid "Is out-of-band" msgstr "" -#: ipam/forms/bulk_import.py:350 +#: netbox/ipam/forms/bulk_import.py:350 msgid "Designate this as the out-of-band IP address for the assigned device" msgstr "" -#: ipam/forms/bulk_import.py:402 +#: netbox/ipam/forms/bulk_import.py:402 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" -#: ipam/forms/bulk_import.py:406 +#: netbox/ipam/forms/bulk_import.py:406 msgid "No device specified; cannot set as out-of-band IP" msgstr "" -#: ipam/forms/bulk_import.py:410 +#: netbox/ipam/forms/bulk_import.py:410 msgid "Cannot set out-of-band IP for virtual machines" msgstr "" -#: ipam/forms/bulk_import.py:414 +#: netbox/ipam/forms/bulk_import.py:414 msgid "No interface specified; cannot set as primary IP" msgstr "" -#: ipam/forms/bulk_import.py:418 +#: netbox/ipam/forms/bulk_import.py:418 msgid "No interface specified; cannot set as out-of-band IP" msgstr "" -#: ipam/forms/bulk_import.py:474 +#: netbox/ipam/forms/bulk_import.py:474 msgid "Auth type" msgstr "" -#: ipam/forms/bulk_import.py:526 +#: netbox/ipam/forms/bulk_import.py:526 msgid "Assigned VLAN group" msgstr "" -#: ipam/forms/bulk_import.py:558 +#: netbox/ipam/forms/bulk_import.py:558 msgid "Service VLAN (for Q-in-Q/802.1ad customer VLANs)" msgstr "" -#: ipam/forms/bulk_import.py:581 ipam/models/vlans.py:371 +#: netbox/ipam/forms/bulk_import.py:581 netbox/ipam/models/vlans.py:371 msgid "VLAN translation policy" msgstr "" -#: ipam/forms/bulk_import.py:593 ipam/forms/bulk_import.py:621 +#: netbox/ipam/forms/bulk_import.py:593 netbox/ipam/forms/bulk_import.py:621 msgid "IP protocol" msgstr "" -#: ipam/forms/bulk_import.py:605 +#: netbox/ipam/forms/bulk_import.py:605 msgid "Parent type (app & model)" msgstr "" -#: ipam/forms/bulk_import.py:612 +#: netbox/ipam/forms/bulk_import.py:612 msgid "Parent object name" msgstr "" -#: ipam/forms/bulk_import.py:616 +#: netbox/ipam/forms/bulk_import.py:616 msgid "Parent object ID" msgstr "" -#: ipam/forms/bulk_import.py:668 +#: netbox/ipam/forms/bulk_import.py:668 msgid "" "One of parent or parent_object_id must be included with parent_object_type" msgstr "" -#: ipam/forms/bulk_import.py:681 +#: netbox/ipam/forms/bulk_import.py:681 #, python-brace-format msgid "{ip} is not assigned to this parent." msgstr "" -#: ipam/forms/filtersets.py:49 ipam/forms/model_forms.py:70 -#: netbox/navigation/menu.py:206 vpn/forms/model_forms.py:408 +#: netbox/ipam/forms/filtersets.py:49 netbox/ipam/forms/model_forms.py:70 +#: netbox/netbox/navigation/menu.py:206 netbox/vpn/forms/model_forms.py:408 msgid "Route Targets" msgstr "" -#: ipam/forms/filtersets.py:56 ipam/forms/model_forms.py:58 -#: vpn/forms/filtersets.py:246 vpn/forms/model_forms.py:396 +#: netbox/ipam/forms/filtersets.py:56 netbox/ipam/forms/model_forms.py:58 +#: netbox/vpn/forms/filtersets.py:246 netbox/vpn/forms/model_forms.py:396 msgid "Import targets" msgstr "" -#: ipam/forms/filtersets.py:61 ipam/forms/model_forms.py:63 -#: vpn/forms/filtersets.py:251 vpn/forms/model_forms.py:401 +#: netbox/ipam/forms/filtersets.py:61 netbox/ipam/forms/model_forms.py:63 +#: netbox/vpn/forms/filtersets.py:251 netbox/vpn/forms/model_forms.py:401 msgid "Export targets" msgstr "" -#: ipam/forms/filtersets.py:77 +#: netbox/ipam/forms/filtersets.py:77 msgid "Imported by VRF" msgstr "" -#: ipam/forms/filtersets.py:82 +#: netbox/ipam/forms/filtersets.py:82 msgid "Exported by VRF" msgstr "" -#: ipam/forms/filtersets.py:96 ipam/tables/ip.py:37 ipam/ui/panels.py:55 +#: netbox/ipam/forms/filtersets.py:96 netbox/ipam/tables/ip.py:37 +#: netbox/ipam/ui/panels.py:55 msgid "Private" msgstr "" -#: ipam/forms/filtersets.py:116 ipam/forms/filtersets.py:220 -#: ipam/forms/filtersets.py:309 ipam/forms/filtersets.py:372 +#: netbox/ipam/forms/filtersets.py:116 netbox/ipam/forms/filtersets.py:220 +#: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/filtersets.py:372 msgid "Address family" msgstr "" -#: ipam/forms/filtersets.py:130 ipam/ui/panels.py:61 +#: netbox/ipam/forms/filtersets.py:130 netbox/ipam/ui/panels.py:61 msgid "Range" msgstr "" -#: ipam/forms/filtersets.py:140 +#: netbox/ipam/forms/filtersets.py:140 msgid "Start" msgstr "" -#: ipam/forms/filtersets.py:144 +#: netbox/ipam/forms/filtersets.py:144 msgid "End" msgstr "" -#: ipam/forms/filtersets.py:215 +#: netbox/ipam/forms/filtersets.py:215 msgid "Search within" msgstr "" -#: ipam/forms/filtersets.py:236 ipam/forms/filtersets.py:388 +#: netbox/ipam/forms/filtersets.py:236 netbox/ipam/forms/filtersets.py:388 msgid "Present in VRF" msgstr "" -#: ipam/forms/filtersets.py:354 +#: netbox/ipam/forms/filtersets.py:354 msgid "Device/VM" msgstr "" -#: ipam/forms/filtersets.py:367 +#: netbox/ipam/forms/filtersets.py:367 msgid "Parent Prefix" msgstr "" -#: ipam/forms/filtersets.py:419 ipam/ui/panels.py:116 +#: netbox/ipam/forms/filtersets.py:419 netbox/ipam/ui/panels.py:116 msgid "DNS Name" msgstr "" -#: ipam/forms/filtersets.py:511 +#: netbox/ipam/forms/filtersets.py:511 msgid "Contains VLAN ID" msgstr "" -#: ipam/forms/filtersets.py:516 ipam/tables/vlans.py:55 +#: netbox/ipam/forms/filtersets.py:516 netbox/ipam/tables/vlans.py:55 msgid "Total VLAN IDs" msgstr "" -#: ipam/forms/filtersets.py:551 ipam/models/vlans.py:391 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/models/vlans.py:391 msgid "Local VLAN ID" msgstr "" -#: ipam/forms/filtersets.py:556 ipam/models/vlans.py:399 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/models/vlans.py:399 msgid "Remote VLAN ID" msgstr "" -#: ipam/forms/filtersets.py:566 +#: netbox/ipam/forms/filtersets.py:566 msgid "Q-in-Q/802.1ad" msgstr "" -#: ipam/forms/filtersets.py:612 ipam/models/vlans.py:208 ipam/ui/panels.py:199 +#: netbox/ipam/forms/filtersets.py:612 netbox/ipam/models/vlans.py:208 +#: netbox/ipam/ui/panels.py:199 msgid "VLAN ID" msgstr "" -#: ipam/forms/model_forms.py:87 +#: netbox/ipam/forms/model_forms.py:87 msgid "Route Target" msgstr "" -#: ipam/forms/model_forms.py:118 ipam/tables/ip.py:65 ipam/ui/panels.py:145 +#: netbox/ipam/forms/model_forms.py:118 netbox/ipam/tables/ip.py:65 +#: netbox/ipam/ui/panels.py:145 msgid "Aggregate" msgstr "" -#: ipam/forms/model_forms.py:139 +#: netbox/ipam/forms/model_forms.py:139 msgid "ASN Range" msgstr "" -#: ipam/forms/model_forms.py:286 +#: netbox/ipam/forms/model_forms.py:286 msgid "IP Range" msgstr "" -#: ipam/forms/model_forms.py:337 +#: netbox/ipam/forms/model_forms.py:337 msgid "Make this the primary IP for the device/VM" msgstr "" -#: ipam/forms/model_forms.py:341 +#: netbox/ipam/forms/model_forms.py:341 msgid "Make this the out-of-band IP for the device" msgstr "" -#: ipam/forms/model_forms.py:355 +#: netbox/ipam/forms/model_forms.py:355 msgid "NAT IP (Inside)" msgstr "" -#: ipam/forms/model_forms.py:417 +#: netbox/ipam/forms/model_forms.py:417 msgid "An IP address can only be assigned to a single object." msgstr "" -#: ipam/forms/model_forms.py:424 +#: netbox/ipam/forms/model_forms.py:424 msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -#: ipam/forms/model_forms.py:428 +#: netbox/ipam/forms/model_forms.py:428 msgid "Cannot reassign out-of-Band IP address for the parent device" msgstr "" -#: ipam/forms/model_forms.py:438 +#: netbox/ipam/forms/model_forms.py:438 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" -#: ipam/forms/model_forms.py:446 +#: netbox/ipam/forms/model_forms.py:446 msgid "" "Only IP addresses assigned to a device interface can be designated as the " "out-of-band IP for a device." msgstr "" -#: ipam/forms/model_forms.py:539 +#: netbox/ipam/forms/model_forms.py:539 msgid "Virtual IP Address" msgstr "" -#: ipam/forms/model_forms.py:616 +#: netbox/ipam/forms/model_forms.py:616 msgid "Assignment already exists" msgstr "" -#: ipam/forms/model_forms.py:624 ipam/ui/panels.py:162 +#: netbox/ipam/forms/model_forms.py:624 netbox/ipam/ui/panels.py:162 msgid "VLAN IDs" msgstr "" -#: ipam/forms/model_forms.py:642 +#: netbox/ipam/forms/model_forms.py:642 msgid "Child VLANs" msgstr "" -#: ipam/forms/model_forms.py:701 +#: netbox/ipam/forms/model_forms.py:701 msgid "" "The direct assignment of VLANs to a site is deprecated and will be removed " "in a future release. Users are encouraged to utilize VLAN groups for this " "purpose." msgstr "" -#: ipam/forms/model_forms.py:751 +#: netbox/ipam/forms/model_forms.py:751 msgid "VLAN Translation Rule" msgstr "" -#: ipam/forms/model_forms.py:768 ipam/forms/model_forms.py:800 +#: netbox/ipam/forms/model_forms.py:768 netbox/ipam/forms/model_forms.py:800 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." msgstr "" -#: ipam/forms/model_forms.py:772 +#: netbox/ipam/forms/model_forms.py:772 msgid "Application Service Template" msgstr "" -#: ipam/forms/model_forms.py:785 +#: netbox/ipam/forms/model_forms.py:785 msgid "Parent type" msgstr "" -#: ipam/forms/model_forms.py:811 +#: netbox/ipam/forms/model_forms.py:811 msgid "Port(s)" msgstr "" -#: ipam/forms/model_forms.py:812 ipam/forms/model_forms.py:878 +#: netbox/ipam/forms/model_forms.py:812 netbox/ipam/forms/model_forms.py:878 msgid "Application Service" msgstr "" -#: ipam/forms/model_forms.py:866 +#: netbox/ipam/forms/model_forms.py:866 msgid "Application Service template" msgstr "" -#: ipam/forms/model_forms.py:875 +#: netbox/ipam/forms/model_forms.py:875 msgid "From Template" msgstr "" -#: ipam/forms/model_forms.py:876 +#: netbox/ipam/forms/model_forms.py:876 msgid "Custom" msgstr "" -#: ipam/forms/model_forms.py:908 +#: netbox/ipam/forms/model_forms.py:908 msgid "" "Must specify name, protocol, and port(s) if not using an application service " "template." msgstr "" -#: ipam/models/asns.py:35 +#: netbox/ipam/models/asns.py:35 msgid "start" msgstr "" -#: ipam/models/asns.py:52 +#: netbox/ipam/models/asns.py:52 msgid "ASN range" msgstr "" -#: ipam/models/asns.py:53 +#: netbox/ipam/models/asns.py:53 msgid "ASN ranges" msgstr "" -#: ipam/models/asns.py:63 +#: netbox/ipam/models/asns.py:63 #, python-brace-format msgid "Starting ASN ({start}) must be lower than ending ASN ({end})." msgstr "" -#: ipam/models/asns.py:133 +#: netbox/ipam/models/asns.py:133 msgid "Regional Internet Registry responsible for this AS number space" msgstr "" -#: ipam/models/asns.py:138 +#: netbox/ipam/models/asns.py:138 msgid "16- or 32-bit autonomous system number" msgstr "" -#: ipam/models/asns.py:147 +#: netbox/ipam/models/asns.py:147 msgid "The primary function of this ASN" msgstr "" -#: ipam/models/fhrp.py:21 +#: netbox/ipam/models/fhrp.py:21 msgid "group ID" msgstr "" -#: ipam/models/fhrp.py:29 ipam/models/services.py:21 +#: netbox/ipam/models/fhrp.py:29 netbox/ipam/models/services.py:21 msgid "protocol" msgstr "" -#: ipam/models/fhrp.py:38 wireless/models.py:30 +#: netbox/ipam/models/fhrp.py:38 netbox/wireless/models.py:30 msgid "authentication type" msgstr "" -#: ipam/models/fhrp.py:43 +#: netbox/ipam/models/fhrp.py:43 msgid "authentication key" msgstr "" -#: ipam/models/fhrp.py:65 +#: netbox/ipam/models/fhrp.py:65 msgid "FHRP group" msgstr "" -#: ipam/models/fhrp.py:66 +#: netbox/ipam/models/fhrp.py:66 msgid "FHRP groups" msgstr "" -#: ipam/models/fhrp.py:120 +#: netbox/ipam/models/fhrp.py:120 msgid "FHRP group assignment" msgstr "" -#: ipam/models/fhrp.py:121 +#: netbox/ipam/models/fhrp.py:121 msgid "FHRP group assignments" msgstr "" -#: ipam/models/ip.py:66 +#: netbox/ipam/models/ip.py:66 msgid "private" msgstr "" -#: ipam/models/ip.py:67 +#: netbox/ipam/models/ip.py:67 msgid "IP space managed by this RIR is considered private" msgstr "" -#: ipam/models/ip.py:73 netbox/navigation/menu.py:199 +#: netbox/ipam/models/ip.py:73 netbox/netbox/navigation/menu.py:199 msgid "RIRs" msgstr "" -#: ipam/models/ip.py:82 +#: netbox/ipam/models/ip.py:82 msgid "IPv4 or IPv6 network" msgstr "" -#: ipam/models/ip.py:89 +#: netbox/ipam/models/ip.py:89 msgid "Regional Internet Registry responsible for this IP space" msgstr "" -#: ipam/models/ip.py:99 +#: netbox/ipam/models/ip.py:99 msgid "date added" msgstr "" -#: ipam/models/ip.py:116 +#: netbox/ipam/models/ip.py:116 msgid "aggregate" msgstr "" -#: ipam/models/ip.py:117 +#: netbox/ipam/models/ip.py:117 msgid "aggregates" msgstr "" -#: ipam/models/ip.py:130 +#: netbox/ipam/models/ip.py:130 msgid "Cannot create aggregate with /0 mask." msgstr "" -#: ipam/models/ip.py:142 +#: netbox/ipam/models/ip.py:142 #, python-brace-format msgid "" "Aggregates cannot overlap. {prefix} is already covered by an existing " "aggregate ({aggregate})." msgstr "" -#: ipam/models/ip.py:156 +#: netbox/ipam/models/ip.py:156 #, python-brace-format msgid "" "Prefixes cannot overlap aggregates. {prefix} covers an existing aggregate " "({aggregate})." msgstr "" -#: ipam/models/ip.py:210 +#: netbox/ipam/models/ip.py:210 msgid "roles" msgstr "" -#: ipam/models/ip.py:223 ipam/models/ip.py:292 +#: netbox/ipam/models/ip.py:223 netbox/ipam/models/ip.py:292 msgid "prefix" msgstr "" -#: ipam/models/ip.py:224 +#: netbox/ipam/models/ip.py:224 msgid "IPv4 or IPv6 network with mask" msgstr "" -#: ipam/models/ip.py:253 +#: netbox/ipam/models/ip.py:253 msgid "Operational status of this prefix" msgstr "" -#: ipam/models/ip.py:261 +#: netbox/ipam/models/ip.py:261 msgid "The primary function of this prefix" msgstr "" -#: ipam/models/ip.py:264 +#: netbox/ipam/models/ip.py:264 msgid "is a pool" msgstr "" -#: ipam/models/ip.py:266 +#: netbox/ipam/models/ip.py:266 msgid "All IP addresses within this prefix are considered usable" msgstr "" -#: ipam/models/ip.py:269 ipam/models/ip.py:574 +#: netbox/ipam/models/ip.py:269 netbox/ipam/models/ip.py:574 msgid "mark utilized" msgstr "" -#: ipam/models/ip.py:293 +#: netbox/ipam/models/ip.py:293 msgid "prefixes" msgstr "" -#: ipam/models/ip.py:317 +#: netbox/ipam/models/ip.py:317 msgid "Cannot create prefix with /0 mask." msgstr "" -#: ipam/models/ip.py:324 ipam/models/ip.py:936 +#: netbox/ipam/models/ip.py:324 netbox/ipam/models/ip.py:936 #, python-brace-format msgid "VRF {vrf}" msgstr "" -#: ipam/models/ip.py:324 ipam/models/ip.py:936 +#: netbox/ipam/models/ip.py:324 netbox/ipam/models/ip.py:936 msgid "global table" msgstr "" -#: ipam/models/ip.py:326 +#: netbox/ipam/models/ip.py:326 #, python-brace-format msgid "Duplicate prefix found in {table}: {prefix}" msgstr "" -#: ipam/models/ip.py:527 +#: netbox/ipam/models/ip.py:527 msgid "start address" msgstr "" -#: ipam/models/ip.py:528 ipam/models/ip.py:532 ipam/models/ip.py:769 +#: netbox/ipam/models/ip.py:528 netbox/ipam/models/ip.py:532 +#: netbox/ipam/models/ip.py:769 msgid "IPv4 or IPv6 address (with mask)" msgstr "" -#: ipam/models/ip.py:531 +#: netbox/ipam/models/ip.py:531 msgid "end address" msgstr "" -#: ipam/models/ip.py:558 +#: netbox/ipam/models/ip.py:558 msgid "Operational status of this range" msgstr "" -#: ipam/models/ip.py:566 +#: netbox/ipam/models/ip.py:566 msgid "The primary function of this range" msgstr "" -#: ipam/models/ip.py:569 +#: netbox/ipam/models/ip.py:569 msgid "mark populated" msgstr "" -#: ipam/models/ip.py:571 +#: netbox/ipam/models/ip.py:571 msgid "Prevent the creation of IP addresses within this range" msgstr "" -#: ipam/models/ip.py:576 +#: netbox/ipam/models/ip.py:576 msgid "Report space as fully utilized" msgstr "" -#: ipam/models/ip.py:585 +#: netbox/ipam/models/ip.py:585 msgid "IP range" msgstr "" -#: ipam/models/ip.py:586 +#: netbox/ipam/models/ip.py:586 msgid "IP ranges" msgstr "" -#: ipam/models/ip.py:599 +#: netbox/ipam/models/ip.py:599 msgid "Starting and ending IP address versions must match" msgstr "" -#: ipam/models/ip.py:605 +#: netbox/ipam/models/ip.py:605 msgid "Starting and ending IP address masks must match" msgstr "" -#: ipam/models/ip.py:612 +#: netbox/ipam/models/ip.py:612 #, python-brace-format msgid "" "Ending address must be greater than the starting address ({start_address})" msgstr "" -#: ipam/models/ip.py:640 +#: netbox/ipam/models/ip.py:640 #, python-brace-format msgid "Defined addresses overlap with range {overlapping_range} in VRF {vrf}" msgstr "" -#: ipam/models/ip.py:649 +#: netbox/ipam/models/ip.py:649 #, python-brace-format msgid "Defined range exceeds maximum supported size ({max_size})" msgstr "" -#: ipam/models/ip.py:768 tenancy/models/contacts.py:104 +#: netbox/ipam/models/ip.py:768 netbox/tenancy/models/contacts.py:104 msgid "address" msgstr "" -#: ipam/models/ip.py:791 +#: netbox/ipam/models/ip.py:791 msgid "The operational status of this IP" msgstr "" -#: ipam/models/ip.py:799 +#: netbox/ipam/models/ip.py:799 msgid "The functional role of this IP" msgstr "" -#: ipam/models/ip.py:822 ipam/ui/panels.py:127 +#: netbox/ipam/models/ip.py:822 netbox/ipam/ui/panels.py:127 msgid "NAT (inside)" msgstr "" -#: ipam/models/ip.py:823 +#: netbox/ipam/models/ip.py:823 msgid "The IP for which this address is the \"outside\" IP" msgstr "" -#: ipam/models/ip.py:830 +#: netbox/ipam/models/ip.py:830 msgid "Hostname or FQDN (not case-sensitive)" msgstr "" -#: ipam/models/ip.py:847 ipam/models/services.py:86 +#: netbox/ipam/models/ip.py:847 netbox/ipam/models/services.py:86 msgid "IP addresses" msgstr "" -#: ipam/models/ip.py:907 +#: netbox/ipam/models/ip.py:907 msgid "Cannot create IP address with /0 mask." msgstr "" -#: ipam/models/ip.py:913 +#: netbox/ipam/models/ip.py:913 #, python-brace-format msgid "{ip} is a network ID, which may not be assigned to an interface." msgstr "" -#: ipam/models/ip.py:924 +#: netbox/ipam/models/ip.py:924 #, python-brace-format msgid "{ip} is a broadcast address, which may not be assigned to an interface." msgstr "" -#: ipam/models/ip.py:938 +#: netbox/ipam/models/ip.py:938 #, python-brace-format msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "" -#: ipam/models/ip.py:954 +#: netbox/ipam/models/ip.py:954 #, python-brace-format msgid "Cannot create IP address {ip} inside range {range}." msgstr "" -#: ipam/models/ip.py:975 +#: netbox/ipam/models/ip.py:975 msgid "" "Cannot reassign IP address while it is designated as the primary IP for the " "parent object" msgstr "" -#: ipam/models/ip.py:982 +#: netbox/ipam/models/ip.py:982 msgid "" "Cannot reassign IP address while it is designated as the OOB IP for the " "parent object" msgstr "" -#: ipam/models/ip.py:988 +#: netbox/ipam/models/ip.py:988 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "" -#: ipam/models/services.py:32 +#: netbox/ipam/models/services.py:32 msgid "port numbers" msgstr "" -#: ipam/models/services.py:58 +#: netbox/ipam/models/services.py:58 msgid "application service template" msgstr "" -#: ipam/models/services.py:59 +#: netbox/ipam/models/services.py:59 msgid "application service templates" msgstr "" -#: ipam/models/services.py:87 +#: netbox/ipam/models/services.py:87 msgid "" "The specific IP addresses (if any) to which this application service is bound" msgstr "" -#: ipam/models/services.py:100 +#: netbox/ipam/models/services.py:100 msgid "application service" msgstr "" -#: ipam/models/services.py:101 +#: netbox/ipam/models/services.py:101 msgid "application services" msgstr "" -#: ipam/models/vlans.py:93 +#: netbox/ipam/models/vlans.py:93 msgid "VLAN groups" msgstr "" -#: ipam/models/vlans.py:100 +#: netbox/ipam/models/vlans.py:100 msgid "Cannot set scope_type without scope_id." msgstr "" -#: ipam/models/vlans.py:102 +#: netbox/ipam/models/vlans.py:102 msgid "Cannot set scope_id without scope_type." msgstr "" -#: ipam/models/vlans.py:110 +#: netbox/ipam/models/vlans.py:110 #, python-brace-format msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" msgstr "" -#: ipam/models/vlans.py:116 +#: netbox/ipam/models/vlans.py:116 #, python-brace-format msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" msgstr "" -#: ipam/models/vlans.py:123 +#: netbox/ipam/models/vlans.py:123 #, python-brace-format msgid "" "Ending VLAN ID in range must be greater than or equal to the starting VLAN " "ID ({range})" msgstr "" -#: ipam/models/vlans.py:129 +#: netbox/ipam/models/vlans.py:129 msgid "Ranges cannot overlap." msgstr "" -#: ipam/models/vlans.py:197 +#: netbox/ipam/models/vlans.py:197 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "" -#: ipam/models/vlans.py:205 +#: netbox/ipam/models/vlans.py:205 msgid "VLAN group (optional)" msgstr "" -#: ipam/models/vlans.py:213 ipam/models/vlans.py:396 ipam/models/vlans.py:404 +#: netbox/ipam/models/vlans.py:213 netbox/ipam/models/vlans.py:396 +#: netbox/ipam/models/vlans.py:404 msgid "Numeric VLAN ID (1-4094)" msgstr "" -#: ipam/models/vlans.py:231 +#: netbox/ipam/models/vlans.py:231 msgid "Operational status of this VLAN" msgstr "" -#: ipam/models/vlans.py:239 +#: netbox/ipam/models/vlans.py:239 msgid "The primary function of this VLAN" msgstr "" -#: ipam/models/vlans.py:254 +#: netbox/ipam/models/vlans.py:254 msgid "Customer/service VLAN designation (for Q-in-Q/IEEE 802.1ad)" msgstr "" -#: ipam/models/vlans.py:306 +#: netbox/ipam/models/vlans.py:306 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " "site {site}." msgstr "" -#: ipam/models/vlans.py:313 +#: netbox/ipam/models/vlans.py:313 #, python-brace-format msgid "" "The assigned site {site} is not a member of the assigned group {group} " "(scope: {scope})." msgstr "" -#: ipam/models/vlans.py:322 +#: netbox/ipam/models/vlans.py:322 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "" -#: ipam/models/vlans.py:329 +#: netbox/ipam/models/vlans.py:329 msgid "Only Q-in-Q customer VLANs maybe assigned to a service VLAN." msgstr "" -#: ipam/models/vlans.py:335 +#: netbox/ipam/models/vlans.py:335 msgid "A Q-in-Q customer VLAN must be assigned to a service VLAN." msgstr "" -#: ipam/models/vlans.py:372 +#: netbox/ipam/models/vlans.py:372 msgid "VLAN translation policies" msgstr "" -#: ipam/models/vlans.py:413 +#: netbox/ipam/models/vlans.py:413 msgid "VLAN translation rule" msgstr "" -#: ipam/models/vrfs.py:29 +#: netbox/ipam/models/vrfs.py:29 msgid "route distinguisher" msgstr "" -#: ipam/models/vrfs.py:30 +#: netbox/ipam/models/vrfs.py:30 msgid "Unique route distinguisher (as defined in RFC 4364)" msgstr "" -#: ipam/models/vrfs.py:41 +#: netbox/ipam/models/vrfs.py:41 msgid "enforce unique space" msgstr "" -#: ipam/models/vrfs.py:42 +#: netbox/ipam/models/vrfs.py:42 msgid "Prevent duplicate prefixes/IP addresses within this VRF" msgstr "" -#: ipam/models/vrfs.py:65 netbox/navigation/menu.py:203 -#: netbox/navigation/menu.py:205 +#: netbox/ipam/models/vrfs.py:65 netbox/netbox/navigation/menu.py:203 +#: netbox/netbox/navigation/menu.py:205 msgid "VRFs" msgstr "" -#: ipam/models/vrfs.py:81 +#: netbox/ipam/models/vrfs.py:81 msgid "Route target value (formatted in accordance with RFC 4360)" msgstr "" -#: ipam/models/vrfs.py:94 +#: netbox/ipam/models/vrfs.py:94 msgid "route target" msgstr "" -#: ipam/models/vrfs.py:95 +#: netbox/ipam/models/vrfs.py:95 msgid "route targets" msgstr "" -#: ipam/tables/asn.py:26 +#: netbox/ipam/tables/asn.py:26 msgid "Start (ASDOT)" msgstr "" -#: ipam/tables/asn.py:31 +#: netbox/ipam/tables/asn.py:31 msgid "End (ASDOT)" msgstr "" -#: ipam/tables/asn.py:62 +#: netbox/ipam/tables/asn.py:62 msgid "ASDOT" msgstr "" -#: ipam/tables/asn.py:67 +#: netbox/ipam/tables/asn.py:67 msgid "Site Count" msgstr "" -#: ipam/tables/asn.py:72 +#: netbox/ipam/tables/asn.py:72 msgid "Provider Count" msgstr "" -#: ipam/tables/ip.py:43 netbox/navigation/menu.py:196 -#: netbox/navigation/menu.py:198 +#: netbox/ipam/tables/ip.py:43 netbox/netbox/navigation/menu.py:196 +#: netbox/netbox/navigation/menu.py:198 msgid "Aggregates" msgstr "" -#: ipam/tables/ip.py:73 +#: netbox/ipam/tables/ip.py:73 msgid "Added" msgstr "" -#: ipam/tables/ip.py:76 ipam/tables/ip.py:111 ipam/tables/vlans.py:125 -#: ipam/views.py:559 ipam/views.py:1650 netbox/navigation/menu.py:182 -#: netbox/navigation/menu.py:184 +#: netbox/ipam/tables/ip.py:76 netbox/ipam/tables/ip.py:111 +#: netbox/ipam/tables/vlans.py:125 netbox/ipam/views.py:559 +#: netbox/ipam/views.py:1650 netbox/netbox/navigation/menu.py:182 +#: netbox/netbox/navigation/menu.py:184 msgid "Prefixes" msgstr "" -#: ipam/tables/ip.py:79 ipam/tables/ip.py:225 ipam/tables/ip.py:282 -#: ipam/tables/vlans.py:59 ipam/ui/panels.py:80 ipam/ui/panels.py:101 -#: templates/dcim/panels/power_utilization.html:12 -#: templates/ipam/panels/prefix_addressing.html:15 +#: netbox/ipam/tables/ip.py:79 netbox/ipam/tables/ip.py:225 +#: netbox/ipam/tables/ip.py:282 netbox/ipam/tables/vlans.py:59 +#: netbox/ipam/ui/panels.py:80 netbox/ipam/ui/panels.py:101 +#: netbox/templates/dcim/panels/power_utilization.html:12 +#: netbox/templates/ipam/panels/prefix_addressing.html:15 msgid "Utilization" msgstr "" -#: ipam/tables/ip.py:116 netbox/navigation/menu.py:178 +#: netbox/ipam/tables/ip.py:116 netbox/netbox/navigation/menu.py:178 msgid "IP Ranges" msgstr "" -#: ipam/tables/ip.py:171 +#: netbox/ipam/tables/ip.py:171 msgid "Prefix (Flat)" msgstr "" -#: ipam/tables/ip.py:175 +#: netbox/ipam/tables/ip.py:175 msgid "Depth" msgstr "" -#: ipam/tables/ip.py:195 ipam/tables/vlans.py:37 -#: virtualization/tables/clusters.py:78 wireless/tables/wirelesslan.py:48 +#: netbox/ipam/tables/ip.py:195 netbox/ipam/tables/vlans.py:37 +#: netbox/virtualization/tables/clusters.py:78 +#: netbox/wireless/tables/wirelesslan.py:48 msgid "Scope Type" msgstr "" -#: ipam/tables/ip.py:217 +#: netbox/ipam/tables/ip.py:217 msgid "Pool" msgstr "" -#: ipam/tables/ip.py:221 ipam/tables/ip.py:278 ipam/ui/panels.py:97 +#: netbox/ipam/tables/ip.py:221 netbox/ipam/tables/ip.py:278 +#: netbox/ipam/ui/panels.py:97 msgid "Marked Utilized" msgstr "" -#: ipam/tables/ip.py:258 +#: netbox/ipam/tables/ip.py:258 msgid "Start address" msgstr "" -#: ipam/tables/ip.py:274 ipam/ui/panels.py:96 +#: netbox/ipam/tables/ip.py:274 netbox/ipam/ui/panels.py:96 msgid "Marked Populated" msgstr "" -#: ipam/tables/ip.py:339 +#: netbox/ipam/tables/ip.py:339 msgid "NAT (Inside)" msgstr "" -#: ipam/tables/ip.py:344 +#: netbox/ipam/tables/ip.py:344 msgid "NAT (Outside)" msgstr "" -#: ipam/tables/ip.py:349 +#: netbox/ipam/tables/ip.py:349 msgid "Assigned" msgstr "" -#: ipam/tables/ip.py:397 vpn/forms/filtersets.py:262 +#: netbox/ipam/tables/ip.py:397 netbox/vpn/forms/filtersets.py:262 msgid "Assigned Object" msgstr "" -#: ipam/tables/vlans.py:46 +#: netbox/ipam/tables/vlans.py:46 msgid "VID Ranges" msgstr "" -#: ipam/tables/vlans.py:87 templates/dcim/inc/interface_vlans_table.html:4 +#: netbox/ipam/tables/vlans.py:87 +#: netbox/templates/dcim/inc/interface_vlans_table.html:4 msgid "VID" msgstr "" -#: ipam/tables/vlans.py:215 +#: netbox/ipam/tables/vlans.py:215 msgid "Rules" msgstr "" -#: ipam/tables/vlans.py:238 ipam/ui/panels.py:175 +#: netbox/ipam/tables/vlans.py:238 netbox/ipam/ui/panels.py:175 msgid "Local VID" msgstr "" -#: ipam/tables/vlans.py:242 ipam/ui/panels.py:176 +#: netbox/ipam/tables/vlans.py:242 netbox/ipam/ui/panels.py:176 msgid "Remote VID" msgstr "" -#: ipam/tables/vrfs.py:30 +#: netbox/ipam/tables/vrfs.py:30 msgid "RD" msgstr "" -#: ipam/tables/vrfs.py:33 +#: netbox/ipam/tables/vrfs.py:33 msgid "Unique" msgstr "" -#: ipam/tables/vrfs.py:37 vpn/tables/l2vpn.py:30 +#: netbox/ipam/tables/vrfs.py:37 netbox/vpn/tables/l2vpn.py:30 msgid "Import Targets" msgstr "" -#: ipam/tables/vrfs.py:42 vpn/tables/l2vpn.py:35 +#: netbox/ipam/tables/vrfs.py:42 netbox/vpn/tables/l2vpn.py:35 msgid "Export Targets" msgstr "" -#: ipam/ui/panels.py:28 templates/ipam/inc/panels/fhrp_groups.html:10 +#: netbox/ipam/ui/panels.py:28 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:10 msgid "Create Group" msgstr "" -#: ipam/ui/panels.py:42 +#: netbox/ipam/ui/panels.py:42 msgid "Route Distinguisher" msgstr "" -#: ipam/ui/panels.py:44 +#: netbox/ipam/ui/panels.py:44 msgid "Unique IP Space" msgstr "" -#: ipam/ui/panels.py:67 +#: netbox/ipam/ui/panels.py:67 msgid "AS Number" msgstr "" -#: ipam/ui/panels.py:75 ipam/ui/panels.py:92 ipam/ui/panels.py:111 -#: ipam/ui/panels.py:139 +#: netbox/ipam/ui/panels.py:75 netbox/ipam/ui/panels.py:92 +#: netbox/ipam/ui/panels.py:111 netbox/ipam/ui/panels.py:139 msgid "Family" msgstr "" -#: ipam/ui/panels.py:83 +#: netbox/ipam/ui/panels.py:83 msgid "Date Added" msgstr "" -#: ipam/ui/panels.py:93 +#: netbox/ipam/ui/panels.py:93 msgid "Starting Address" msgstr "" -#: ipam/ui/panels.py:94 +#: netbox/ipam/ui/panels.py:94 msgid "Ending Address" msgstr "" -#: ipam/ui/panels.py:132 +#: netbox/ipam/ui/panels.py:132 msgid "NAT (outside)" msgstr "" -#: ipam/ui/panels.py:134 +#: netbox/ipam/ui/panels.py:134 msgid "Primary IP" msgstr "" -#: ipam/ui/panels.py:135 +#: netbox/ipam/ui/panels.py:135 msgid "OOB IP" msgstr "" -#: ipam/ui/panels.py:191 +#: netbox/ipam/ui/panels.py:191 msgid "Authentication Type" msgstr "" -#: ipam/ui/panels.py:192 +#: netbox/ipam/ui/panels.py:192 msgid "Authentication Key" msgstr "" -#: ipam/ui/panels.py:205 +#: netbox/ipam/ui/panels.py:205 msgid "Q-in-Q Role" msgstr "" -#: ipam/ui/panels.py:219 +#: netbox/ipam/ui/panels.py:219 msgid "Customer VLANs" msgstr "" -#: ipam/ui/panels.py:227 +#: netbox/ipam/ui/panels.py:227 msgid "Add a VLAN" msgstr "" -#: ipam/utils.py:30 +#: netbox/ipam/utils.py:30 msgid "1 IP available" msgstr "" -#: ipam/utils.py:32 +#: netbox/ipam/utils.py:32 #, python-brace-format msgid "{count} IPs available" msgstr "" -#: ipam/utils.py:33 +#: netbox/ipam/utils.py:33 msgid "Many IPs available" msgstr "" -#: ipam/validators.py:9 +#: netbox/ipam/validators.py:9 #, python-brace-format msgid "{prefix} is not a valid prefix. Did you mean {suggested}?" msgstr "" -#: ipam/validators.py:16 +#: netbox/ipam/validators.py:16 #, python-format msgid "The prefix length must be less than or equal to %(limit_value)s." msgstr "" -#: ipam/validators.py:24 +#: netbox/ipam/validators.py:24 #, python-format msgid "The prefix length must be greater than or equal to %(limit_value)s." msgstr "" -#: ipam/validators.py:33 +#: netbox/ipam/validators.py:33 msgid "" "Only alphanumeric characters, asterisks, hyphens, periods, and underscores " "are allowed in DNS names" msgstr "" -#: ipam/views.py:105 ipam/views.py:1677 +#: netbox/ipam/views.py:105 netbox/ipam/views.py:1680 msgid "Device Interfaces" msgstr "" -#: ipam/views.py:110 ipam/views.py:1695 +#: netbox/ipam/views.py:110 netbox/ipam/views.py:1698 msgid "VM Interfaces" msgstr "" -#: ipam/views.py:195 +#: netbox/ipam/views.py:195 msgid "Importing VRFs" msgstr "" -#: ipam/views.py:202 +#: netbox/ipam/views.py:202 msgid "Exporting VRFs" msgstr "" -#: ipam/views.py:211 +#: netbox/ipam/views.py:211 msgid "Importing L2VPNs" msgstr "" -#: ipam/views.py:218 +#: netbox/ipam/views.py:218 msgid "Exporting L2VPNs" msgstr "" -#: ipam/views.py:728 +#: netbox/ipam/views.py:728 msgid "Duplicate prefixes" msgstr "" -#: ipam/views.py:729 ipam/views.py:933 ipam/views.py:1041 +#: netbox/ipam/views.py:729 netbox/ipam/views.py:933 netbox/ipam/views.py:1041 msgid "Parent prefixes" msgstr "" -#: ipam/views.py:781 +#: netbox/ipam/views.py:781 msgid "Child Prefixes" msgstr "" -#: ipam/views.py:817 +#: netbox/ipam/views.py:817 msgid "Child Ranges" msgstr "" -#: ipam/views.py:1042 +#: netbox/ipam/views.py:1042 msgid "Duplicate IPs" msgstr "" -#: ipam/views.py:1046 +#: netbox/ipam/views.py:1046 msgid "Application services" msgstr "" -#: ipam/views.py:1212 +#: netbox/ipam/views.py:1212 msgid "Related IPs" msgstr "" -#: ipam/views.py:1351 +#: netbox/ipam/views.py:1351 msgid "VLAN translation rules" msgstr "" -#: ipam/views.py:1357 +#: netbox/ipam/views.py:1357 msgid "Add Rule" msgstr "" -#: ipam/views.py:1499 +#: netbox/ipam/views.py:1499 msgid "Virtual IP addresses" msgstr "" -#: ipam/views.py:1504 templates/ipam/iprange/ip_addresses.html:7 -#: templates/ipam/prefix/ip_addresses.html:7 +#: netbox/ipam/views.py:1504 netbox/templates/ipam/iprange/ip_addresses.html:7 +#: netbox/templates/ipam/prefix/ip_addresses.html:7 msgid "Add IP Address" msgstr "" -#: ipam/views.py:1660 +#: netbox/ipam/views.py:1663 msgid "Add a Prefix" msgstr "" -#: netbox/api/fields.py:67 +#: netbox/netbox/api/fields.py:67 msgid "This field may not be blank." msgstr "" -#: netbox/api/fields.py:72 +#: netbox/netbox/api/fields.py:72 msgid "" "Value must be passed directly (e.g. \"foo\": 123); do not use a dictionary " "or list." msgstr "" -#: netbox/api/fields.py:93 +#: netbox/netbox/api/fields.py:93 #, python-brace-format msgid "{value} is not a valid choice." msgstr "" -#: netbox/api/fields.py:106 +#: netbox/netbox/api/fields.py:106 #, python-brace-format msgid "Invalid content type: {content_type}" msgstr "" -#: netbox/api/fields.py:107 +#: netbox/netbox/api/fields.py:107 msgid "Invalid value. Specify a content type as '.'." msgstr "" -#: netbox/api/fields.py:169 +#: netbox/netbox/api/fields.py:169 msgid "Ranges must be specified in the form (lower, upper)." msgstr "" -#: netbox/api/fields.py:171 +#: netbox/netbox/api/fields.py:171 msgid "Range boundaries must be defined as integers." msgstr "" -#: netbox/api/pagination.py:55 +#: netbox/netbox/api/pagination.py:57 #, python-brace-format msgid "'{start_param}' and '{offset_param}' are mutually exclusive." msgstr "" -#: netbox/api/pagination.py:61 +#: netbox/netbox/api/pagination.py:63 msgid "" "Ordering cannot be specified in conjunction with cursor-based pagination." msgstr "" -#: netbox/api/pagination.py:99 netbox/api/pagination.py:108 +#: netbox/netbox/api/pagination.py:101 netbox/netbox/api/pagination.py:110 #, python-brace-format msgid "Invalid '{param}' parameter: must be a non-negative integer." msgstr "" -#: netbox/api/serializers/fields.py:40 +#: netbox/netbox/api/serializers/fields.py:40 #, python-brace-format msgid "{class_name} must implement get_view_name()" msgstr "" -#: netbox/authentication/__init__.py:143 +#: netbox/netbox/authentication/__init__.py:143 #, python-brace-format msgid "Invalid permission {permission} for model {model}" msgstr "" -#: netbox/choices.py:51 +#: netbox/netbox/choices.py:51 msgid "Dark Red" msgstr "" -#: netbox/choices.py:54 +#: netbox/netbox/choices.py:54 msgid "Rose" msgstr "" -#: netbox/choices.py:55 +#: netbox/netbox/choices.py:55 msgid "Fuchsia" msgstr "" -#: netbox/choices.py:57 +#: netbox/netbox/choices.py:57 msgid "Dark Purple" msgstr "" -#: netbox/choices.py:60 +#: netbox/netbox/choices.py:60 msgid "Light Blue" msgstr "" -#: netbox/choices.py:63 +#: netbox/netbox/choices.py:63 msgid "Aqua" msgstr "" -#: netbox/choices.py:64 +#: netbox/netbox/choices.py:64 msgid "Dark Green" msgstr "" -#: netbox/choices.py:66 +#: netbox/netbox/choices.py:66 msgid "Light Green" msgstr "" -#: netbox/choices.py:67 +#: netbox/netbox/choices.py:67 msgid "Lime" msgstr "" -#: netbox/choices.py:69 +#: netbox/netbox/choices.py:69 msgid "Amber" msgstr "" -#: netbox/choices.py:71 +#: netbox/netbox/choices.py:71 msgid "Dark Orange" msgstr "" -#: netbox/choices.py:72 +#: netbox/netbox/choices.py:72 msgid "Brown" msgstr "" -#: netbox/choices.py:73 +#: netbox/netbox/choices.py:73 msgid "Light Grey" msgstr "" -#: netbox/choices.py:74 +#: netbox/netbox/choices.py:74 msgid "Grey" msgstr "" -#: netbox/choices.py:75 +#: netbox/netbox/choices.py:75 msgid "Dark Grey" msgstr "" -#: netbox/choices.py:103 templates/core/htmx/system_db_schema.html:72 -#: templates/extras/panels/tableconfig_ordering.html:19 -#: templates/extras/script_result.html:56 +#: netbox/netbox/choices.py:103 +#: netbox/templates/core/htmx/system_db_schema.html:72 +#: netbox/templates/extras/panels/tableconfig_ordering.html:19 +#: netbox/templates/extras/script_result.html:56 msgid "Default" msgstr "" -#: netbox/choices.py:130 +#: netbox/netbox/choices.py:130 msgid "Direct" msgstr "" -#: netbox/choices.py:131 +#: netbox/netbox/choices.py:131 msgid "Upload" msgstr "" -#: netbox/choices.py:143 netbox/choices.py:158 +#: netbox/netbox/choices.py:143 netbox/netbox/choices.py:158 msgid "Auto-detect" msgstr "" -#: netbox/choices.py:159 +#: netbox/netbox/choices.py:159 msgid "Comma" msgstr "" -#: netbox/choices.py:160 +#: netbox/netbox/choices.py:160 msgid "Semicolon" msgstr "" -#: netbox/choices.py:161 +#: netbox/netbox/choices.py:161 msgid "Pipe" msgstr "" -#: netbox/choices.py:162 +#: netbox/netbox/choices.py:162 msgid "Tab" msgstr "" -#: netbox/choices.py:195 templates/dcim/device/attrs/total_weight.html:2 -#: templates/dcim/rack/attrs/total_weight.html:2 +#: netbox/netbox/choices.py:195 +#: netbox/templates/dcim/device/attrs/total_weight.html:2 +#: netbox/templates/dcim/rack/attrs/total_weight.html:2 msgid "Kilograms" msgstr "" -#: netbox/choices.py:196 +#: netbox/netbox/choices.py:196 msgid "Grams" msgstr "" -#: netbox/choices.py:197 templates/dcim/device/attrs/total_weight.html:3 -#: templates/dcim/rack/attrs/total_weight.html:3 +#: netbox/netbox/choices.py:197 +#: netbox/templates/dcim/device/attrs/total_weight.html:3 +#: netbox/templates/dcim/rack/attrs/total_weight.html:3 msgid "Pounds" msgstr "" -#: netbox/choices.py:198 +#: netbox/netbox/choices.py:198 msgid "Ounces" msgstr "" -#: netbox/config/__init__.py:68 +#: netbox/netbox/config/__init__.py:68 #, python-brace-format msgid "Invalid configuration parameter: {item}" msgstr "" -#: netbox/config/parameters.py:22 templates/core/inc/config_data.html:62 +#: netbox/netbox/config/parameters.py:22 +#: netbox/templates/core/inc/config_data.html:62 msgid "Login banner" msgstr "" -#: netbox/config/parameters.py:24 +#: netbox/netbox/config/parameters.py:24 msgid "Additional content to display on the login page" msgstr "" -#: netbox/config/parameters.py:33 templates/core/inc/config_data.html:66 +#: netbox/netbox/config/parameters.py:33 +#: netbox/templates/core/inc/config_data.html:66 msgid "Maintenance banner" msgstr "" -#: netbox/config/parameters.py:35 +#: netbox/netbox/config/parameters.py:35 msgid "Additional content to display when in maintenance mode" msgstr "" -#: netbox/config/parameters.py:44 templates/core/inc/config_data.html:70 +#: netbox/netbox/config/parameters.py:44 +#: netbox/templates/core/inc/config_data.html:70 msgid "Top banner" msgstr "" -#: netbox/config/parameters.py:46 +#: netbox/netbox/config/parameters.py:46 msgid "Additional content to display at the top of every page" msgstr "" -#: netbox/config/parameters.py:55 templates/core/inc/config_data.html:74 +#: netbox/netbox/config/parameters.py:55 +#: netbox/templates/core/inc/config_data.html:74 msgid "Bottom banner" msgstr "" -#: netbox/config/parameters.py:57 +#: netbox/netbox/config/parameters.py:57 msgid "Additional content to display at the bottom of every page" msgstr "" -#: netbox/config/parameters.py:68 +#: netbox/netbox/config/parameters.py:68 msgid "Globally unique IP space" msgstr "" -#: netbox/config/parameters.py:70 +#: netbox/netbox/config/parameters.py:70 msgid "Enforce unique IP addressing within the global table" msgstr "" -#: netbox/config/parameters.py:75 templates/core/inc/config_data.html:44 +#: netbox/netbox/config/parameters.py:75 +#: netbox/templates/core/inc/config_data.html:44 msgid "Prefer IPv4" msgstr "" -#: netbox/config/parameters.py:77 +#: netbox/netbox/config/parameters.py:77 msgid "Prefer IPv4 addresses over IPv6" msgstr "" -#: netbox/config/parameters.py:84 +#: netbox/netbox/config/parameters.py:84 msgid "Rack unit height" msgstr "" -#: netbox/config/parameters.py:86 +#: netbox/netbox/config/parameters.py:86 msgid "Default unit height for rendered rack elevations" msgstr "" -#: netbox/config/parameters.py:91 +#: netbox/netbox/config/parameters.py:91 msgid "Rack unit width" msgstr "" -#: netbox/config/parameters.py:93 +#: netbox/netbox/config/parameters.py:93 msgid "Default unit width for rendered rack elevations" msgstr "" -#: netbox/config/parameters.py:100 +#: netbox/netbox/config/parameters.py:100 msgid "Powerfeed voltage" msgstr "" -#: netbox/config/parameters.py:102 +#: netbox/netbox/config/parameters.py:102 msgid "Default voltage for powerfeeds" msgstr "" -#: netbox/config/parameters.py:107 +#: netbox/netbox/config/parameters.py:107 msgid "Powerfeed amperage" msgstr "" -#: netbox/config/parameters.py:109 +#: netbox/netbox/config/parameters.py:109 msgid "Default amperage for powerfeeds" msgstr "" -#: netbox/config/parameters.py:114 +#: netbox/netbox/config/parameters.py:114 msgid "Powerfeed max utilization" msgstr "" -#: netbox/config/parameters.py:116 +#: netbox/netbox/config/parameters.py:116 msgid "Default max utilization for powerfeeds" msgstr "" -#: netbox/config/parameters.py:123 templates/core/inc/config_data.html:53 +#: netbox/netbox/config/parameters.py:123 +#: netbox/templates/core/inc/config_data.html:53 msgid "Allowed URL schemes" msgstr "" -#: netbox/config/parameters.py:128 +#: netbox/netbox/config/parameters.py:128 msgid "Permitted schemes for URLs in user-provided content" msgstr "" -#: netbox/config/parameters.py:136 +#: netbox/netbox/config/parameters.py:136 msgid "Default page size" msgstr "" -#: netbox/config/parameters.py:142 +#: netbox/netbox/config/parameters.py:142 msgid "Maximum page size" msgstr "" -#: netbox/config/parameters.py:150 templates/core/inc/config_data.html:96 +#: netbox/netbox/config/parameters.py:150 +#: netbox/templates/core/inc/config_data.html:96 msgid "Custom validators" msgstr "" -#: netbox/config/parameters.py:152 +#: netbox/netbox/config/parameters.py:152 msgid "Custom validation rules (JSON)" msgstr "" -#: netbox/config/parameters.py:160 templates/core/inc/config_data.html:104 +#: netbox/netbox/config/parameters.py:160 +#: netbox/templates/core/inc/config_data.html:104 msgid "Protection rules" msgstr "" -#: netbox/config/parameters.py:162 +#: netbox/netbox/config/parameters.py:162 msgid "Deletion protection rules (JSON)" msgstr "" -#: netbox/config/parameters.py:172 templates/core/inc/config_data.html:117 +#: netbox/netbox/config/parameters.py:172 +#: netbox/templates/core/inc/config_data.html:117 msgid "Default preferences" msgstr "" -#: netbox/config/parameters.py:174 +#: netbox/netbox/config/parameters.py:174 msgid "Default preferences for new users" msgstr "" -#: netbox/config/parameters.py:181 templates/core/inc/config_data.html:130 +#: netbox/netbox/config/parameters.py:181 +#: netbox/templates/core/inc/config_data.html:130 msgid "Changelog retention" msgstr "" -#: netbox/config/parameters.py:183 +#: netbox/netbox/config/parameters.py:183 msgid "Days to retain changelog history (set to zero for unlimited)" msgstr "" -#: netbox/config/parameters.py:188 +#: netbox/netbox/config/parameters.py:188 msgid "Retain create & last update changelog records" msgstr "" -#: netbox/config/parameters.py:191 +#: netbox/netbox/config/parameters.py:191 msgid "" "Retain each object's create record and most recent update record when " "pruning expired changelog entries (excluding objects with a delete record)." msgstr "" -#: netbox/config/parameters.py:200 templates/core/inc/config_data.html:142 +#: netbox/netbox/config/parameters.py:200 +#: netbox/templates/core/inc/config_data.html:142 msgid "Maintenance mode" msgstr "" -#: netbox/config/parameters.py:202 +#: netbox/netbox/config/parameters.py:202 msgid "Enable maintenance mode" msgstr "" -#: netbox/config/parameters.py:207 templates/core/inc/config_data.html:146 +#: netbox/netbox/config/parameters.py:207 +#: netbox/templates/core/inc/config_data.html:146 msgid "NetBox Copilot enabled" msgstr "" -#: netbox/config/parameters.py:210 +#: netbox/netbox/config/parameters.py:210 msgid "" "Enable the NetBox Copilot AI agent globally. If enabled, users can toggle " "the agent individually." msgstr "" -#: netbox/config/parameters.py:216 templates/core/inc/config_data.html:150 +#: netbox/netbox/config/parameters.py:216 +#: netbox/templates/core/inc/config_data.html:150 msgid "GraphQL enabled" msgstr "" -#: netbox/config/parameters.py:218 +#: netbox/netbox/config/parameters.py:218 msgid "Enable the GraphQL API" msgstr "" -#: netbox/config/parameters.py:223 +#: netbox/netbox/config/parameters.py:223 msgid "Job result retention" msgstr "" -#: netbox/config/parameters.py:225 +#: netbox/netbox/config/parameters.py:225 msgid "Days to retain job result history (set to zero for unlimited)" msgstr "" -#: netbox/config/parameters.py:230 templates/core/inc/config_data.html:158 +#: netbox/netbox/config/parameters.py:230 +#: netbox/templates/core/inc/config_data.html:158 msgid "Maps URL" msgstr "" -#: netbox/config/parameters.py:232 +#: netbox/netbox/config/parameters.py:232 msgid "Base URL for mapping geographic locations" msgstr "" -#: netbox/forms/bulk_edit.py:36 +#: netbox/netbox/forms/bulk_edit.py:36 msgid "Add tags" msgstr "" -#: netbox/forms/bulk_edit.py:41 +#: netbox/netbox/forms/bulk_edit.py:41 msgid "Remove tags" msgstr "" -#: netbox/forms/bulk_import.py:31 +#: netbox/netbox/forms/bulk_import.py:31 msgid "" "Tag slugs separated by commas, encased with double quotes (e.g. \"tag1,tag2," "tag3\")" msgstr "" -#: netbox/forms/bulk_import.py:79 +#: netbox/netbox/forms/bulk_import.py:79 msgid "Name of the object's owner" msgstr "" -#: netbox/forms/mixins.py:62 +#: netbox/netbox/forms/mixins.py:62 #, python-brace-format msgid "{class_name} must specify a model class." msgstr "" -#: netbox/forms/mixins.py:152 +#: netbox/netbox/forms/mixins.py:152 msgid "Owner group" msgstr "" -#: netbox/forms/mixins.py:178 netbox/tables/tables.py:307 -#: netbox/tables/tables.py:322 netbox/tables/tables.py:337 -#: users/forms/model_forms.py:535 +#: netbox/netbox/forms/mixins.py:178 netbox/netbox/tables/tables.py:307 +#: netbox/netbox/tables/tables.py:322 netbox/netbox/tables/tables.py:337 +#: netbox/users/forms/model_forms.py:526 msgid "Owner Group" msgstr "" -#: netbox/forms/search.py:10 +#: netbox/netbox/forms/search.py:10 msgid "Partial match" msgstr "" -#: netbox/forms/search.py:11 +#: netbox/netbox/forms/search.py:11 msgid "Exact match" msgstr "" -#: netbox/forms/search.py:12 +#: netbox/netbox/forms/search.py:12 msgid "Starts with" msgstr "" -#: netbox/forms/search.py:13 +#: netbox/netbox/forms/search.py:13 msgid "Ends with" msgstr "" -#: netbox/forms/search.py:14 +#: netbox/netbox/forms/search.py:14 msgid "Regex" msgstr "" -#: netbox/forms/search.py:32 +#: netbox/netbox/forms/search.py:32 msgid "Object type(s)" msgstr "" -#: netbox/forms/search.py:38 +#: netbox/netbox/forms/search.py:38 msgid "Lookup" msgstr "" -#: netbox/models/features.py:312 +#: netbox/netbox/models/features.py:312 #, python-brace-format msgid "Invalid value for custom field '{name}': {error}" msgstr "" -#: netbox/models/features.py:321 +#: netbox/netbox/models/features.py:321 #, python-brace-format msgid "Custom field '{name}' must have a unique value." msgstr "" -#: netbox/models/features.py:328 +#: netbox/netbox/models/features.py:328 #, python-brace-format msgid "Missing required custom field '{name}'." msgstr "" -#: netbox/models/features.py:522 +#: netbox/netbox/models/features.py:522 msgid "Remote data source" msgstr "" -#: netbox/models/features.py:532 +#: netbox/netbox/models/features.py:532 msgid "data path" msgstr "" -#: netbox/models/features.py:536 +#: netbox/netbox/models/features.py:536 msgid "Path to remote file (relative to data source root)" msgstr "" -#: netbox/models/features.py:539 +#: netbox/netbox/models/features.py:539 msgid "auto sync enabled" msgstr "" -#: netbox/models/features.py:541 +#: netbox/netbox/models/features.py:541 msgid "Enable automatic synchronization of data when the data file is updated" msgstr "" -#: netbox/models/features.py:544 +#: netbox/netbox/models/features.py:544 msgid "date synced" msgstr "" -#: netbox/models/features.py:637 +#: netbox/netbox/models/features.py:637 #, python-brace-format msgid "{class_name} must implement a sync_data() method." msgstr "" -#: netbox/models/mixins.py:39 +#: netbox/netbox/models/mixins.py:39 msgid "weight unit" msgstr "" -#: netbox/models/mixins.py:69 +#: netbox/netbox/models/mixins.py:69 msgid "Must specify a unit when setting a weight" msgstr "" -#: netbox/models/mixins.py:74 +#: netbox/netbox/models/mixins.py:74 msgid "distance" msgstr "" -#: netbox/models/mixins.py:81 +#: netbox/netbox/models/mixins.py:81 msgid "distance unit" msgstr "" -#: netbox/models/mixins.py:116 +#: netbox/netbox/models/mixins.py:116 msgid "Must specify a unit when setting a distance" msgstr "" -#: netbox/navigation/menu.py:14 +#: netbox/netbox/navigation/menu.py:14 msgid "Organization" msgstr "" -#: netbox/navigation/menu.py:21 +#: netbox/netbox/navigation/menu.py:21 msgid "Site Groups" msgstr "" -#: netbox/navigation/menu.py:30 +#: netbox/netbox/navigation/menu.py:30 msgid "Tenant Groups" msgstr "" -#: netbox/navigation/menu.py:37 +#: netbox/netbox/navigation/menu.py:37 msgid "Contact Groups" msgstr "" -#: netbox/navigation/menu.py:38 +#: netbox/netbox/navigation/menu.py:38 msgid "Contact Roles" msgstr "" -#: netbox/navigation/menu.py:39 +#: netbox/netbox/navigation/menu.py:39 msgid "Contact Assignments" msgstr "" -#: netbox/navigation/menu.py:56 +#: netbox/netbox/navigation/menu.py:56 msgid "Elevations" msgstr "" -#: netbox/navigation/menu.py:62 +#: netbox/netbox/navigation/menu.py:62 msgid "Rack Organization" msgstr "" -#: netbox/navigation/menu.py:64 +#: netbox/netbox/navigation/menu.py:64 msgid "Rack Groups" msgstr "" -#: netbox/navigation/menu.py:65 +#: netbox/netbox/navigation/menu.py:65 msgid "Rack Roles" msgstr "" -#: netbox/navigation/menu.py:85 +#: netbox/netbox/navigation/menu.py:85 msgid "Modules" msgstr "" -#: netbox/navigation/menu.py:97 +#: netbox/netbox/navigation/menu.py:97 msgid "Module Type Profiles" msgstr "" -#: netbox/navigation/menu.py:98 +#: netbox/netbox/navigation/menu.py:98 msgid "Manufacturers" msgstr "" -#: netbox/navigation/menu.py:102 +#: netbox/netbox/navigation/menu.py:102 msgid "Device Components" msgstr "" -#: netbox/navigation/menu.py:114 +#: netbox/netbox/navigation/menu.py:114 msgid "Inventory Item Roles" msgstr "" -#: netbox/navigation/menu.py:127 netbox/navigation/menu.py:131 -#: templates/dcim/panels/interface_virtual_circuit.html:23 +#: netbox/netbox/navigation/menu.py:127 netbox/netbox/navigation/menu.py:131 +#: netbox/templates/dcim/panels/interface_virtual_circuit.html:23 msgid "Connections" msgstr "" -#: netbox/navigation/menu.py:134 templates/dcim/cablebundle.html:7 +#: netbox/netbox/navigation/menu.py:134 +#: netbox/templates/dcim/cablebundle.html:7 msgid "Cable Bundles" msgstr "" -#: netbox/navigation/menu.py:135 +#: netbox/netbox/navigation/menu.py:135 msgid "Wireless Links" msgstr "" -#: netbox/navigation/menu.py:138 +#: netbox/netbox/navigation/menu.py:138 msgid "Interface Connections" msgstr "" -#: netbox/navigation/menu.py:143 +#: netbox/netbox/navigation/menu.py:143 msgid "Console Connections" msgstr "" -#: netbox/navigation/menu.py:148 +#: netbox/netbox/navigation/menu.py:148 msgid "Power Connections" msgstr "" -#: netbox/navigation/menu.py:164 +#: netbox/netbox/navigation/menu.py:164 msgid "Wireless LAN Groups" msgstr "" -#: netbox/navigation/menu.py:185 +#: netbox/netbox/navigation/menu.py:185 msgid "Prefix & VLAN Roles" msgstr "" -#: netbox/navigation/menu.py:191 +#: netbox/netbox/navigation/menu.py:191 msgid "ASN Ranges" msgstr "" -#: netbox/navigation/menu.py:214 +#: netbox/netbox/navigation/menu.py:214 msgid "VLAN Translation Policies" msgstr "" -#: netbox/navigation/menu.py:215 +#: netbox/netbox/navigation/menu.py:215 msgid "VLAN Translation Rules" msgstr "" -#: netbox/navigation/menu.py:222 +#: netbox/netbox/navigation/menu.py:222 msgid "Application Service Templates" msgstr "" -#: netbox/navigation/menu.py:230 +#: netbox/netbox/navigation/menu.py:230 msgid "VPN" msgstr "" -#: netbox/navigation/menu.py:234 netbox/navigation/menu.py:236 -#: vpn/tables/tunnels.py:24 +#: netbox/netbox/navigation/menu.py:234 netbox/netbox/navigation/menu.py:236 +#: netbox/vpn/tables/tunnels.py:24 msgid "Tunnels" msgstr "" -#: netbox/navigation/menu.py:237 +#: netbox/netbox/navigation/menu.py:237 msgid "Tunnel Groups" msgstr "" -#: netbox/navigation/menu.py:238 +#: netbox/netbox/navigation/menu.py:238 msgid "Tunnel Terminations" msgstr "" -#: netbox/navigation/menu.py:242 netbox/navigation/menu.py:244 -#: vpn/models/l2vpn.py:69 +#: netbox/netbox/navigation/menu.py:242 netbox/netbox/navigation/menu.py:244 +#: netbox/vpn/models/l2vpn.py:69 msgid "L2VPNs" msgstr "" -#: netbox/navigation/menu.py:245 +#: netbox/netbox/navigation/menu.py:245 msgid "L2VPN Terminations" msgstr "" -#: netbox/navigation/menu.py:251 +#: netbox/netbox/navigation/menu.py:251 msgid "IKE Proposals" msgstr "" -#: netbox/navigation/menu.py:252 vpn/views.py:296 +#: netbox/netbox/navigation/menu.py:252 netbox/vpn/views.py:296 msgid "IKE Policies" msgstr "" -#: netbox/navigation/menu.py:253 +#: netbox/netbox/navigation/menu.py:253 msgid "IPSec Proposals" msgstr "" -#: netbox/navigation/menu.py:254 vpn/views.py:450 +#: netbox/netbox/navigation/menu.py:254 netbox/vpn/views.py:450 msgid "IPSec Policies" msgstr "" -#: netbox/navigation/menu.py:255 +#: netbox/netbox/navigation/menu.py:255 msgid "IPSec Profiles" msgstr "" -#: netbox/navigation/menu.py:270 -#: templates/virtualization/buttons/bulk_add_components.html:17 -#: templates/virtualization/virtualmachine/base.html:32 -#: virtualization/tables/virtualmachines.py:111 virtualization/views.py:554 +#: netbox/netbox/navigation/menu.py:270 +#: netbox/templates/virtualization/buttons/bulk_add_components.html:17 +#: netbox/templates/virtualization/virtualmachine/base.html:32 +#: netbox/virtualization/tables/virtualmachines.py:111 +#: netbox/virtualization/views.py:554 msgid "Virtual Disks" msgstr "" -#: netbox/navigation/menu.py:271 +#: netbox/netbox/navigation/menu.py:271 msgid "Virtual Machine Types" msgstr "" -#: netbox/navigation/menu.py:278 +#: netbox/netbox/navigation/menu.py:278 msgid "Cluster Types" msgstr "" -#: netbox/navigation/menu.py:279 +#: netbox/netbox/navigation/menu.py:279 msgid "Cluster Groups" msgstr "" -#: netbox/navigation/menu.py:293 +#: netbox/netbox/navigation/menu.py:293 msgid "Circuit Types" msgstr "" -#: netbox/navigation/menu.py:294 +#: netbox/netbox/navigation/menu.py:294 msgid "Circuit Terminations" msgstr "" -#: netbox/navigation/menu.py:298 netbox/navigation/menu.py:300 +#: netbox/netbox/navigation/menu.py:298 netbox/netbox/navigation/menu.py:300 msgid "Virtual Circuits" msgstr "" -#: netbox/navigation/menu.py:301 +#: netbox/netbox/navigation/menu.py:301 msgid "Virtual Circuit Types" msgstr "" -#: netbox/navigation/menu.py:302 +#: netbox/netbox/navigation/menu.py:302 msgid "Virtual Circuit Terminations" msgstr "" -#: netbox/navigation/menu.py:308 +#: netbox/netbox/navigation/menu.py:308 msgid "Circuit Groups" msgstr "" -#: netbox/navigation/menu.py:313 netbox/navigation/menu.py:315 +#: netbox/netbox/navigation/menu.py:313 netbox/netbox/navigation/menu.py:315 msgid "Providers" msgstr "" -#: netbox/navigation/menu.py:316 +#: netbox/netbox/navigation/menu.py:316 msgid "Provider Accounts" msgstr "" -#: netbox/navigation/menu.py:317 +#: netbox/netbox/navigation/menu.py:317 msgid "Provider Networks" msgstr "" -#: netbox/navigation/menu.py:331 +#: netbox/netbox/navigation/menu.py:331 msgid "Power Panels" msgstr "" -#: netbox/navigation/menu.py:342 +#: netbox/netbox/navigation/menu.py:342 msgid "Configurations" msgstr "" -#: netbox/navigation/menu.py:344 +#: netbox/netbox/navigation/menu.py:344 msgid "Config Contexts" msgstr "" -#: netbox/navigation/menu.py:345 +#: netbox/netbox/navigation/menu.py:345 msgid "Config Context Profiles" msgstr "" -#: netbox/navigation/menu.py:346 +#: netbox/netbox/navigation/menu.py:346 msgid "Config Templates" msgstr "" -#: netbox/navigation/menu.py:353 netbox/navigation/menu.py:357 +#: netbox/netbox/navigation/menu.py:353 netbox/netbox/navigation/menu.py:357 msgid "Customization" msgstr "" -#: netbox/navigation/menu.py:360 +#: netbox/netbox/navigation/menu.py:360 msgid "Custom Field Choices" msgstr "" -#: netbox/navigation/menu.py:361 +#: netbox/netbox/navigation/menu.py:361 msgid "Custom Links" msgstr "" -#: netbox/navigation/menu.py:362 +#: netbox/netbox/navigation/menu.py:362 msgid "Export Templates" msgstr "" -#: netbox/navigation/menu.py:363 +#: netbox/netbox/navigation/menu.py:363 msgid "Saved Filters" msgstr "" -#: netbox/navigation/menu.py:364 +#: netbox/netbox/navigation/menu.py:364 msgid "Table Configs" msgstr "" -#: netbox/navigation/menu.py:366 +#: netbox/netbox/navigation/menu.py:366 msgid "Image Attachments" msgstr "" -#: netbox/navigation/menu.py:384 +#: netbox/netbox/navigation/menu.py:384 msgid "Operations" msgstr "" -#: netbox/navigation/menu.py:388 +#: netbox/netbox/navigation/menu.py:388 msgid "Integrations" msgstr "" -#: netbox/navigation/menu.py:390 +#: netbox/netbox/navigation/menu.py:390 msgid "Data Sources" msgstr "" -#: netbox/navigation/menu.py:391 +#: netbox/netbox/navigation/menu.py:391 msgid "Event Rules" msgstr "" -#: netbox/navigation/menu.py:392 +#: netbox/netbox/navigation/menu.py:392 msgid "Webhooks" msgstr "" -#: netbox/navigation/menu.py:396 netbox/navigation/menu.py:400 -#: netbox/views/generic/feature_views.py:185 -#: templates/extras/report/base.html:37 templates/extras/script/base.html:36 +#: netbox/netbox/navigation/menu.py:396 netbox/netbox/navigation/menu.py:400 +#: netbox/netbox/views/generic/feature_views.py:185 +#: netbox/templates/extras/report/base.html:37 +#: netbox/templates/extras/script/base.html:36 msgid "Jobs" msgstr "" -#: netbox/navigation/menu.py:406 +#: netbox/netbox/navigation/menu.py:406 msgid "Logging" msgstr "" -#: netbox/navigation/menu.py:408 +#: netbox/netbox/navigation/menu.py:408 msgid "Notification Groups" msgstr "" -#: netbox/navigation/menu.py:409 +#: netbox/netbox/navigation/menu.py:409 msgid "Journal Entries" msgstr "" -#: netbox/navigation/menu.py:417 templates/inc/user_menu.html:29 +#: netbox/netbox/navigation/menu.py:417 netbox/templates/inc/user_menu.html:29 msgid "Admin" msgstr "" -#: netbox/navigation/menu.py:425 templates/account/base.html:27 -#: templates/inc/user_menu.html:50 +#: netbox/netbox/navigation/menu.py:425 netbox/templates/account/base.html:27 +#: netbox/templates/inc/user_menu.html:50 msgid "API Tokens" msgstr "" -#: netbox/navigation/menu.py:426 users/forms/model_forms.py:217 -#: users/forms/model_forms.py:225 users/forms/model_forms.py:272 -#: users/forms/model_forms.py:279 +#: netbox/netbox/navigation/menu.py:426 netbox/users/forms/model_forms.py:208 +#: netbox/users/forms/model_forms.py:216 netbox/users/forms/model_forms.py:263 +#: netbox/users/forms/model_forms.py:270 msgid "Permissions" msgstr "" -#: netbox/navigation/menu.py:432 +#: netbox/netbox/navigation/menu.py:432 msgid "Owner Groups" msgstr "" -#: netbox/navigation/menu.py:433 users/tables.py:166 +#: netbox/netbox/navigation/menu.py:433 netbox/users/tables.py:166 msgid "Owners" msgstr "" -#: netbox/navigation/menu.py:437 netbox/navigation/menu.py:441 -#: templates/core/system.html:8 +#: netbox/netbox/navigation/menu.py:437 netbox/netbox/navigation/menu.py:441 +#: netbox/templates/core/system.html:8 msgid "System" msgstr "" -#: netbox/navigation/menu.py:446 netbox/navigation/menu.py:501 -#: templates/500.html:35 templates/account/preferences.html:22 -#: templates/core/plugin.html:13 templates/core/plugin_list.html:7 -#: templates/core/plugin_list.html:12 templates/core/system.html:30 +#: netbox/netbox/navigation/menu.py:446 netbox/netbox/navigation/menu.py:501 +#: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 +#: netbox/templates/core/plugin.html:13 +#: netbox/templates/core/plugin_list.html:7 +#: netbox/templates/core/plugin_list.html:12 +#: netbox/templates/core/system.html:30 msgid "Plugins" msgstr "" -#: netbox/navigation/menu.py:451 +#: netbox/netbox/navigation/menu.py:451 msgid "Configuration History" msgstr "" -#: netbox/navigation/menu.py:457 templates/core/rq_task.html:8 -#: templates/core/rq_task_list.html:22 +#: netbox/netbox/navigation/menu.py:457 netbox/templates/core/rq_task.html:8 +#: netbox/templates/core/rq_task_list.html:22 msgid "Background Tasks" msgstr "" -#: netbox/object_actions.py:88 netbox/ui/actions.py:129 -#: templates/circuits/inc/circuit_termination.html:10 -#: templates/circuits/panels/circuit_circuit_termination.html:10 -#: templates/dcim/manufacturer.html:8 templates/extras/tableconfig_edit.html:29 -#: templates/generic/bulk_add_component.html:22 users/ui/panels.py:57 -#: utilities/templates/helpers/table_config_form.html:20 -#: utilities/templates/widgets/splitmultiselect.html:11 -#: utilities/templatetags/buttons.py:175 +#: netbox/netbox/object_actions.py:88 netbox/netbox/ui/actions.py:133 +#: netbox/templates/circuits/inc/circuit_termination.html:10 +#: netbox/templates/circuits/panels/circuit_circuit_termination.html:10 +#: netbox/templates/dcim/manufacturer.html:8 +#: netbox/templates/extras/tableconfig_edit.html:29 +#: netbox/templates/generic/bulk_add_component.html:22 +#: netbox/users/ui/panels.py:57 +#: netbox/utilities/templates/helpers/table_config_form.html:20 +#: netbox/utilities/templates/widgets/splitmultiselect.html:11 +#: netbox/utilities/templatetags/buttons.py:175 msgid "Add" msgstr "" -#: netbox/object_actions.py:98 utilities/templates/buttons/clone.html:4 +#: netbox/netbox/object_actions.py:98 +#: netbox/utilities/templates/buttons/clone.html:4 msgid "Clone" msgstr "" -#: netbox/object_actions.py:114 -#: templates/circuits/circuit_termination/attrs/connection.html:25 -#: templates/circuits/inc/circuit_termination.html:15 -#: templates/circuits/inc/circuit_termination_fields.html:37 -#: templates/circuits/panels/circuit_circuit_termination.html:15 -#: templates/dcim/inc/panels/inventory_items.html:32 -#: templates/dcim/panels/component_inventory_items.html:22 -#: templates/extras/inc/script_list_content.html:16 -#: templates/generic/object_edit.html:47 -#: templates/ipam/inc/ipaddress_edit_header.html:7 -#: templates/ipam/inc/panels/fhrp_groups.html:43 -#: templates/ipam/panels/fhrp_groups.html:29 -#: utilities/templatetags/buttons.py:135 +#: netbox/netbox/object_actions.py:114 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:25 +#: netbox/templates/circuits/inc/circuit_termination.html:15 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:37 +#: netbox/templates/circuits/panels/circuit_circuit_termination.html:15 +#: netbox/templates/dcim/inc/panels/inventory_items.html:32 +#: netbox/templates/dcim/panels/component_inventory_items.html:22 +#: netbox/templates/extras/inc/script_list_content.html:16 +#: netbox/templates/generic/object_edit.html:47 +#: netbox/templates/ipam/inc/ipaddress_edit_header.html:7 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:43 +#: netbox/templates/ipam/panels/fhrp_groups.html:29 +#: netbox/utilities/templatetags/buttons.py:135 msgid "Edit" msgstr "" -#: netbox/object_actions.py:125 -#: templates/circuits/inc/circuit_termination.html:20 -#: templates/circuits/panels/circuit_circuit_termination.html:20 -#: templates/dcim/inc/panels/inventory_items.html:37 -#: templates/dcim/panels/component_inventory_items.html:27 -#: templates/extras/inc/script_list_content.html:21 -#: templates/generic/bulk_delete.html:21 templates/generic/bulk_delete.html:79 -#: templates/generic/object_delete.html:19 templates/htmx/delete_form.html:70 -#: templates/ipam/inc/panels/fhrp_groups.html:48 -#: templates/ipam/panels/fhrp_groups.html:34 users/ui/panels.py:59 -#: utilities/templatetags/buttons.py:146 +#: netbox/netbox/object_actions.py:125 +#: netbox/templates/circuits/inc/circuit_termination.html:20 +#: netbox/templates/circuits/panels/circuit_circuit_termination.html:20 +#: netbox/templates/dcim/inc/panels/inventory_items.html:37 +#: netbox/templates/dcim/panels/component_inventory_items.html:27 +#: netbox/templates/extras/inc/script_list_content.html:21 +#: netbox/templates/generic/bulk_delete.html:21 +#: netbox/templates/generic/bulk_delete.html:79 +#: netbox/templates/generic/object_delete.html:19 +#: netbox/templates/htmx/delete_form.html:70 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:48 +#: netbox/templates/ipam/panels/fhrp_groups.html:34 +#: netbox/users/ui/panels.py:59 netbox/utilities/templatetags/buttons.py:146 msgid "Delete" msgstr "" -#: netbox/object_actions.py:136 utilities/templatetags/buttons.py:190 +#: netbox/netbox/object_actions.py:136 +#: netbox/utilities/templatetags/buttons.py:190 msgid "Import" msgstr "" -#: netbox/object_actions.py:146 utilities/templatetags/buttons.py:207 +#: netbox/netbox/object_actions.py:146 +#: netbox/utilities/templatetags/buttons.py:207 msgid "Export" msgstr "" -#: netbox/object_actions.py:174 utilities/templatetags/buttons.py:227 +#: netbox/netbox/object_actions.py:174 +#: netbox/utilities/templatetags/buttons.py:227 msgid "Edit Selected" msgstr "" -#: netbox/object_actions.py:200 +#: netbox/netbox/object_actions.py:200 msgid "Rename Selected" msgstr "" -#: netbox/object_actions.py:211 utilities/templatetags/buttons.py:243 +#: netbox/netbox/object_actions.py:211 +#: netbox/utilities/templatetags/buttons.py:243 msgid "Delete Selected" msgstr "" -#: netbox/plugins/navigation.py:53 netbox/plugins/navigation.py:89 +#: netbox/netbox/plugins/navigation.py:53 +#: netbox/netbox/plugins/navigation.py:89 msgid "Permissions must be passed as a tuple or list." msgstr "" -#: netbox/plugins/navigation.py:59 +#: netbox/netbox/plugins/navigation.py:59 msgid "Buttons must be passed as a tuple or list." msgstr "" -#: netbox/plugins/navigation.py:95 +#: netbox/netbox/plugins/navigation.py:95 msgid "Button color must be a choice within ButtonColorChoices." msgstr "" -#: netbox/plugins/registration.py:27 +#: netbox/netbox/plugins/registration.py:27 #, python-brace-format msgid "" "PluginTemplateExtension class {template_extension} was passed as an instance!" msgstr "" -#: netbox/plugins/registration.py:33 +#: netbox/netbox/plugins/registration.py:33 #, python-brace-format msgid "" "{template_extension} is not a subclass of netbox.plugins." "PluginTemplateExtension!" msgstr "" -#: netbox/plugins/registration.py:50 +#: netbox/netbox/plugins/registration.py:50 #, python-brace-format msgid "{item} must be an instance of netbox.plugins.PluginMenuItem" msgstr "" -#: netbox/plugins/registration.py:61 +#: netbox/netbox/plugins/registration.py:61 #, python-brace-format msgid "{menu_link} must be an instance of netbox.plugins.PluginMenuItem" msgstr "" -#: netbox/plugins/registration.py:66 +#: netbox/netbox/plugins/registration.py:66 #, python-brace-format msgid "{button} must be an instance of netbox.plugins.PluginMenuButton" msgstr "" -#: netbox/plugins/templates.py:42 +#: netbox/netbox/plugins/templates.py:42 msgid "extra_context must be a dictionary" msgstr "" -#: netbox/preferences.py:30 +#: netbox/netbox/preferences.py:30 msgid "Language" msgstr "" -#: netbox/preferences.py:35 +#: netbox/netbox/preferences.py:35 msgid "Forces UI translation to the specified language" msgstr "" -#: netbox/preferences.py:37 +#: netbox/netbox/preferences.py:37 msgid "Support for translation has been disabled locally" msgstr "" -#: netbox/preferences.py:43 +#: netbox/netbox/preferences.py:43 msgid "NetBox Copilot" msgstr "" -#: netbox/preferences.py:48 +#: netbox/netbox/preferences.py:48 msgid "Enable the NetBox Copilot AI agent" msgstr "" -#: netbox/preferences.py:52 +#: netbox/netbox/preferences.py:52 msgid "Page length" msgstr "" -#: netbox/preferences.py:54 +#: netbox/netbox/preferences.py:54 msgid "The default number of objects to display per page" msgstr "" -#: netbox/preferences.py:58 +#: netbox/netbox/preferences.py:58 msgid "Paginator placement" msgstr "" -#: netbox/preferences.py:60 +#: netbox/netbox/preferences.py:60 msgid "Bottom" msgstr "" -#: netbox/preferences.py:61 +#: netbox/netbox/preferences.py:61 msgid "Top" msgstr "" -#: netbox/preferences.py:62 +#: netbox/netbox/preferences.py:62 msgid "Both" msgstr "" -#: netbox/preferences.py:65 +#: netbox/netbox/preferences.py:65 msgid "Where the paginator controls will be displayed relative to a table" msgstr "" -#: netbox/preferences.py:68 +#: netbox/netbox/preferences.py:68 msgid "Striped table rows" msgstr "" -#: netbox/preferences.py:73 +#: netbox/netbox/preferences.py:73 msgid "Render table rows with alternating colors to increase readability" msgstr "" -#: netbox/preferences.py:78 +#: netbox/netbox/preferences.py:78 msgid "Data format" msgstr "" -#: netbox/preferences.py:83 +#: netbox/netbox/preferences.py:83 msgid "The preferred syntax for displaying generic data within the UI" msgstr "" -#: netbox/preferences.py:86 utilities/forms/bulk_import.py:38 +#: netbox/netbox/preferences.py:86 netbox/utilities/forms/bulk_import.py:38 msgid "CSV delimiter" msgstr "" -#: netbox/preferences.py:89 +#: netbox/netbox/preferences.py:89 msgid "The character used to separate fields in CSV data" msgstr "" -#: netbox/registry.py:24 +#: netbox/netbox/registry.py:24 #, python-brace-format msgid "Invalid store: {key}" msgstr "" -#: netbox/registry.py:27 +#: netbox/netbox/registry.py:27 msgid "Cannot add stores to registry after initialization" msgstr "" -#: netbox/registry.py:30 +#: netbox/netbox/registry.py:30 msgid "Cannot delete stores from registry" msgstr "" -#: netbox/settings.py:859 +#: netbox/netbox/settings.py:859 msgid "Czech" msgstr "" -#: netbox/settings.py:860 +#: netbox/netbox/settings.py:860 msgid "Danish" msgstr "" -#: netbox/settings.py:861 +#: netbox/netbox/settings.py:861 msgid "German" msgstr "" -#: netbox/settings.py:862 +#: netbox/netbox/settings.py:862 msgid "English" msgstr "" -#: netbox/settings.py:863 +#: netbox/netbox/settings.py:863 msgid "Spanish" msgstr "" -#: netbox/settings.py:864 +#: netbox/netbox/settings.py:864 msgid "French" msgstr "" -#: netbox/settings.py:865 +#: netbox/netbox/settings.py:865 msgid "Italian" msgstr "" -#: netbox/settings.py:866 +#: netbox/netbox/settings.py:866 msgid "Japanese" msgstr "" -#: netbox/settings.py:867 +#: netbox/netbox/settings.py:867 msgid "Latvian" msgstr "" -#: netbox/settings.py:868 +#: netbox/netbox/settings.py:868 msgid "Dutch" msgstr "" -#: netbox/settings.py:869 +#: netbox/netbox/settings.py:869 msgid "Polish" msgstr "" -#: netbox/settings.py:870 +#: netbox/netbox/settings.py:870 msgid "Portuguese" msgstr "" -#: netbox/settings.py:871 +#: netbox/netbox/settings.py:871 msgid "Russian" msgstr "" -#: netbox/settings.py:872 +#: netbox/netbox/settings.py:872 msgid "Turkish" msgstr "" -#: netbox/settings.py:873 +#: netbox/netbox/settings.py:873 msgid "Ukrainian" msgstr "" -#: netbox/settings.py:874 +#: netbox/netbox/settings.py:874 msgid "Chinese" msgstr "" -#: netbox/tables/columns.py:183 +#: netbox/netbox/tables/columns.py:183 msgid "Select all" msgstr "" -#: netbox/tables/columns.py:196 +#: netbox/netbox/tables/columns.py:196 msgid "Toggle all" msgstr "" -#: netbox/tables/columns.py:316 templates/inc/table_controls_htmx.html:35 +#: netbox/netbox/tables/columns.py:316 +#: netbox/templates/inc/table_controls_htmx.html:35 msgid "Toggle Dropdown" msgstr "" -#: netbox/tables/tables.py:62 +#: netbox/netbox/tables/tables.py:62 #, python-brace-format msgid "No {model_name} found" msgstr "" -#: netbox/tables/tables.py:367 templates/generic/bulk_import.html:148 +#: netbox/netbox/tables/tables.py:367 +#: netbox/templates/generic/bulk_import.html:148 msgid "Field" msgstr "" -#: netbox/tables/tables.py:370 -#: templates/extras/panels/customfieldchoiceset_choices.html:9 +#: netbox/netbox/tables/tables.py:370 +#: netbox/templates/extras/panels/customfieldchoiceset_choices.html:9 msgid "Value" msgstr "" -#: netbox/tests/dummy_plugin/navigation.py:29 +#: netbox/netbox/tests/dummy_plugin/navigation.py:29 msgid "Dummy Plugin" msgstr "" -#: netbox/ui/actions.py:146 +#: netbox/netbox/ui/actions.py:150 +#: netbox/templates/users/inc/new_token_banner.html:19 msgid "Copy" msgstr "" -#: netbox/ui/attrs.py:251 +#: netbox/netbox/ui/attrs.py:251 #, python-brace-format msgid "" "Invalid decoding option: {decoding}! Must be one of {image_decoding_choices}" msgstr "" -#: netbox/ui/attrs.py:316 +#: netbox/netbox/ui/attrs.py:316 #, python-brace-format msgid "" "Invalid max_items value: {max_items}! Must be a positive integer or None." msgstr "" -#: netbox/ui/attrs.py:461 +#: netbox/netbox/ui/attrs.py:461 msgid "GPS coordinates" msgstr "" -#: netbox/views/generic/bulk_views.py:138 +#: netbox/netbox/views/generic/bulk_views.py:138 #, python-brace-format msgid "" "There was an error rendering the selected export template ({template}): " "{error}" msgstr "" -#: netbox/views/generic/bulk_views.py:418 +#: netbox/netbox/views/generic/bulk_views.py:418 msgid "Must be a list." msgstr "" -#: netbox/views/generic/bulk_views.py:428 +#: netbox/netbox/views/generic/bulk_views.py:428 msgid "Must be a dictionary." msgstr "" -#: netbox/views/generic/bulk_views.py:485 +#: netbox/netbox/views/generic/bulk_views.py:485 #, python-brace-format msgid "Object with ID {id} does not exist" msgstr "" -#: netbox/views/generic/bulk_views.py:548 +#: netbox/netbox/views/generic/bulk_views.py:548 #, python-brace-format msgid "" "Duplicate objects found: {model} with ID(s) {ids} appears multiple times" msgstr "" -#: netbox/views/generic/bulk_views.py:600 +#: netbox/netbox/views/generic/bulk_views.py:600 #, python-brace-format msgid "Bulk import {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:616 +#: netbox/netbox/views/generic/bulk_views.py:616 #, python-brace-format msgid "Imported {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:806 +#: netbox/netbox/views/generic/bulk_views.py:806 #, python-brace-format msgid "Bulk edit {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:822 +#: netbox/netbox/views/generic/bulk_views.py:822 #, python-brace-format msgid "Updated {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:855 -#: netbox/views/generic/bulk_views.py:1096 -#: netbox/views/generic/bulk_views.py:1144 +#: netbox/netbox/views/generic/bulk_views.py:855 +#: netbox/netbox/views/generic/bulk_views.py:1096 +#: netbox/netbox/views/generic/bulk_views.py:1144 #, python-brace-format msgid "No {object_type} were selected." msgstr "" -#: netbox/views/generic/bulk_views.py:955 +#: netbox/netbox/views/generic/bulk_views.py:955 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:1025 +#: netbox/netbox/views/generic/bulk_views.py:1025 #, python-brace-format msgid "Bulk delete {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:1052 +#: netbox/netbox/views/generic/bulk_views.py:1052 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:1069 +#: netbox/netbox/views/generic/bulk_views.py:1069 msgid "Deletion failed due to the presence of one or more dependent objects." msgstr "" -#: netbox/views/generic/bulk_views.py:1157 +#: netbox/netbox/views/generic/bulk_views.py:1157 #, python-brace-format msgid "Bulk add {count} {object_type}" msgstr "" -#: netbox/views/generic/bulk_views.py:1210 +#: netbox/netbox/views/generic/bulk_views.py:1210 msgid "An integrity error occurred while creating components" msgstr "" -#: netbox/views/generic/bulk_views.py:1222 +#: netbox/netbox/views/generic/bulk_views.py:1222 #, python-brace-format msgid "Added {count} {component} to {parent_count} {parent}." msgstr "" -#: netbox/views/generic/feature_views.py:48 +#: netbox/netbox/views/generic/feature_views.py:48 msgid "Changelog" msgstr "" -#: netbox/views/generic/feature_views.py:125 +#: netbox/netbox/views/generic/feature_views.py:125 msgid "Journal" msgstr "" -#: netbox/views/generic/feature_views.py:230 +#: netbox/netbox/views/generic/feature_views.py:230 msgid "Unable to synchronize data: No data file set." msgstr "" -#: netbox/views/generic/feature_views.py:234 +#: netbox/netbox/views/generic/feature_views.py:234 #, python-brace-format msgid "Synchronized data for {object_type} {object}." msgstr "" -#: netbox/views/generic/feature_views.py:259 +#: netbox/netbox/views/generic/feature_views.py:259 #, python-brace-format msgid "Synced {count} {object_type}" msgstr "" -#: netbox/views/generic/object_views.py:118 +#: netbox/netbox/views/generic/object_views.py:118 #, python-brace-format msgid "{class_name} must implement get_children()" msgstr "" -#: netbox/views/misc.py:49 +#: netbox/netbox/views/misc.py:49 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." msgstr "" -#: templates/403.html:4 +#: netbox/templates/403.html:4 msgid "Access Denied" msgstr "" -#: templates/403.html:9 +#: netbox/templates/403.html:9 msgid "You do not have permission to access this page" msgstr "" -#: templates/404.html:4 +#: netbox/templates/404.html:4 msgid "Page Not Found" msgstr "" -#: templates/404.html:9 +#: netbox/templates/404.html:9 msgid "The requested page does not exist" msgstr "" -#: templates/500.html:7 templates/500.html:18 +#: netbox/templates/500.html:7 netbox/templates/500.html:18 msgid "Server Error" msgstr "" -#: templates/500.html:23 +#: netbox/templates/500.html:23 msgid "There was a problem with your request. Please contact an administrator" msgstr "" -#: templates/500.html:28 +#: netbox/templates/500.html:28 msgid "The complete exception is provided below" msgstr "" -#: templates/500.html:33 templates/core/system.html:68 +#: netbox/templates/500.html:33 netbox/templates/core/system.html:68 msgid "Python version" msgstr "" -#: templates/500.html:34 +#: netbox/templates/500.html:34 msgid "NetBox version" msgstr "" -#: templates/500.html:36 +#: netbox/templates/500.html:36 msgid "None installed" msgstr "" -#: templates/500.html:39 +#: netbox/templates/500.html:39 msgid "The request which yielded the above error is shown below:" msgstr "" -#: templates/500.html:45 +#: netbox/templates/500.html:45 msgid "If further assistance is required, please post to the" msgstr "" -#: templates/500.html:45 +#: netbox/templates/500.html:45 msgid "NetBox discussion forum" msgstr "" -#: templates/500.html:45 +#: netbox/templates/500.html:45 msgid "on GitHub" msgstr "" -#: templates/500.html:48 templates/base/40x.html:17 +#: netbox/templates/500.html:48 netbox/templates/base/40x.html:17 msgid "Home Page" msgstr "" -#: templates/account/base.html:16 templates/account/subscriptions.html:7 -#: templates/inc/user_menu.html:44 +#: netbox/templates/account/base.html:16 +#: netbox/templates/account/subscriptions.html:7 +#: netbox/templates/inc/user_menu.html:44 msgid "Subscriptions" msgstr "" -#: templates/account/base.html:19 templates/inc/user_menu.html:47 +#: netbox/templates/account/base.html:19 netbox/templates/inc/user_menu.html:47 msgid "Preferences" msgstr "" -#: templates/account/password.html:5 +#: netbox/templates/account/password.html:5 msgid "Change Password" msgstr "" -#: templates/account/password.html:19 templates/account/preferences.html:79 -#: templates/core/configrevision_restore.html:63 -#: templates/dcim/devicebay_populate.html:34 -#: templates/dcim/virtualchassis_add_member.html:26 -#: templates/dcim/virtualchassis_edit.html:118 -#: templates/extras/object_journal.html:26 templates/extras/script.html:38 -#: templates/generic/bulk_add_component.html:81 -#: templates/generic/bulk_delete.html:78 templates/generic/bulk_edit.html:130 -#: templates/generic/bulk_import.html:66 templates/generic/bulk_import.html:98 -#: templates/generic/bulk_import.html:131 templates/generic/bulk_rename.html:65 -#: templates/generic/confirmation_form.html:19 -#: templates/generic/object_edit.html:74 templates/htmx/delete_form.html:66 -#: templates/htmx/delete_form.html:68 templates/htmx/quick_add.html:21 -#: templates/ipam/ipaddress_assign.html:28 -#: templates/virtualization/cluster_add_devices.html:30 +#: netbox/templates/account/password.html:19 +#: netbox/templates/account/preferences.html:79 +#: netbox/templates/account/usertoken_edit.html:7 +#: netbox/templates/core/configrevision_restore.html:63 +#: netbox/templates/dcim/devicebay_populate.html:34 +#: netbox/templates/dcim/virtualchassis_add_member.html:26 +#: netbox/templates/dcim/virtualchassis_edit.html:118 +#: netbox/templates/extras/object_journal.html:26 +#: netbox/templates/extras/script.html:38 +#: netbox/templates/generic/bulk_add_component.html:81 +#: netbox/templates/generic/bulk_delete.html:78 +#: netbox/templates/generic/bulk_edit.html:130 +#: netbox/templates/generic/bulk_import.html:66 +#: netbox/templates/generic/bulk_import.html:98 +#: netbox/templates/generic/bulk_import.html:131 +#: netbox/templates/generic/bulk_rename.html:65 +#: netbox/templates/generic/confirmation_form.html:19 +#: netbox/templates/generic/object_edit.html:74 +#: netbox/templates/htmx/delete_form.html:66 +#: netbox/templates/htmx/delete_form.html:68 +#: netbox/templates/htmx/quick_add.html:21 +#: netbox/templates/ipam/ipaddress_assign.html:28 +#: netbox/templates/users/token_edit.html:14 +#: netbox/templates/virtualization/cluster_add_devices.html:30 msgid "Cancel" msgstr "" -#: templates/account/password.html:20 templates/account/preferences.html:80 -#: templates/dcim/devicebay_populate.html:35 -#: templates/dcim/virtualchassis_add_member.html:28 -#: templates/dcim/virtualchassis_edit.html:120 -#: templates/extras/dashboard/widget_add.html:26 -#: templates/extras/dashboard/widget_config.html:19 -#: templates/extras/object_journal.html:27 -#: templates/generic/object_edit.html:77 -#: utilities/templates/helpers/applied_filters.html:16 -#: utilities/templates/helpers/table_config_form.html:40 +#: netbox/templates/account/password.html:20 +#: netbox/templates/account/preferences.html:80 +#: netbox/templates/account/usertoken_edit.html:9 +#: netbox/templates/dcim/devicebay_populate.html:35 +#: netbox/templates/dcim/virtualchassis_add_member.html:28 +#: netbox/templates/dcim/virtualchassis_edit.html:120 +#: netbox/templates/extras/dashboard/widget_add.html:26 +#: netbox/templates/extras/dashboard/widget_config.html:19 +#: netbox/templates/extras/object_journal.html:27 +#: netbox/templates/generic/object_edit.html:77 +#: netbox/templates/users/token_edit.html:16 +#: netbox/utilities/templates/helpers/applied_filters.html:16 +#: netbox/utilities/templates/helpers/table_config_form.html:40 msgid "Save" msgstr "" -#: templates/account/preferences.html:34 +#: netbox/templates/account/preferences.html:34 msgid "Table Configurations" msgstr "" -#: templates/account/preferences.html:39 +#: netbox/templates/account/preferences.html:39 msgid "Clear table preferences" msgstr "" -#: templates/account/preferences.html:47 +#: netbox/templates/account/preferences.html:47 msgid "Toggle All" msgstr "" -#: templates/account/preferences.html:49 +#: netbox/templates/account/preferences.html:49 msgid "Table" msgstr "" -#: templates/account/preferences.html:51 -#: templates/core/htmx/system_db_schema.html:18 -#: templates/core/htmx/system_db_schema.html:65 +#: netbox/templates/account/preferences.html:51 +#: netbox/templates/core/htmx/system_db_schema.html:18 +#: netbox/templates/core/htmx/system_db_schema.html:65 msgid "Columns" msgstr "" -#: templates/account/preferences.html:71 templates/core/system.html:119 -#: templates/dcim/cable_trace.html:113 -#: templates/extras/object_configcontext.html:43 +#: netbox/templates/account/preferences.html:71 +#: netbox/templates/core/system.html:119 +#: netbox/templates/dcim/cable_trace.html:113 +#: netbox/templates/extras/object_configcontext.html:43 msgid "None found" msgstr "" -#: templates/account/profile.html:4 +#: netbox/templates/account/profile.html:4 msgid "User Profile" msgstr "" -#: templates/account/profile.html:10 +#: netbox/templates/account/profile.html:10 msgid "Account Details" msgstr "" -#: templates/account/profile.html:27 tenancy/forms/bulk_edit.py:104 -#: tenancy/ui/panels.py:16 +#: netbox/templates/account/profile.html:27 +#: netbox/tenancy/forms/bulk_edit.py:104 netbox/tenancy/ui/panels.py:16 msgid "Email" msgstr "" -#: templates/account/profile.html:31 +#: netbox/templates/account/profile.html:31 msgid "Account Created" msgstr "" -#: templates/account/profile.html:35 +#: netbox/templates/account/profile.html:35 msgid "Last Login" msgstr "" -#: templates/account/profile.html:39 users/ui/panels.py:39 +#: netbox/templates/account/profile.html:39 netbox/users/ui/panels.py:39 msgid "Superuser" msgstr "" -#: templates/account/profile.html:47 users/views.py:104 users/views.py:286 +#: netbox/templates/account/profile.html:47 netbox/users/views.py:118 +#: netbox/users/views.py:300 msgid "Assigned Groups" msgstr "" -#: templates/account/profile.html:52 -#: templates/circuits/inc/circuit_termination.html:65 -#: templates/circuits/panels/circuit_circuit_termination.html:66 -#: templates/core/panels/objectchange_postchange.html:15 -#: templates/core/panels/objectchange_prechange.html:17 -#: templates/dcim/inc/panels/inventory_items.html:45 -#: templates/dcim/panels/component_inventory_items.html:35 -#: templates/dcim/panels/interface_wireless_lans.html:20 -#: templates/dcim/panels/module_type_attributes.html:26 -#: templates/extras/htmx/script_result.html:70 -#: templates/extras/panels/configcontext_assignment.html:14 -#: templates/extras/panels/customfield_related_objects.html:18 -#: templates/inc/panel_table.html:13 templates/inc/panels/comments.html:10 -#: templates/inc/panels/related_objects.html:22 -#: templates/ipam/inc/panels/fhrp_groups.html:56 -#: templates/ipam/panels/fhrp_groups.html:42 -#: templates/ui/panels/comments.html:9 -#: templates/ui/panels/related_objects.html:22 -#: templates/ui/panels/text_code.html:12 -#: templates/users/panels/object_types.html:8 +#: netbox/templates/account/profile.html:52 +#: netbox/templates/circuits/inc/circuit_termination.html:65 +#: netbox/templates/circuits/panels/circuit_circuit_termination.html:66 +#: netbox/templates/core/panels/objectchange_postchange.html:15 +#: netbox/templates/core/panels/objectchange_prechange.html:17 +#: netbox/templates/dcim/inc/panels/inventory_items.html:45 +#: netbox/templates/dcim/panels/component_inventory_items.html:35 +#: netbox/templates/dcim/panels/interface_wireless_lans.html:20 +#: netbox/templates/dcim/panels/module_type_attributes.html:26 +#: netbox/templates/extras/htmx/script_result.html:70 +#: netbox/templates/extras/panels/configcontext_assignment.html:14 +#: netbox/templates/extras/panels/customfield_related_objects.html:18 +#: netbox/templates/inc/panel_table.html:13 +#: netbox/templates/inc/panels/comments.html:10 +#: netbox/templates/inc/panels/related_objects.html:22 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:56 +#: netbox/templates/ipam/panels/fhrp_groups.html:42 +#: netbox/templates/ui/panels/comments.html:9 +#: netbox/templates/ui/panels/related_objects.html:22 +#: netbox/templates/ui/panels/text_code.html:12 +#: netbox/templates/users/panels/object_types.html:8 msgid "None" msgstr "" -#: templates/account/token.html:6 templates/account/token_list.html:6 +#: netbox/templates/account/token.html:6 +#: netbox/templates/account/token_list.html:6 msgid "My API Tokens" msgstr "" -#: templates/account/token_list.html:12 +#: netbox/templates/account/token_list.html:12 msgid "Add a Token" msgstr "" -#: templates/base/base.html:24 templates/home.html:27 +#: netbox/templates/account/usertoken_edit.html:11 +#: netbox/templates/dcim/virtualchassis_edit.html:122 +#: netbox/templates/generic/bulk_add.html:12 +#: netbox/templates/generic/bulk_add_component.html:82 +#: netbox/templates/generic/object_edit.html:47 +#: netbox/templates/generic/object_edit.html:82 +#: netbox/templates/htmx/quick_add.html:24 +#: netbox/templates/ipam/inc/ipaddress_edit_header.html:7 +#: netbox/templates/ipam/inc/prefix_edit_header.html:7 +#: netbox/templates/users/token_edit.html:18 +msgid "Create" +msgstr "" + +#: netbox/templates/base/base.html:24 netbox/templates/home.html:27 msgid "Home" msgstr "" -#: templates/base/layout.html:25 +#: netbox/templates/base/layout.html:25 msgid "NetBox Motif" msgstr "" -#: templates/base/layout.html:38 templates/base/layout.html:39 -#: templates/login.html:14 templates/login.html:15 +#: netbox/templates/base/layout.html:38 netbox/templates/base/layout.html:39 +#: netbox/templates/login.html:14 netbox/templates/login.html:15 msgid "NetBox Logo" msgstr "" -#: templates/base/layout.html:60 templates/base/layout.html:61 +#: netbox/templates/base/layout.html:60 netbox/templates/base/layout.html:61 msgid "Get" msgstr "" -#: templates/base/layout.html:161 templates/base/layout.html:162 +#: netbox/templates/base/layout.html:161 netbox/templates/base/layout.html:162 msgid "Docs" msgstr "" -#: templates/base/layout.html:167 templates/base/layout.html:168 -#: templates/rest_framework/api.html:10 +#: netbox/templates/base/layout.html:167 netbox/templates/base/layout.html:168 +#: netbox/templates/rest_framework/api.html:10 msgid "REST API" msgstr "" -#: templates/base/layout.html:173 templates/base/layout.html:174 +#: netbox/templates/base/layout.html:173 netbox/templates/base/layout.html:174 msgid "REST API documentation" msgstr "" -#: templates/base/layout.html:180 templates/base/layout.html:181 +#: netbox/templates/base/layout.html:180 netbox/templates/base/layout.html:181 msgid "GraphQL API" msgstr "" -#: templates/base/layout.html:196 templates/base/layout.html:197 +#: netbox/templates/base/layout.html:196 netbox/templates/base/layout.html:197 msgid "NetBox Labs Support" msgstr "" -#: templates/base/layout.html:205 templates/base/layout.html:206 +#: netbox/templates/base/layout.html:205 netbox/templates/base/layout.html:206 msgid "Source Code" msgstr "" -#: templates/base/layout.html:211 templates/base/layout.html:212 +#: netbox/templates/base/layout.html:211 netbox/templates/base/layout.html:212 msgid "Community" msgstr "" -#: templates/circuits/circuit_termination/attrs/connection.html:5 -#: templates/circuits/inc/circuit_termination_fields.html:20 -#: templates/dcim/panels/connection.html:8 -#: templates/dcim/panels/interface_connection.html:8 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:5 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:20 +#: netbox/templates/dcim/panels/connection.html:8 +#: netbox/templates/dcim/panels/interface_connection.html:8 msgid "Marked as connected" msgstr "" -#: templates/circuits/circuit_termination/attrs/connection.html:9 -#: templates/circuits/inc/circuit_termination_fields.html:22 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:9 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:22 msgid "to" msgstr "" -#: templates/circuits/circuit_termination/attrs/connection.html:20 -#: templates/circuits/circuit_termination/attrs/connection.html:21 -#: templates/circuits/inc/circuit_termination_fields.html:32 -#: templates/circuits/inc/circuit_termination_fields.html:33 -#: templates/dcim/inc/cable_termination.html:26 -#: templates/dcim/inc/cable_termination.html:48 -#: templates/dcim/inc/cable_termination.html:66 -#: templates/dcim/inc/connection_endpoints.html:7 -#: templates/dcim/panels/connection.html:17 -#: templates/dcim/panels/connection.html:54 -#: templates/dcim/panels/interface_connection.html:16 -#: templates/dcim/panels/interface_connection.html:53 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:20 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:21 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:32 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:33 +#: netbox/templates/dcim/inc/cable_termination.html:26 +#: netbox/templates/dcim/inc/cable_termination.html:48 +#: netbox/templates/dcim/inc/cable_termination.html:66 +#: netbox/templates/dcim/inc/connection_endpoints.html:7 +#: netbox/templates/dcim/panels/connection.html:17 +#: netbox/templates/dcim/panels/connection.html:54 +#: netbox/templates/dcim/panels/interface_connection.html:16 +#: netbox/templates/dcim/panels/interface_connection.html:53 msgid "Trace" msgstr "" -#: templates/circuits/circuit_termination/attrs/connection.html:24 -#: templates/circuits/inc/circuit_termination_fields.html:36 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:24 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:36 msgid "Edit cable" msgstr "" -#: templates/circuits/circuit_termination/attrs/connection.html:29 -#: templates/circuits/inc/circuit_termination_fields.html:41 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:29 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:41 msgid "Remove cable" msgstr "" -#: templates/circuits/circuit_termination/attrs/connection.html:30 -#: templates/circuits/inc/circuit_termination_fields.html:42 -#: templates/dcim/bulk_disconnect.html:5 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:30 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:42 +#: netbox/templates/dcim/bulk_disconnect.html:5 msgid "Disconnect" msgstr "" -#: templates/circuits/circuit_termination/attrs/connection.html:37 -#: templates/circuits/inc/circuit_termination_fields.html:49 -#: templates/dcim/panels/connection.html:78 -#: templates/dcim/panels/connection.html:90 -#: templates/dcim/panels/interface_connection.html:79 -#: templates/dcim/panels/interface_connection.html:99 +#: netbox/templates/circuits/circuit_termination/attrs/connection.html:37 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:49 +#: netbox/templates/dcim/panels/connection.html:78 +#: netbox/templates/dcim/panels/connection.html:90 +#: netbox/templates/dcim/panels/interface_connection.html:79 +#: netbox/templates/dcim/panels/interface_connection.html:99 msgid "Connect" msgstr "" -#: templates/circuits/circuit_termination/attrs/speed.html:3 -#: templates/circuits/inc/circuit_termination_fields.html:67 +#: netbox/templates/circuits/circuit_termination/attrs/speed.html:3 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:67 msgid "Downstream" msgstr "" -#: templates/circuits/circuit_termination/attrs/speed.html:5 -#: templates/circuits/inc/circuit_termination_fields.html:68 +#: netbox/templates/circuits/circuit_termination/attrs/speed.html:5 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:68 msgid "Upstream" msgstr "" -#: templates/circuits/circuitgroup.html:12 +#: netbox/templates/circuits/circuitgroup.html:12 msgid "Assign Circuit" msgstr "" -#: templates/circuits/circuittype.html:7 +#: netbox/templates/circuits/circuittype.html:7 msgid "Add Circuit" msgstr "" -#: templates/circuits/provider.html:11 +#: netbox/templates/circuits/provider.html:11 msgid "Add circuit" msgstr "" -#: templates/circuits/virtualcircuittype.html:7 +#: netbox/templates/circuits/virtualcircuittype.html:7 msgid "Add Virtual Circuit" msgstr "" -#: templates/core/configrevision_restore.html:8 -#: templates/core/configrevision_restore.html:25 -#: templates/core/configrevision_restore.html:64 +#: netbox/templates/core/configrevision_restore.html:8 +#: netbox/templates/core/configrevision_restore.html:25 +#: netbox/templates/core/configrevision_restore.html:64 msgid "Restore" msgstr "" -#: templates/core/configrevision_restore.html:36 +#: netbox/templates/core/configrevision_restore.html:36 msgid "Parameter" msgstr "" -#: templates/core/configrevision_restore.html:37 +#: netbox/templates/core/configrevision_restore.html:37 msgid "Current Value" msgstr "" -#: templates/core/configrevision_restore.html:38 +#: netbox/templates/core/configrevision_restore.html:38 msgid "New Value" msgstr "" -#: templates/core/configrevision_restore.html:50 +#: netbox/templates/core/configrevision_restore.html:50 msgid "Changed" msgstr "" -#: templates/core/datafile/attrs/size.html:1 -#: templates/extras/panels/imageattachment_file.html:20 +#: netbox/templates/core/datafile/attrs/size.html:1 +#: netbox/templates/extras/panels/imageattachment_file.html:20 msgid "bytes" msgstr "" -#: templates/core/htmx/system_db_schema.html:10 +#: netbox/templates/core/htmx/system_db_schema.html:10 msgid "Tables" msgstr "" -#: templates/core/htmx/system_db_schema.html:26 -#: templates/core/htmx/system_db_schema.html:95 +#: netbox/templates/core/htmx/system_db_schema.html:26 +#: netbox/templates/core/htmx/system_db_schema.html:95 msgid "Indexes" msgstr "" -#: templates/core/htmx/system_db_schema.html:39 +#: netbox/templates/core/htmx/system_db_schema.html:39 msgid "plugin" msgstr "" -#: templates/core/htmx/system_db_schema.html:40 +#: netbox/templates/core/htmx/system_db_schema.html:40 msgid "tables" msgstr "" -#: templates/core/htmx/system_db_schema.html:41 -#: templates/core/htmx/system_db_schema.html:56 +#: netbox/templates/core/htmx/system_db_schema.html:41 +#: netbox/templates/core/htmx/system_db_schema.html:56 msgid "indexes" msgstr "" -#: templates/core/htmx/system_db_schema.html:54 +#: netbox/templates/core/htmx/system_db_schema.html:54 msgid "columns" msgstr "" -#: templates/core/htmx/system_db_schema.html:69 +#: netbox/templates/core/htmx/system_db_schema.html:69 msgid "Column" msgstr "" -#: templates/core/htmx/system_db_schema.html:71 +#: netbox/templates/core/htmx/system_db_schema.html:71 msgid "Nullable" msgstr "" -#: templates/core/htmx/system_db_schema.html:82 +#: netbox/templates/core/htmx/system_db_schema.html:82 msgid "yes" msgstr "" -#: templates/core/htmx/system_db_schema.html:84 +#: netbox/templates/core/htmx/system_db_schema.html:84 msgid "no" msgstr "" -#: templates/core/htmx/system_db_schema.html:100 +#: netbox/templates/core/htmx/system_db_schema.html:100 msgid "Definition" msgstr "" -#: templates/core/htmx/system_db_schema.html:125 +#: netbox/templates/core/htmx/system_db_schema.html:125 msgid "Schema information unavailable." msgstr "" -#: templates/core/inc/config_data.html:7 +#: netbox/templates/core/inc/config_data.html:7 msgid "Rack elevations" msgstr "" -#: templates/core/inc/config_data.html:10 +#: netbox/templates/core/inc/config_data.html:10 msgid "Default unit height" msgstr "" -#: templates/core/inc/config_data.html:14 +#: netbox/templates/core/inc/config_data.html:14 msgid "Default unit width" msgstr "" -#: templates/core/inc/config_data.html:20 +#: netbox/templates/core/inc/config_data.html:20 msgid "Power feeds" msgstr "" -#: templates/core/inc/config_data.html:23 +#: netbox/templates/core/inc/config_data.html:23 msgid "Default voltage" msgstr "" -#: templates/core/inc/config_data.html:27 +#: netbox/templates/core/inc/config_data.html:27 msgid "Default amperage" msgstr "" -#: templates/core/inc/config_data.html:31 +#: netbox/templates/core/inc/config_data.html:31 msgid "Default max utilization" msgstr "" -#: templates/core/inc/config_data.html:40 +#: netbox/templates/core/inc/config_data.html:40 msgid "Enforce global unique" msgstr "" -#: templates/core/inc/config_data.html:83 +#: netbox/templates/core/inc/config_data.html:83 msgid "Paginate count" msgstr "" -#: templates/core/inc/config_data.html:87 +#: netbox/templates/core/inc/config_data.html:87 msgid "Max page size" msgstr "" -#: templates/core/inc/config_data.html:114 +#: netbox/templates/core/inc/config_data.html:114 msgid "User preferences" msgstr "" -#: templates/core/inc/config_data.html:127 +#: netbox/templates/core/inc/config_data.html:127 msgid "Change log" msgstr "" -#: templates/core/inc/config_data.html:134 +#: netbox/templates/core/inc/config_data.html:134 msgid "Changelog retain create & last update records" msgstr "" -#: templates/core/inc/config_data.html:154 +#: netbox/templates/core/inc/config_data.html:154 msgid "Job retention" msgstr "" -#: templates/core/inc/datafile_panel.html:23 -#: templates/extras/configtemplate/attrs/data_file.html:6 +#: netbox/templates/core/inc/datafile_panel.html:23 +#: netbox/templates/extras/configtemplate/attrs/data_file.html:6 msgid "The data file associated with this object has been deleted" msgstr "" -#: templates/core/inc/datafile_panel.html:32 +#: netbox/templates/core/inc/datafile_panel.html:32 msgid "Data Synced" msgstr "" -#: templates/core/job/attrs/scheduled.html:3 +#: netbox/templates/core/job/attrs/scheduled.html:3 #, python-format msgid "every %(interval)s minutes" msgstr "" -#: templates/core/objectchange_list.html:9 -#: templates/extras/object_changelog.html:15 +#: netbox/templates/core/objectchange_list.html:9 +#: netbox/templates/extras/object_changelog.html:15 msgid "Change log retention" msgstr "" -#: templates/core/objectchange_list.html:9 -#: templates/extras/object_changelog.html:15 +#: netbox/templates/core/objectchange_list.html:9 +#: netbox/templates/extras/object_changelog.html:15 msgid "days" msgstr "" -#: templates/core/objectchange_list.html:9 -#: templates/extras/object_changelog.html:15 +#: netbox/templates/core/objectchange_list.html:9 +#: netbox/templates/extras/object_changelog.html:15 msgid "retaining create & last update records for non-deleted objects" msgstr "" -#: templates/core/objectchange_list.html:9 -#: templates/extras/object_changelog.html:15 +#: netbox/templates/core/objectchange_list.html:9 +#: netbox/templates/extras/object_changelog.html:15 msgid "Indefinite" msgstr "" -#: templates/core/panels/configrevision_comment.html:3 +#: netbox/templates/core/panels/configrevision_comment.html:3 msgid "Comment" msgstr "" -#: templates/core/panels/configrevision_data.html:3 +#: netbox/templates/core/panels/configrevision_data.html:3 msgid "Configuration Data" msgstr "" -#: templates/core/panels/datasource_backend.html:20 +#: netbox/templates/core/panels/datasource_backend.html:20 msgid "No parameters defined" msgstr "" -#: templates/core/panels/objectchange_difference.html:5 +#: netbox/templates/core/panels/objectchange_difference.html:5 msgid "Difference" msgstr "" -#: templates/core/panels/objectchange_difference.html:8 +#: netbox/templates/core/panels/objectchange_difference.html:8 msgid "Previous" msgstr "" -#: templates/core/panels/objectchange_difference.html:11 +#: netbox/templates/core/panels/objectchange_difference.html:11 msgid "Next" msgstr "" -#: templates/core/panels/objectchange_difference.html:19 +#: netbox/templates/core/panels/objectchange_difference.html:19 msgid "Object Created" msgstr "" -#: templates/core/panels/objectchange_difference.html:21 +#: netbox/templates/core/panels/objectchange_difference.html:21 msgid "Object Deleted" msgstr "" -#: templates/core/panels/objectchange_difference.html:23 +#: netbox/templates/core/panels/objectchange_difference.html:23 msgid "No Changes" msgstr "" -#: templates/core/panels/objectchange_postchange.html:4 +#: netbox/templates/core/panels/objectchange_postchange.html:4 msgid "Post-Change Data" msgstr "" -#: templates/core/panels/objectchange_prechange.html:4 +#: netbox/templates/core/panels/objectchange_prechange.html:4 msgid "Pre-Change Data" msgstr "" -#: templates/core/panels/objectchange_prechange.html:15 +#: netbox/templates/core/panels/objectchange_prechange.html:15 msgid "Warning: Comparing non-atomic change to previous change record" msgstr "" -#: templates/core/panels/objectchange_related.html:6 +#: netbox/templates/core/panels/objectchange_related.html:6 #, python-format msgid "See All %(count)s Changes" msgstr "" -#: templates/core/plugin.html:22 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "" -#: templates/core/plugin.html:33 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "" -#: templates/core/plugin.html:39 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "" -#: templates/core/plugin.html:51 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "" -#: templates/core/plugin.html:58 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "" -#: templates/core/plugin.html:76 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "" -#: templates/core/plugin.html:96 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "" -#: templates/core/plugin.html:107 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "" -#: templates/core/rq_queue_list.html:5 templates/core/rq_queue_list.html:13 -#: templates/core/rq_task_list.html:14 templates/core/rq_worker.html:7 +#: netbox/templates/core/rq_queue_list.html:5 +#: netbox/templates/core/rq_queue_list.html:13 +#: netbox/templates/core/rq_task_list.html:14 +#: netbox/templates/core/rq_worker.html:7 msgid "Background Queues" msgstr "" -#: templates/core/rq_queue_list.html:24 templates/core/rq_queue_list.html:25 -#: templates/core/rq_worker_list.html:49 templates/core/rq_worker_list.html:50 -#: templates/extras/script_result.html:67 -#: templates/extras/script_result.html:69 -#: templates/inc/table_controls_htmx.html:30 -#: templates/inc/table_controls_htmx.html:31 +#: netbox/templates/core/rq_queue_list.html:24 +#: netbox/templates/core/rq_queue_list.html:25 +#: netbox/templates/core/rq_worker_list.html:49 +#: netbox/templates/core/rq_worker_list.html:50 +#: netbox/templates/extras/script_result.html:67 +#: netbox/templates/extras/script_result.html:69 +#: netbox/templates/inc/table_controls_htmx.html:30 +#: netbox/templates/inc/table_controls_htmx.html:31 msgid "Configure Table" msgstr "" -#: templates/core/rq_task.html:29 +#: netbox/templates/core/rq_task.html:29 msgid "Stop" msgstr "" -#: templates/core/rq_task.html:34 +#: netbox/templates/core/rq_task.html:34 msgid "Requeue" msgstr "" -#: templates/core/rq_task.html:39 +#: netbox/templates/core/rq_task.html:39 msgid "Enqueue" msgstr "" -#: templates/core/rq_task.html:65 +#: netbox/templates/core/rq_task.html:65 msgid "Timeout" msgstr "" -#: templates/core/rq_task.html:69 +#: netbox/templates/core/rq_task.html:69 msgid "Result TTL" msgstr "" -#: templates/core/rq_task.html:89 +#: netbox/templates/core/rq_task.html:89 msgid "Meta" msgstr "" -#: templates/core/rq_task.html:93 +#: netbox/templates/core/rq_task.html:93 msgid "Arguments" msgstr "" -#: templates/core/rq_task.html:97 +#: netbox/templates/core/rq_task.html:97 msgid "Keyword Arguments" msgstr "" -#: templates/core/rq_task.html:103 +#: netbox/templates/core/rq_task.html:103 msgid "Depends on" msgstr "" -#: templates/core/rq_task.html:109 +#: netbox/templates/core/rq_task.html:109 msgid "Exception" msgstr "" -#: templates/core/rq_task_list.html:28 +#: netbox/templates/core/rq_task_list.html:28 msgid "tasks in " msgstr "" -#: templates/core/rq_task_list.html:33 +#: netbox/templates/core/rq_task_list.html:33 msgid "Queued Jobs" msgstr "" -#: templates/core/rq_task_list.html:64 templates/extras/script_result.html:86 +#: netbox/templates/core/rq_task_list.html:64 +#: netbox/templates/extras/script_result.html:86 #, python-format msgid "" "Select all %(count)s %(object_type_plural)s matching query" msgstr "" -#: templates/core/rq_worker.html:10 +#: netbox/templates/core/rq_worker.html:10 msgid "Worker Info" msgstr "" -#: templates/core/rq_worker.html:31 templates/core/rq_worker.html:40 +#: netbox/templates/core/rq_worker.html:31 +#: netbox/templates/core/rq_worker.html:40 msgid "Worker" msgstr "" -#: templates/core/rq_worker.html:55 +#: netbox/templates/core/rq_worker.html:55 msgid "Queues" msgstr "" -#: templates/core/rq_worker.html:63 +#: netbox/templates/core/rq_worker.html:63 msgid "Current Job" msgstr "" -#: templates/core/rq_worker.html:67 +#: netbox/templates/core/rq_worker.html:67 msgid "Successful job count" msgstr "" -#: templates/core/rq_worker.html:71 +#: netbox/templates/core/rq_worker.html:71 msgid "Failed job count" msgstr "" -#: templates/core/rq_worker.html:75 +#: netbox/templates/core/rq_worker.html:75 msgid "Total working time" msgstr "" -#: templates/core/rq_worker.html:76 +#: netbox/templates/core/rq_worker.html:76 msgid "seconds" msgstr "" -#: templates/core/rq_worker_list.html:13 templates/core/rq_worker_list.html:21 +#: netbox/templates/core/rq_worker_list.html:13 +#: netbox/templates/core/rq_worker_list.html:21 msgid "Background Workers" msgstr "" -#: templates/core/rq_worker_list.html:29 +#: netbox/templates/core/rq_worker_list.html:29 #, python-format msgid "Workers in %(queue_name)s" msgstr "" -#: templates/core/system.html:12 +#: netbox/templates/core/system.html:12 msgid "Export All" msgstr "" -#: templates/core/system.html:25 templates/extras/object_render_config.html:6 +#: netbox/templates/core/system.html:25 +#: netbox/templates/extras/object_render_config.html:6 msgid "Config" msgstr "" -#: templates/core/system.html:40 +#: netbox/templates/core/system.html:40 msgid "Database" msgstr "" -#: templates/core/system.html:52 +#: netbox/templates/core/system.html:52 msgid "System Status" msgstr "" -#: templates/core/system.html:55 +#: netbox/templates/core/system.html:55 msgid "System hostname" msgstr "" -#: templates/core/system.html:59 +#: netbox/templates/core/system.html:59 msgid "NetBox release" msgstr "" -#: templates/core/system.html:72 +#: netbox/templates/core/system.html:72 msgid "Django version" msgstr "" -#: templates/core/system.html:76 +#: netbox/templates/core/system.html:76 msgid "PostgreSQL version" msgstr "" -#: templates/core/system.html:80 +#: netbox/templates/core/system.html:80 msgid "Database name" msgstr "" -#: templates/core/system.html:84 +#: netbox/templates/core/system.html:84 msgid "Database size" msgstr "" -#: templates/core/system.html:89 +#: netbox/templates/core/system.html:89 msgid "Unavailable" msgstr "" -#: templates/core/system.html:94 +#: netbox/templates/core/system.html:94 msgid "RQ workers" msgstr "" -#: templates/core/system.html:97 +#: netbox/templates/core/system.html:97 msgid "default queue" msgstr "" -#: templates/core/system.html:101 +#: netbox/templates/core/system.html:101 msgid "System time" msgstr "" -#: templates/core/system.html:107 +#: netbox/templates/core/system.html:107 msgid "Django Apps" msgstr "" -#: templates/core/system.html:132 +#: netbox/templates/core/system.html:132 msgid "Current Configuration" msgstr "" -#: templates/core/system.html:144 +#: netbox/templates/core/system.html:144 msgid "Installed Plugins" msgstr "" -#: templates/core/system.html:156 +#: netbox/templates/core/system.html:156 msgid "No plugins are installed." msgstr "" -#: templates/core/system.html:189 +#: netbox/templates/core/system.html:189 msgid "Loading database schema…" msgstr "" -#: templates/dcim/bulk_disconnect.html:9 +#: netbox/templates/dcim/bulk_disconnect.html:9 #, python-format msgid "" "Are you sure you want to disconnect these %(count)s %(obj_type_plural)s?" msgstr "" -#: templates/dcim/cable_trace.html:10 +#: netbox/templates/dcim/cable_trace.html:10 #, python-format msgid "Cable Trace for %(object_type)s %(object)s" msgstr "" -#: templates/dcim/cable_trace.html:24 templates/dcim/inc/rack_elevation.html:18 +#: netbox/templates/dcim/cable_trace.html:24 +#: netbox/templates/dcim/inc/rack_elevation.html:18 msgid "Download SVG" msgstr "" -#: templates/dcim/cable_trace.html:30 +#: netbox/templates/dcim/cable_trace.html:30 msgid "Asymmetric Path" msgstr "" -#: templates/dcim/cable_trace.html:31 +#: netbox/templates/dcim/cable_trace.html:31 msgid "The nodes below have no links and result in an asymmetric path" msgstr "" -#: templates/dcim/cable_trace.html:38 +#: netbox/templates/dcim/cable_trace.html:38 msgid "Path split" msgstr "" -#: templates/dcim/cable_trace.html:39 +#: netbox/templates/dcim/cable_trace.html:39 msgid "Select a node below to continue" msgstr "" -#: templates/dcim/cable_trace.html:55 +#: netbox/templates/dcim/cable_trace.html:55 msgid "Trace Completed" msgstr "" -#: templates/dcim/cable_trace.html:58 +#: netbox/templates/dcim/cable_trace.html:58 msgid "Total segments" msgstr "" -#: templates/dcim/cable_trace.html:62 +#: netbox/templates/dcim/cable_trace.html:62 msgid "Total length" msgstr "" -#: templates/dcim/cable_trace.html:77 +#: netbox/templates/dcim/cable_trace.html:77 msgid "No paths found" msgstr "" -#: templates/dcim/cable_trace.html:85 +#: netbox/templates/dcim/cable_trace.html:85 msgid "Related Paths" msgstr "" -#: templates/dcim/cable_trace.html:89 +#: netbox/templates/dcim/cable_trace.html:89 msgid "Origin" msgstr "" -#: templates/dcim/cable_trace.html:90 +#: netbox/templates/dcim/cable_trace.html:90 msgid "Destination" msgstr "" -#: templates/dcim/cable_trace.html:91 +#: netbox/templates/dcim/cable_trace.html:91 msgid "Segments" msgstr "" -#: templates/dcim/cable_trace.html:104 +#: netbox/templates/dcim/cable_trace.html:104 msgid "Incomplete" msgstr "" -#: templates/dcim/device/attrs/ipaddress.html:5 -#: templates/virtualization/virtualmachine/attrs/ipaddress.html:5 +#: netbox/templates/dcim/device/attrs/ipaddress.html:5 +#: netbox/templates/virtualization/virtualmachine/attrs/ipaddress.html:5 msgid "NAT for" msgstr "" -#: templates/dcim/device/attrs/ipaddress.html:7 -#: templates/virtualization/virtualmachine/attrs/ipaddress.html:7 +#: netbox/templates/dcim/device/attrs/ipaddress.html:7 +#: netbox/templates/virtualization/virtualmachine/attrs/ipaddress.html:7 msgid "NAT" msgstr "" -#: templates/dcim/device/attrs/ipaddress.html:10 -#: templates/ui/actions/copy_content.html:2 templates/ui/attrs/numeric.html:9 -#: templates/ui/attrs/text.html:4 -#: templates/virtualization/virtualmachine/attrs/ipaddress.html:10 -#: utilities/templates/form_helpers/render_field.html:41 +#: netbox/templates/dcim/device/attrs/ipaddress.html:10 +#: netbox/templates/ui/actions/copy_content.html:2 +#: netbox/templates/ui/attrs/numeric.html:9 +#: netbox/templates/ui/attrs/text.html:4 +#: netbox/templates/users/inc/new_token_banner.html:17 +#: netbox/templates/virtualization/virtualmachine/attrs/ipaddress.html:10 +#: netbox/utilities/templates/form_helpers/render_field.html:41 msgid "Copy to clipboard" msgstr "" -#: templates/dcim/device/attrs/parent_device.html:7 -#: templates/dcim/device/attrs/rack.html:11 +#: netbox/templates/dcim/device/attrs/parent_device.html:7 +#: netbox/templates/dcim/device/attrs/rack.html:11 msgid "Highlight device in rack" msgstr "" -#: templates/dcim/device/attrs/rack.html:7 +#: netbox/templates/dcim/device/attrs/rack.html:7 msgid "Not racked" msgstr "" -#: templates/dcim/device/inc/interface_table_controls.html:9 +#: netbox/templates/dcim/device/inc/interface_table_controls.html:9 msgid "Hide Enabled" msgstr "" -#: templates/dcim/device/inc/interface_table_controls.html:10 +#: netbox/templates/dcim/device/inc/interface_table_controls.html:10 msgid "Hide Disabled" msgstr "" -#: templates/dcim/device/inc/interface_table_controls.html:11 +#: netbox/templates/dcim/device/inc/interface_table_controls.html:11 msgid "Hide Virtual" msgstr "" -#: templates/dcim/device/inc/interface_table_controls.html:12 +#: netbox/templates/dcim/device/inc/interface_table_controls.html:12 msgid "Hide Disconnected" msgstr "" -#: templates/dcim/device_edit.html:46 +#: netbox/templates/dcim/device_edit.html:46 msgid "Parent Bay" msgstr "" -#: templates/dcim/device_edit.html:50 -#: utilities/templates/form_helpers/render_field.html:22 +#: netbox/templates/dcim/device_edit.html:50 +#: netbox/utilities/templates/form_helpers/render_field.html:22 msgid "Regenerate Slug" msgstr "" -#: templates/dcim/device_edit.html:51 templates/extras/tableconfig_edit.html:32 -#: utilities/templates/helpers/table_config_form.html:23 -#: utilities/templates/widgets/splitmultiselect.html:14 +#: netbox/templates/dcim/device_edit.html:51 +#: netbox/templates/extras/tableconfig_edit.html:32 +#: netbox/utilities/templates/helpers/table_config_form.html:23 +#: netbox/utilities/templates/widgets/splitmultiselect.html:14 msgid "Remove" msgstr "" -#: templates/dcim/device_edit.html:120 +#: netbox/templates/dcim/device_edit.html:120 msgid "Local Config Context Data" msgstr "" -#: templates/dcim/devicebay_depopulate.html:6 +#: netbox/templates/dcim/devicebay_depopulate.html:6 #, python-format msgid "Remove %(device)s from %(device_bay)s?" msgstr "" -#: templates/dcim/devicebay_depopulate.html:13 +#: netbox/templates/dcim/devicebay_depopulate.html:13 #, python-format msgid "" "Are you sure you want to remove %(device)s from " "%(device_bay)s?" msgstr "" -#: templates/dcim/devicebay_populate.html:13 +#: netbox/templates/dcim/devicebay_populate.html:13 msgid "Populate" msgstr "" -#: templates/dcim/devicebay_populate.html:22 +#: netbox/templates/dcim/devicebay_populate.html:22 msgid "Bay" msgstr "" -#: templates/dcim/devicerole.html:14 templates/dcim/platform.html:17 +#: netbox/templates/dcim/devicerole.html:14 +#: netbox/templates/dcim/platform.html:17 msgid "Add Device" msgstr "" -#: templates/dcim/htmx/cable_edit.html:13 +#: netbox/templates/dcim/htmx/cable_edit.html:13 msgid "A Side" msgstr "" -#: templates/dcim/htmx/cable_edit.html:33 +#: netbox/templates/dcim/htmx/cable_edit.html:33 msgid "B Side" msgstr "" -#: templates/dcim/inc/cable_termination.html:76 +#: netbox/templates/dcim/inc/cable_termination.html:76 msgid "No termination" msgstr "" -#: templates/dcim/inc/cable_toggle_buttons.html:3 +#: netbox/templates/dcim/inc/cable_toggle_buttons.html:3 msgid "Mark Planned" msgstr "" -#: templates/dcim/inc/cable_toggle_buttons.html:6 +#: netbox/templates/dcim/inc/cable_toggle_buttons.html:6 msgid "Mark Installed" msgstr "" -#: templates/dcim/inc/connection_endpoints.html:13 +#: netbox/templates/dcim/inc/connection_endpoints.html:13 msgid "Path Status" msgstr "" -#: templates/dcim/inc/connection_endpoints.html:18 -#: templates/dcim/panels/connection.html:28 -#: templates/dcim/panels/interface_connection.html:27 +#: netbox/templates/dcim/inc/connection_endpoints.html:18 +#: netbox/templates/dcim/panels/connection.html:28 +#: netbox/templates/dcim/panels/interface_connection.html:27 msgid "Not Reachable" msgstr "" -#: templates/dcim/inc/connection_endpoints.html:23 +#: netbox/templates/dcim/inc/connection_endpoints.html:23 msgid "Path Endpoints" msgstr "" -#: templates/dcim/inc/endpoint_connection.html:8 +#: netbox/templates/dcim/inc/endpoint_connection.html:8 msgid "Not connected" msgstr "" -#: templates/dcim/inc/interface_vlans_table.html:6 +#: netbox/templates/dcim/inc/interface_vlans_table.html:6 msgid "Untagged" msgstr "" -#: templates/dcim/inc/interface_vlans_table.html:37 +#: netbox/templates/dcim/inc/interface_vlans_table.html:37 msgid "No VLANs Assigned" msgstr "" -#: templates/dcim/inc/interface_vlans_table.html:44 -#: templates/ipam/inc/max_depth.html:11 templates/ipam/inc/max_length.html:11 +#: netbox/templates/dcim/inc/interface_vlans_table.html:44 +#: netbox/templates/ipam/inc/max_depth.html:11 +#: netbox/templates/ipam/inc/max_length.html:11 msgid "Clear" msgstr "" -#: templates/dcim/inc/interface_vlans_table.html:47 +#: netbox/templates/dcim/inc/interface_vlans_table.html:47 msgid "Clear All" msgstr "" -#: templates/dcim/inc/panels/inventory_items.html:10 +#: netbox/templates/dcim/inc/panels/inventory_items.html:10 msgid "Add Inventory Item" msgstr "" -#: templates/dcim/inc/panels/racktype_dimensions.html:48 +#: netbox/templates/dcim/inc/panels/racktype_dimensions.html:48 msgid "Mounting Depth" msgstr "" -#: templates/dcim/inc/panels/racktype_numbering.html:6 +#: netbox/templates/dcim/inc/panels/racktype_numbering.html:6 msgid "Starting Unit" msgstr "" -#: templates/dcim/inc/panels/racktype_numbering.html:10 +#: netbox/templates/dcim/inc/panels/racktype_numbering.html:10 msgid "Descending Units" msgstr "" -#: templates/dcim/inc/rack_elevation.html:7 +#: netbox/templates/dcim/inc/rack_elevation.html:7 msgid "Rack elevation" msgstr "" -#: templates/dcim/inc/rack_elevation.html:11 +#: netbox/templates/dcim/inc/rack_elevation.html:11 msgid "Loading..." msgstr "" -#: templates/dcim/interface.html:14 +#: netbox/templates/dcim/interface.html:14 msgid "Add Child Interface" msgstr "" -#: templates/dcim/manufacturer.html:13 +#: netbox/templates/dcim/manufacturer.html:13 msgid "Add Device Type" msgstr "" -#: templates/dcim/manufacturer.html:18 +#: netbox/templates/dcim/manufacturer.html:18 msgid "Add Module Type" msgstr "" -#: templates/dcim/panels/connection.html:23 -#: templates/dcim/panels/interface_connection.html:22 +#: netbox/templates/dcim/panels/connection.html:23 +#: netbox/templates/dcim/panels/interface_connection.html:22 msgid "Path status" msgstr "" -#: templates/dcim/panels/connection.html:33 -#: templates/dcim/panels/interface_connection.html:32 +#: netbox/templates/dcim/panels/connection.html:33 +#: netbox/templates/dcim/panels/interface_connection.html:32 msgid "Path endpoints" msgstr "" -#: templates/dcim/panels/connection.html:73 -#: templates/dcim/panels/interface_connection.html:75 +#: netbox/templates/dcim/panels/connection.html:73 +#: netbox/templates/dcim/panels/interface_connection.html:75 msgid "Not Connected" msgstr "" -#: templates/dcim/panels/front_port_mappings.html:4 -#: templates/dcim/panels/rear_port_mappings.html:4 +#: netbox/templates/dcim/panels/front_port_mappings.html:4 +#: netbox/templates/dcim/panels/rear_port_mappings.html:4 msgid "Port Mappings" msgstr "" -#: templates/dcim/panels/front_port_mappings.html:24 -#: templates/dcim/panels/rear_port_mappings.html:24 +#: netbox/templates/dcim/panels/front_port_mappings.html:24 +#: netbox/templates/dcim/panels/rear_port_mappings.html:24 msgid "No mappings defined" msgstr "" -#: templates/dcim/panels/interface_connection.html:50 +#: netbox/templates/dcim/panels/interface_connection.html:50 msgid "Wireless Link" msgstr "" -#: templates/dcim/panels/interface_wireless.html:24 -#: templates/wireless/panels/wirelesslink_interface.html:24 +#: netbox/templates/dcim/panels/interface_wireless.html:24 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:24 msgid "Channel" msgstr "" -#: templates/dcim/panels/interface_wireless.html:33 +#: netbox/templates/dcim/panels/interface_wireless.html:33 msgid "Channel frequency" msgstr "" -#: templates/dcim/panels/interface_wireless.html:36 -#: templates/dcim/panels/interface_wireless.html:44 -#: templates/dcim/panels/interface_wireless.html:55 -#: templates/dcim/panels/interface_wireless.html:63 +#: netbox/templates/dcim/panels/interface_wireless.html:36 +#: netbox/templates/dcim/panels/interface_wireless.html:44 +#: netbox/templates/dcim/panels/interface_wireless.html:55 +#: netbox/templates/dcim/panels/interface_wireless.html:63 msgid "MHz" msgstr "" -#: templates/dcim/panels/interface_wireless.html:52 +#: netbox/templates/dcim/panels/interface_wireless.html:52 msgid "Channel width" msgstr "" -#: templates/dcim/panels/interface_wireless_lans.html:9 -#: wireless/forms/bulk_edit.py:57 wireless/forms/bulk_edit.py:94 -#: wireless/forms/filtersets.py:49 wireless/forms/filtersets.py:115 -#: wireless/models.py:86 wireless/models.py:153 -#: wireless/tables/wirelesslan.py:37 wireless/ui/panels.py:11 -#: wireless/ui/panels.py:48 +#: netbox/templates/dcim/panels/interface_wireless_lans.html:9 +#: netbox/wireless/forms/bulk_edit.py:57 netbox/wireless/forms/bulk_edit.py:94 +#: netbox/wireless/forms/filtersets.py:49 +#: netbox/wireless/forms/filtersets.py:115 netbox/wireless/models.py:86 +#: netbox/wireless/models.py:153 netbox/wireless/tables/wirelesslan.py:37 +#: netbox/wireless/ui/panels.py:11 netbox/wireless/ui/panels.py:48 msgid "SSID" msgstr "" -#: templates/dcim/panels/module_type_attributes.html:7 +#: netbox/templates/dcim/panels/module_type_attributes.html:7 msgid "No profile assigned" msgstr "" -#: templates/dcim/panels/power_utilization.html:8 +#: netbox/templates/dcim/panels/power_utilization.html:8 msgid "Input" msgstr "" -#: templates/dcim/panels/power_utilization.html:9 +#: netbox/templates/dcim/panels/power_utilization.html:9 msgid "Outlets" msgstr "" -#: templates/dcim/panels/power_utilization.html:10 +#: netbox/templates/dcim/panels/power_utilization.html:10 msgid "Allocated" msgstr "" -#: templates/dcim/panels/power_utilization.html:20 -#: templates/dcim/panels/power_utilization.html:22 -#: templates/dcim/panels/power_utilization.html:38 -#: templates/dcim/powerfeed/attrs/utilization.html:5 +#: netbox/templates/dcim/panels/power_utilization.html:20 +#: netbox/templates/dcim/panels/power_utilization.html:22 +#: netbox/templates/dcim/panels/power_utilization.html:38 +#: netbox/templates/dcim/powerfeed/attrs/utilization.html:5 msgid "VA" msgstr "" -#: templates/dcim/panels/power_utilization.html:32 +#: netbox/templates/dcim/panels/power_utilization.html:32 msgctxt "Leg of a power feed" msgid "Leg" msgstr "" -#: templates/dcim/panels/rack_elevations.html:4 -#: templates/dcim/rack_elevation_list.html:15 +#: netbox/templates/dcim/panels/rack_elevations.html:4 +#: netbox/templates/dcim/rack_elevation_list.html:15 msgid "Images and Labels" msgstr "" -#: templates/dcim/panels/rack_elevations.html:5 -#: templates/dcim/rack_elevation_list.html:16 +#: netbox/templates/dcim/panels/rack_elevations.html:5 +#: netbox/templates/dcim/rack_elevation_list.html:16 msgid "Images only" msgstr "" -#: templates/dcim/panels/rack_elevations.html:6 -#: templates/dcim/rack_elevation_list.html:17 +#: netbox/templates/dcim/panels/rack_elevations.html:6 +#: netbox/templates/dcim/rack_elevation_list.html:17 msgid "Labels only" msgstr "" -#: templates/dcim/rack/reservations.html:8 +#: netbox/templates/dcim/rack/reservations.html:8 msgid "Add reservation" msgstr "" -#: templates/dcim/rack_elevation_list.html:12 +#: netbox/templates/dcim/rack_elevation_list.html:12 msgid "View List" msgstr "" -#: templates/dcim/rack_elevation_list.html:14 +#: netbox/templates/dcim/rack_elevation_list.html:14 msgid "Select rack view" msgstr "" -#: templates/dcim/rack_elevation_list.html:25 +#: netbox/templates/dcim/rack_elevation_list.html:25 msgid "Sort By" msgstr "" -#: templates/dcim/rack_elevation_list.html:74 +#: netbox/templates/dcim/rack_elevation_list.html:74 msgid "No Racks Found" msgstr "" -#: templates/dcim/rack_list.html:8 +#: netbox/templates/dcim/rack_list.html:8 msgid "View Elevations" msgstr "" -#: templates/dcim/rackgroup.html:7 templates/dcim/rackrole.html:7 +#: netbox/templates/dcim/rackgroup.html:7 netbox/templates/dcim/rackrole.html:7 msgid "Add Rack" msgstr "" -#: templates/dcim/region.html:14 templates/dcim/sitegroup.html:14 +#: netbox/templates/dcim/region.html:14 netbox/templates/dcim/sitegroup.html:14 msgid "Add Site" msgstr "" -#: templates/dcim/virtualchassis_add_member.html:10 +#: netbox/templates/dcim/virtualchassis_add_member.html:10 #, python-format msgid "Add New Member to Virtual Chassis %(virtual_chassis)s" msgstr "" -#: templates/dcim/virtualchassis_add_member.html:19 +#: netbox/templates/dcim/virtualchassis_add_member.html:19 msgid "Add New Member" msgstr "" -#: templates/dcim/virtualchassis_add_member.html:27 -#: templates/generic/object_edit.html:80 users/forms/filtersets.py:64 -#: users/forms/model_forms.py:377 users/forms/model_forms.py:419 -#: users/ui/panels.py:50 +#: netbox/templates/dcim/virtualchassis_add_member.html:27 +#: netbox/templates/generic/object_edit.html:80 +#: netbox/users/forms/filtersets.py:64 netbox/users/forms/model_forms.py:368 +#: netbox/users/forms/model_forms.py:410 netbox/users/ui/panels.py:50 msgid "Actions" msgstr "" -#: templates/dcim/virtualchassis_add_member.html:29 +#: netbox/templates/dcim/virtualchassis_add_member.html:29 msgid "Save & Add Another" msgstr "" -#: templates/dcim/virtualchassis_edit.html:7 +#: netbox/templates/dcim/virtualchassis_edit.html:7 #, python-format msgid "Editing Virtual Chassis %(name)s" msgstr "" -#: templates/dcim/virtualchassis_edit.html:65 +#: netbox/templates/dcim/virtualchassis_edit.html:65 msgid "Rack/Unit" msgstr "" -#: templates/dcim/virtualchassis_edit.html:122 -#: templates/generic/bulk_add.html:12 -#: templates/generic/bulk_add_component.html:82 -#: templates/generic/object_edit.html:47 templates/generic/object_edit.html:82 -#: templates/htmx/quick_add.html:24 -#: templates/ipam/inc/ipaddress_edit_header.html:7 -#: templates/ipam/inc/prefix_edit_header.html:7 -msgid "Create" -msgstr "" - -#: templates/dcim/virtualchassis_remove_member.html:5 +#: netbox/templates/dcim/virtualchassis_remove_member.html:5 msgid "Remove Virtual Chassis Member" msgstr "" -#: templates/dcim/virtualchassis_remove_member.html:9 +#: netbox/templates/dcim/virtualchassis_remove_member.html:9 #, python-format msgid "" "Are you sure you want to remove %(device)s from virtual " "chassis %(name)s?" msgstr "" -#: templates/exceptions/import_error.html:6 +#: netbox/templates/exceptions/import_error.html:6 msgid "" "A module import error occurred during this request. Common causes include " "the following:" msgstr "" -#: templates/exceptions/import_error.html:10 +#: netbox/templates/exceptions/import_error.html:10 msgid "Missing required packages" msgstr "" -#: templates/exceptions/import_error.html:11 +#: netbox/templates/exceptions/import_error.html:11 #, python-format msgid "" "This installation of NetBox might be missing one or more required Python " @@ -13950,28 +14508,28 @@ msgid "" "of required packages." msgstr "" -#: templates/exceptions/import_error.html:20 +#: netbox/templates/exceptions/import_error.html:20 msgid "WSGI service not restarted after upgrade" msgstr "" -#: templates/exceptions/import_error.html:21 +#: netbox/templates/exceptions/import_error.html:21 msgid "" "If this installation has recently been upgraded, check that the WSGI service " "(e.g. gunicorn or uWSGI) has been restarted. This ensures that the new code " "is running." msgstr "" -#: templates/exceptions/permission_error.html:6 +#: netbox/templates/exceptions/permission_error.html:6 msgid "" "A file permission error was detected while processing this request. Common " "causes include the following:" msgstr "" -#: templates/exceptions/permission_error.html:10 +#: netbox/templates/exceptions/permission_error.html:10 msgid "Insufficient write permission to the media root" msgstr "" -#: templates/exceptions/permission_error.html:11 +#: netbox/templates/exceptions/permission_error.html:11 #, python-format msgid "" "The configured media root is %(media_root)s. Ensure that the " @@ -13979,17 +14537,17 @@ msgid "" "path." msgstr "" -#: templates/exceptions/programming_error.html:6 +#: netbox/templates/exceptions/programming_error.html:6 msgid "" "A database programming error was detected while processing this request. " "Common causes include the following:" msgstr "" -#: templates/exceptions/programming_error.html:10 +#: netbox/templates/exceptions/programming_error.html:10 msgid "Database migrations missing" msgstr "" -#: templates/exceptions/programming_error.html:11 +#: netbox/templates/exceptions/programming_error.html:11 #, python-format msgid "" "When upgrading to a new NetBox release, the upgrade script must be run to " @@ -13997,11 +14555,11 @@ msgid "" "executing %(command)s from the command line." msgstr "" -#: templates/exceptions/programming_error.html:18 +#: netbox/templates/exceptions/programming_error.html:18 msgid "Unsupported PostgreSQL version" msgstr "" -#: templates/exceptions/programming_error.html:19 +#: netbox/templates/exceptions/programming_error.html:19 #, python-format msgid "" "Ensure that PostgreSQL version 14 or later is in use. You can check this by " @@ -14009,156 +14567,157 @@ msgid "" "for %(sql_query)s." msgstr "" -#: templates/extras/customfield/attrs/choice_set.html:1 -#: templates/generic/bulk_import.html:179 +#: netbox/templates/extras/customfield/attrs/choice_set.html:1 +#: netbox/templates/generic/bulk_import.html:179 msgid "choices" msgstr "" -#: templates/extras/dashboard/reset.html:4 templates/home.html:66 +#: netbox/templates/extras/dashboard/reset.html:4 netbox/templates/home.html:66 msgid "Reset Dashboard" msgstr "" -#: templates/extras/dashboard/reset.html:8 +#: netbox/templates/extras/dashboard/reset.html:8 msgid "" "This will remove all configured widgets and restore the " "default dashboard configuration." msgstr "" -#: templates/extras/dashboard/reset.html:13 +#: netbox/templates/extras/dashboard/reset.html:13 msgid "" "This change affects only your dashboard, and will not impact other " "users." msgstr "" -#: templates/extras/dashboard/widget.html:21 +#: netbox/templates/extras/dashboard/widget.html:21 msgid "widget configuration" msgstr "" -#: templates/extras/dashboard/widget.html:36 +#: netbox/templates/extras/dashboard/widget.html:36 msgid "Close widget" msgstr "" -#: templates/extras/dashboard/widget_add.html:7 +#: netbox/templates/extras/dashboard/widget_add.html:7 msgid "Add a Widget" msgstr "" -#: templates/extras/dashboard/widgets/bookmarks.html:14 +#: netbox/templates/extras/dashboard/widgets/bookmarks.html:14 msgid "No bookmarks have been added yet." msgstr "" -#: templates/extras/dashboard/widgets/objectcounts.html:10 +#: netbox/templates/extras/dashboard/widgets/objectcounts.html:10 msgid "No permission" msgstr "" -#: templates/extras/dashboard/widgets/objectlist.html:6 +#: netbox/templates/extras/dashboard/widgets/objectlist.html:6 msgid "No permission to view this content" msgstr "" -#: templates/extras/dashboard/widgets/objectlist.html:10 +#: netbox/templates/extras/dashboard/widgets/objectlist.html:10 msgid "Unable to load content. Could not resolve list URL for:" msgstr "" -#: templates/extras/dashboard/widgets/rssfeed.html:12 +#: netbox/templates/extras/dashboard/widgets/rssfeed.html:12 msgid "No content found" msgstr "" -#: templates/extras/dashboard/widgets/rssfeed.html:17 +#: netbox/templates/extras/dashboard/widgets/rssfeed.html:17 msgid "" "This RSS feed requires an external connection. Check the ISOLATED_DEPLOYMENT " "setting." msgstr "" -#: templates/extras/dashboard/widgets/rssfeed.html:22 +#: netbox/templates/extras/dashboard/widgets/rssfeed.html:22 msgid "There was a problem fetching the RSS feed" msgstr "" -#: templates/extras/dashboard/widgets/rssfeed.html:25 +#: netbox/templates/extras/dashboard/widgets/rssfeed.html:25 msgid "HTTP" msgstr "" -#: templates/extras/htmx/script_result.html:10 +#: netbox/templates/extras/htmx/script_result.html:10 msgid "Scheduled for" msgstr "" -#: templates/extras/htmx/script_result.html:15 +#: netbox/templates/extras/htmx/script_result.html:15 msgid "Duration" msgstr "" -#: templates/extras/htmx/script_result.html:23 +#: netbox/templates/extras/htmx/script_result.html:23 msgid "Test Summary" msgstr "" -#: templates/extras/htmx/script_result.html:57 +#: netbox/templates/extras/htmx/script_result.html:57 msgid "Output" msgstr "" -#: templates/extras/htmx/script_result.html:61 -#: templates/extras/object_render_config.html:70 +#: netbox/templates/extras/htmx/script_result.html:61 +#: netbox/templates/extras/object_render_config.html:70 msgid "Download" msgstr "" -#: templates/extras/inc/result_pending.html:4 +#: netbox/templates/extras/inc/result_pending.html:4 msgid "Loading" msgstr "" -#: templates/extras/inc/result_pending.html:6 +#: netbox/templates/extras/inc/result_pending.html:6 msgid "Results pending" msgstr "" -#: templates/extras/inc/script_list_content.html:34 +#: netbox/templates/extras/inc/script_list_content.html:34 msgid "Last Run" msgstr "" -#: templates/extras/inc/script_list_content.html:50 +#: netbox/templates/extras/inc/script_list_content.html:50 msgid "Script is no longer present in the source file" msgstr "" -#: templates/extras/inc/script_list_content.html:76 +#: netbox/templates/extras/inc/script_list_content.html:76 msgid "Run Again" msgstr "" -#: templates/extras/inc/script_list_content.html:78 -#: templates/extras/script.html:41 templates/extras/script.html:45 +#: netbox/templates/extras/inc/script_list_content.html:78 +#: netbox/templates/extras/script.html:41 +#: netbox/templates/extras/script.html:45 msgid "Run Script" msgstr "" -#: templates/extras/inc/script_list_content.html:125 +#: netbox/templates/extras/inc/script_list_content.html:125 #, python-format msgid "Could not load scripts from module %(module)s" msgstr "" -#: templates/extras/inc/script_list_content.html:134 +#: netbox/templates/extras/inc/script_list_content.html:134 msgid "No Scripts Found" msgstr "" -#: templates/extras/inc/script_list_content.html:137 +#: netbox/templates/extras/inc/script_list_content.html:137 #, python-format msgid "" "Get started by creating a script from " "an uploaded file or data source." msgstr "" -#: templates/extras/object_configcontext.html:19 +#: netbox/templates/extras/object_configcontext.html:19 msgid "The local config context overwrites all source contexts" msgstr "" -#: templates/extras/object_configcontext.html:25 +#: netbox/templates/extras/object_configcontext.html:25 msgid "Source Contexts" msgstr "" -#: templates/extras/object_imageattachments.html:10 +#: netbox/templates/extras/object_imageattachments.html:10 msgid "Attach an Image" msgstr "" -#: templates/extras/object_imageattachments.html:35 +#: netbox/templates/extras/object_imageattachments.html:35 msgid "Thumbnail cannot be generated" msgstr "" -#: templates/extras/object_imageattachments.html:36 +#: netbox/templates/extras/object_imageattachments.html:36 msgid "Click to view original" msgstr "" -#: templates/extras/object_imageattachments.html:49 +#: netbox/templates/extras/object_imageattachments.html:49 #, python-format msgid "" "\n" @@ -14166,123 +14725,126 @@ msgid "" " " msgstr "" -#: templates/extras/object_journal.html:17 +#: netbox/templates/extras/object_journal.html:17 msgid "New Journal Entry" msgstr "" -#: templates/extras/object_render_config.html:36 +#: netbox/templates/extras/object_render_config.html:36 msgid "Context Data" msgstr "" -#: templates/extras/object_render_config.html:54 +#: netbox/templates/extras/object_render_config.html:54 msgid "Error rendering template" msgstr "" -#: templates/extras/object_render_config.html:67 +#: netbox/templates/extras/object_render_config.html:67 msgid "Rendered Config" msgstr "" -#: templates/extras/object_render_config.html:79 +#: netbox/templates/extras/object_render_config.html:79 msgid "Template output is empty" msgstr "" -#: templates/extras/object_render_config.html:84 +#: netbox/templates/extras/object_render_config.html:84 msgid "No configuration template has been assigned." msgstr "" -#: templates/extras/panels/notificationgroup_groups.html:9 -#: templates/extras/panels/notificationgroup_users.html:9 -#: utilities/templates/widgets/clearable_file_input.html:12 +#: netbox/templates/extras/panels/notificationgroup_groups.html:9 +#: netbox/templates/extras/panels/notificationgroup_users.html:9 +#: netbox/utilities/templates/widgets/clearable_file_input.html:12 msgid "None assigned" msgstr "" -#: templates/extras/panels/tag_object_types.html:12 +#: netbox/templates/extras/panels/tag_object_types.html:12 msgid "Any" msgstr "" -#: templates/extras/panels/tags.html:11 templates/inc/panels/tags.html:11 +#: netbox/templates/extras/panels/tags.html:11 +#: netbox/templates/inc/panels/tags.html:11 msgid "No tags assigned" msgstr "" -#: templates/extras/report/base.html:30 +#: netbox/templates/extras/report/base.html:30 msgid "Report" msgstr "" -#: templates/extras/script.html:14 +#: netbox/templates/extras/script.html:14 msgid "You do not have permission to run scripts" msgstr "" -#: templates/extras/script.html:51 templates/extras/script/source.html:10 +#: netbox/templates/extras/script.html:51 +#: netbox/templates/extras/script/source.html:10 msgid "Error loading script" msgstr "" -#: templates/extras/script/jobs.html:16 +#: netbox/templates/extras/script/jobs.html:16 msgid "Script no longer exists in the source file." msgstr "" -#: templates/extras/script_result.html:35 templates/generic/object_list.html:42 -#: templates/search.html:13 +#: netbox/templates/extras/script_result.html:35 +#: netbox/templates/generic/object_list.html:42 netbox/templates/search.html:13 msgid "Results" msgstr "" -#: templates/extras/script_result.html:46 +#: netbox/templates/extras/script_result.html:46 msgid "Log threshold" msgstr "" -#: templates/extras/script_result.html:56 +#: netbox/templates/extras/script_result.html:56 msgid "All" msgstr "" -#: templates/extras/tableconfig_edit.html:8 -#: utilities/templates/helpers/table_config_form.html:8 +#: netbox/templates/extras/tableconfig_edit.html:8 +#: netbox/utilities/templates/helpers/table_config_form.html:8 msgid "Table Configuration" msgstr "" -#: templates/extras/tableconfig_edit.html:40 -#: utilities/templates/helpers/table_config_form.html:31 -#: utilities/templates/widgets/splitmultiselect.html:23 +#: netbox/templates/extras/tableconfig_edit.html:40 +#: netbox/utilities/templates/helpers/table_config_form.html:31 +#: netbox/utilities/templates/widgets/splitmultiselect.html:23 msgid "Move Up" msgstr "" -#: templates/extras/tableconfig_edit.html:43 -#: utilities/templates/helpers/table_config_form.html:34 -#: utilities/templates/widgets/splitmultiselect.html:26 +#: netbox/templates/extras/tableconfig_edit.html:43 +#: netbox/utilities/templates/helpers/table_config_form.html:34 +#: netbox/utilities/templates/widgets/splitmultiselect.html:26 msgid "Move Down" msgstr "" -#: templates/generic/bulk_add.html:6 +#: netbox/templates/generic/bulk_add.html:6 #, python-format msgid "Bulk Add %(object_type_plural)s" msgstr "" -#: templates/generic/bulk_add.html:17 -#: templates/ipam/inc/ipaddress_edit_header.html:19 -#: templates/ipam/inc/prefix_edit_header.html:13 +#: netbox/templates/generic/bulk_add.html:17 +#: netbox/templates/ipam/inc/ipaddress_edit_header.html:19 +#: netbox/templates/ipam/inc/prefix_edit_header.html:13 msgid "Bulk Create" msgstr "" -#: templates/generic/bulk_add_component.html:29 +#: netbox/templates/generic/bulk_add_component.html:29 msgid "Bulk Creation" msgstr "" -#: templates/generic/bulk_add_component.html:34 -#: templates/generic/bulk_delete.html:33 templates/generic/bulk_edit.html:33 +#: netbox/templates/generic/bulk_add_component.html:34 +#: netbox/templates/generic/bulk_delete.html:33 +#: netbox/templates/generic/bulk_edit.html:33 msgid "Selected Objects" msgstr "" -#: templates/generic/bulk_add_component.html:58 +#: netbox/templates/generic/bulk_add_component.html:58 msgid "to Add" msgstr "" -#: templates/generic/bulk_delete.html:28 +#: netbox/templates/generic/bulk_delete.html:28 msgid "Bulk Delete" msgstr "" -#: templates/generic/bulk_delete.html:50 +#: netbox/templates/generic/bulk_delete.html:50 msgid "Confirm Bulk Deletion" msgstr "" -#: templates/generic/bulk_delete.html:51 +#: netbox/templates/generic/bulk_delete.html:51 #, python-format msgid "" "The following operation will delete %(count)s " @@ -14290,207 +14852,210 @@ msgid "" "this action." msgstr "" -#: templates/generic/bulk_edit.html:21 templates/generic/object_edit.html:22 +#: netbox/templates/generic/bulk_edit.html:21 +#: netbox/templates/generic/object_edit.html:22 msgid "Editing" msgstr "" -#: templates/generic/bulk_edit.html:28 +#: netbox/templates/generic/bulk_edit.html:28 msgid "Bulk Edit" msgstr "" -#: templates/generic/bulk_edit.html:131 templates/generic/bulk_rename.html:68 +#: netbox/templates/generic/bulk_edit.html:131 +#: netbox/templates/generic/bulk_rename.html:68 msgid "Apply" msgstr "" -#: templates/generic/bulk_import.html:19 +#: netbox/templates/generic/bulk_import.html:19 msgid "Bulk Import" msgstr "" -#: templates/generic/bulk_import.html:25 +#: netbox/templates/generic/bulk_import.html:25 msgid "Direct Import" msgstr "" -#: templates/generic/bulk_import.html:30 +#: netbox/templates/generic/bulk_import.html:30 msgid "Upload File" msgstr "" -#: templates/generic/bulk_import.html:68 templates/generic/bulk_import.html:100 -#: templates/generic/bulk_import.html:133 +#: netbox/templates/generic/bulk_import.html:68 +#: netbox/templates/generic/bulk_import.html:100 +#: netbox/templates/generic/bulk_import.html:133 msgid "Submit" msgstr "" -#: templates/generic/bulk_import.html:144 +#: netbox/templates/generic/bulk_import.html:144 msgid "Field Options" msgstr "" -#: templates/generic/bulk_import.html:150 +#: netbox/templates/generic/bulk_import.html:150 msgid "Accessor" msgstr "" -#: templates/generic/bulk_import.html:192 +#: netbox/templates/generic/bulk_import.html:192 msgid "Import Value" msgstr "" -#: templates/generic/bulk_import.html:212 +#: netbox/templates/generic/bulk_import.html:212 msgid "Format: YYYY-MM-DD" msgstr "" -#: templates/generic/bulk_import.html:214 +#: netbox/templates/generic/bulk_import.html:214 msgid "Specify true or false" msgstr "" -#: templates/generic/bulk_import.html:226 +#: netbox/templates/generic/bulk_import.html:226 msgid "Required fields must be specified for all objects." msgstr "" -#: templates/generic/bulk_import.html:232 +#: netbox/templates/generic/bulk_import.html:232 #, python-format msgid "" "Related objects may be referenced by any unique attribute. For example, " "%(example)s would identify a VRF by its route distinguisher." msgstr "" -#: templates/generic/bulk_rename.html:20 +#: netbox/templates/generic/bulk_rename.html:20 msgid "Renaming" msgstr "" -#: templates/generic/bulk_rename.html:27 +#: netbox/templates/generic/bulk_rename.html:27 msgid "Bulk Rename" msgstr "" -#: templates/generic/bulk_rename.html:39 +#: netbox/templates/generic/bulk_rename.html:39 msgid "Current Name" msgstr "" -#: templates/generic/bulk_rename.html:40 +#: netbox/templates/generic/bulk_rename.html:40 msgid "New Name" msgstr "" -#: templates/generic/bulk_rename.html:59 +#: netbox/templates/generic/bulk_rename.html:59 msgid "Rename" msgstr "" -#: templates/generic/bulk_rename.html:66 -#: utilities/templates/widgets/markdown_input.html:11 +#: netbox/templates/generic/bulk_rename.html:66 +#: netbox/utilities/templates/widgets/markdown_input.html:11 msgid "Preview" msgstr "" -#: templates/generic/confirmation_form.html:16 +#: netbox/templates/generic/confirmation_form.html:16 msgid "Are you sure" msgstr "" -#: templates/generic/confirmation_form.html:20 +#: netbox/templates/generic/confirmation_form.html:20 msgid "Confirm" msgstr "" -#: templates/generic/object_edit.html:24 +#: netbox/templates/generic/object_edit.html:24 #, python-format msgid "Add a new %(object_type)s" msgstr "" -#: templates/generic/object_edit.html:35 +#: netbox/templates/generic/object_edit.html:35 msgid "View model documentation" msgstr "" -#: templates/generic/object_edit.html:36 +#: netbox/templates/generic/object_edit.html:36 msgid "Help" msgstr "" -#: templates/generic/object_edit.html:85 +#: netbox/templates/generic/object_edit.html:85 msgid "Create & Add Another" msgstr "" -#: templates/generic/object_list.html:49 +#: netbox/templates/generic/object_list.html:49 msgid "Filters" msgstr "" -#: templates/generic/object_list.html:80 +#: netbox/templates/generic/object_list.html:80 #, python-format msgid "" "Select all %(count)s " "%(object_type_plural)s matching query" msgstr "" -#: templates/home.html:15 +#: netbox/templates/home.html:15 msgid "New Release Available" msgstr "" -#: templates/home.html:16 +#: netbox/templates/home.html:16 msgid "is available" msgstr "" -#: templates/home.html:18 +#: netbox/templates/home.html:18 msgctxt "Document title" msgid "Upgrade Instructions" msgstr "" -#: templates/home.html:40 +#: netbox/templates/home.html:40 msgid "Unlock Dashboard" msgstr "" -#: templates/home.html:49 +#: netbox/templates/home.html:49 msgid "Lock Dashboard" msgstr "" -#: templates/home.html:60 +#: netbox/templates/home.html:60 msgid "Add Widget" msgstr "" -#: templates/home.html:63 +#: netbox/templates/home.html:63 msgid "Save Layout" msgstr "" -#: templates/htmx/delete_form.html:12 +#: netbox/templates/htmx/delete_form.html:12 msgid "Confirm Deletion" msgstr "" -#: templates/htmx/delete_form.html:17 +#: netbox/templates/htmx/delete_form.html:17 #, python-format msgid "" "Are you sure you want to delete " "%(object_type)s %(object)s?" msgstr "" -#: templates/htmx/delete_form.html:23 +#: netbox/templates/htmx/delete_form.html:23 msgid "The following objects will be deleted as a result of this action." msgstr "" -#: templates/htmx/notifications.html:6 +#: netbox/templates/htmx/notifications.html:6 #, python-format msgid "Dismiss %(count)s unread notification?" msgid_plural "Dismiss %(count)s unread notifications?" msgstr[0] "" msgstr[1] "" -#: templates/htmx/notifications.html:7 +#: netbox/templates/htmx/notifications.html:7 msgid "Dismiss all unread notifications" msgstr "" -#: templates/htmx/notifications.html:9 +#: netbox/templates/htmx/notifications.html:9 msgid "Dismiss all" msgstr "" -#: templates/htmx/notifications.html:26 +#: netbox/templates/htmx/notifications.html:26 msgid "ago" msgstr "" -#: templates/htmx/notifications.html:37 +#: netbox/templates/htmx/notifications.html:37 msgid "No unread notifications" msgstr "" -#: templates/htmx/notifications.html:42 +#: netbox/templates/htmx/notifications.html:42 msgid "All notifications" msgstr "" -#: templates/htmx/object_selector.html:5 +#: netbox/templates/htmx/object_selector.html:5 msgid "Select" msgstr "" -#: templates/htmx/quick_add.html:7 +#: netbox/templates/htmx/quick_add.html:7 msgid "Quick Add" msgstr "" -#: templates/htmx/quick_add_created.html:18 +#: netbox/templates/htmx/quick_add_created.html:18 #, python-format msgid "" "\n" @@ -14498,209 +15063,210 @@ msgid "" " " msgstr "" -#: templates/inc/filter_list.html:40 -#: utilities/templates/helpers/table_config_form.html:39 +#: netbox/templates/inc/filter_list.html:40 +#: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "" -#: templates/inc/light_toggle.html:4 +#: netbox/templates/inc/light_toggle.html:4 msgid "Enable dark mode" msgstr "" -#: templates/inc/light_toggle.html:7 +#: netbox/templates/inc/light_toggle.html:7 msgid "Enable light mode" msgstr "" -#: templates/inc/missing_prerequisites.html:9 +#: netbox/templates/inc/missing_prerequisites.html:9 #, python-format msgid "" "Before you can add a %(model)s you must first create a " "%(prerequisite_model)s." msgstr "" -#: templates/inc/paginator.html:15 +#: netbox/templates/inc/paginator.html:15 msgid "Page selection" msgstr "" -#: templates/inc/paginator.html:75 +#: netbox/templates/inc/paginator.html:75 #, python-format msgid "Showing %(start)s-%(end)s of %(total)s" msgstr "" -#: templates/inc/paginator.html:82 +#: netbox/templates/inc/paginator.html:82 msgid "Pagination options" msgstr "" -#: templates/inc/paginator.html:86 +#: netbox/templates/inc/paginator.html:86 msgid "Per Page" msgstr "" -#: templates/inc/sync_warning.html:10 +#: netbox/templates/inc/sync_warning.html:10 msgid "Data is out of sync with upstream file" msgstr "" -#: templates/inc/table_controls_htmx.html:7 +#: netbox/templates/inc/table_controls_htmx.html:7 msgid "Quick search" msgstr "" -#: templates/inc/table_controls_htmx.html:20 +#: netbox/templates/inc/table_controls_htmx.html:20 msgid "Saved filter" msgstr "" -#: templates/inc/table_htmx.html:18 +#: netbox/templates/inc/table_htmx.html:18 msgid "Clear ordering" msgstr "" -#: templates/inc/user_menu.html:6 +#: netbox/templates/inc/user_menu.html:6 msgid "Help center" msgstr "" -#: templates/inc/user_menu.html:54 +#: netbox/templates/inc/user_menu.html:54 msgid "Log Out" msgstr "" -#: templates/inc/user_menu.html:61 templates/login.html:39 -#: templates/login.html:84 +#: netbox/templates/inc/user_menu.html:61 netbox/templates/login.html:39 +#: netbox/templates/login.html:84 msgid "Log In" msgstr "" -#: templates/ipam/aggregate/prefixes.html:10 -#: templates/ipam/prefix/prefixes.html:10 templates/ipam/role.html:7 +#: netbox/templates/ipam/aggregate/prefixes.html:10 +#: netbox/templates/ipam/prefix/prefixes.html:10 +#: netbox/templates/ipam/role.html:7 msgid "Add Prefix" msgstr "" -#: templates/ipam/attrs/vrf.html:2 +#: netbox/templates/ipam/attrs/vrf.html:2 msgid "Global" msgstr "" -#: templates/ipam/inc/ipaddress_edit_header.html:13 +#: netbox/templates/ipam/inc/ipaddress_edit_header.html:13 msgid "Assign IP" msgstr "" -#: templates/ipam/inc/max_depth.html:6 +#: netbox/templates/ipam/inc/max_depth.html:6 msgid "Max Depth" msgstr "" -#: templates/ipam/inc/max_length.html:6 +#: netbox/templates/ipam/inc/max_length.html:6 msgid "Max Length" msgstr "" -#: templates/ipam/inc/panels/fhrp_groups.html:25 -#: templates/ipam/panels/fhrp_groups.html:11 +#: netbox/templates/ipam/inc/panels/fhrp_groups.html:25 +#: netbox/templates/ipam/panels/fhrp_groups.html:11 msgid "Virtual IPs" msgstr "" -#: templates/ipam/inc/toggle_available.html:7 +#: netbox/templates/ipam/inc/toggle_available.html:7 msgid "Show Assigned" msgstr "" -#: templates/ipam/inc/toggle_available.html:10 +#: netbox/templates/ipam/inc/toggle_available.html:10 msgid "Show Available" msgstr "" -#: templates/ipam/inc/toggle_available.html:13 +#: netbox/templates/ipam/inc/toggle_available.html:13 msgid "Show All" msgstr "" -#: templates/ipam/ipaddress_assign.html:8 +#: netbox/templates/ipam/ipaddress_assign.html:8 msgid "Assign an IP Address" msgstr "" -#: templates/ipam/ipaddress_assign.html:22 +#: netbox/templates/ipam/ipaddress_assign.html:22 msgid "Select IP Address" msgstr "" -#: templates/ipam/ipaddress_assign.html:35 +#: netbox/templates/ipam/ipaddress_assign.html:35 msgid "Search Results" msgstr "" -#: templates/ipam/panels/prefix_addressing.html:8 +#: netbox/templates/ipam/panels/prefix_addressing.html:8 msgid "Addressing Details" msgstr "" -#: templates/ipam/panels/prefix_addressing.html:19 +#: netbox/templates/ipam/panels/prefix_addressing.html:19 msgid "Marked fully utilized" msgstr "" -#: templates/ipam/panels/prefix_addressing.html:27 +#: netbox/templates/ipam/panels/prefix_addressing.html:27 msgid "Child IPs" msgstr "" -#: templates/ipam/panels/prefix_addressing.html:35 +#: netbox/templates/ipam/panels/prefix_addressing.html:35 msgid "Available IPs" msgstr "" -#: templates/ipam/panels/prefix_addressing.html:46 +#: netbox/templates/ipam/panels/prefix_addressing.html:46 msgid "First available IP" msgstr "" -#: templates/ipam/prefix/base.html:20 +#: netbox/templates/ipam/prefix/base.html:20 msgid "Prefix Details" msgstr "" -#: templates/ipam/prefix/base.html:26 +#: netbox/templates/ipam/prefix/base.html:26 msgid "Network Address" msgstr "" -#: templates/ipam/prefix/base.html:30 +#: netbox/templates/ipam/prefix/base.html:30 msgid "Network Mask" msgstr "" -#: templates/ipam/prefix/base.html:34 +#: netbox/templates/ipam/prefix/base.html:34 msgid "Wildcard Mask" msgstr "" -#: templates/ipam/prefix/base.html:38 +#: netbox/templates/ipam/prefix/base.html:38 msgid "Broadcast Address" msgstr "" -#: templates/ipam/prefix/ip_ranges.html:7 +#: netbox/templates/ipam/prefix/ip_ranges.html:7 msgid "Add IP Range" msgstr "" -#: templates/ipam/prefix_list.html:7 +#: netbox/templates/ipam/prefix_list.html:7 msgid "Hide Depth Indicators" msgstr "" -#: templates/ipam/rir.html:7 +#: netbox/templates/ipam/rir.html:7 msgid "Add Aggregate" msgstr "" -#: templates/ipam/vlangroup.html:16 +#: netbox/templates/ipam/vlangroup.html:16 msgid "Add VLAN" msgstr "" -#: templates/login.html:29 -#: utilities/templates/form_helpers/render_errors.html:7 +#: netbox/templates/login.html:29 +#: netbox/utilities/templates/form_helpers/render_errors.html:7 msgid "Errors" msgstr "" -#: templates/login.html:70 +#: netbox/templates/login.html:70 msgid "Sign In" msgstr "" -#: templates/login.html:80 +#: netbox/templates/login.html:80 msgctxt "Denotes an alternative option" msgid "Or" msgstr "" -#: templates/media_failure.html:7 +#: netbox/templates/media_failure.html:7 msgid "Static Media Failure - NetBox" msgstr "" -#: templates/media_failure.html:21 +#: netbox/templates/media_failure.html:21 msgid "Static Media Failure" msgstr "" -#: templates/media_failure.html:23 +#: netbox/templates/media_failure.html:23 msgid "The following static media file failed to load" msgstr "" -#: templates/media_failure.html:26 +#: netbox/templates/media_failure.html:26 msgid "Check the following" msgstr "" -#: templates/media_failure.html:29 +#: netbox/templates/media_failure.html:29 #, python-format msgid "" "%(command)s was run during the most recent upgrade. This " @@ -14708,7 +15274,7 @@ msgid "" "path." msgstr "" -#: templates/media_failure.html:35 +#: netbox/templates/media_failure.html:35 #, python-format msgid "" "The HTTP service (e.g. nginx or Apache) is configured to serve files from " @@ -14716,2333 +15282,2368 @@ msgid "" "installation documentation for further guidance." msgstr "" -#: templates/media_failure.html:47 +#: netbox/templates/media_failure.html:47 #, python-format msgid "" "The file %(filename)s exists in the static root directory and " "is readable by the HTTP server." msgstr "" -#: templates/media_failure.html:55 +#: netbox/templates/media_failure.html:55 #, python-format msgid "" "Click here to attempt loading NetBox again." msgstr "" -#: templates/tenancy/object_contacts.html:8 +#: netbox/templates/tenancy/object_contacts.html:8 msgid "Add a contact" msgstr "" -#: templates/tenancy/tenantgroup.html:14 +#: netbox/templates/tenancy/tenantgroup.html:14 msgid "Add Tenant" msgstr "" -#: templates/ui/attrs/address.html:6 templates/ui/attrs/gps_coordinates.html:6 +#: netbox/templates/ui/attrs/address.html:6 +#: netbox/templates/ui/attrs/gps_coordinates.html:6 msgid "Map" msgstr "" -#: templates/ui/attrs/timezone.html:4 +#: netbox/templates/ui/attrs/timezone.html:4 msgid "UTC" msgstr "" -#: templates/ui/attrs/timezone.html:5 +#: netbox/templates/ui/attrs/timezone.html:5 msgid "Local time" msgstr "" -#: templates/ui/exception.html:8 +#: netbox/templates/ui/exception.html:8 #, python-format msgid "An error occurred when loading content from plugin %(plugin)s:" msgstr "" -#: templates/users/inc/user_activity.html:6 users/views.py:118 +#: netbox/templates/users/inc/new_token_banner.html:8 +msgid "Save this token now. It cannot be retrieved later." +msgstr "" + +#: netbox/templates/users/inc/new_token_banner.html:10 +msgid "" +"\n" +" The full HTTP Authorization header value is shown below. NetBox " +"does not store the token plaintext,\n" +" so this is your only chance to copy it. It will be lost when " +"navigating away from this page.\n" +" " +msgstr "" + +#: netbox/templates/users/inc/user_activity.html:6 netbox/users/views.py:132 msgid "Recent Activity" msgstr "" -#: templates/users/inc/user_activity.html:9 users/views.py:123 +#: netbox/templates/users/inc/user_activity.html:9 netbox/users/views.py:137 msgid "View All" msgstr "" -#: templates/users/objectpermission.html:4 users/forms/filtersets.py:63 +#: netbox/templates/users/objectpermission.html:4 +#: netbox/users/forms/filtersets.py:63 msgid "Permission" msgstr "" -#: templates/users/panels/actions.html:27 users/forms/model_forms.py:347 +#: netbox/templates/users/panels/actions.html:27 +#: netbox/users/forms/model_forms.py:338 msgid "Additional actions" msgstr "" -#: templates/users/token.html:4 users/forms/bulk_import.py:48 -#: users/forms/filtersets.py:117 users/forms/model_forms.py:128 +#: netbox/templates/users/token.html:4 netbox/users/forms/bulk_import.py:48 +#: netbox/users/forms/filtersets.py:117 msgid "Token" msgstr "" -#: templates/virtualization/cluster/base.html:18 -#: templates/virtualization/virtualmachinetype.html:7 +#: netbox/templates/virtualization/cluster/base.html:18 +#: netbox/templates/virtualization/virtualmachinetype.html:7 msgid "Add Virtual Machine" msgstr "" -#: templates/virtualization/cluster/base.html:24 +#: netbox/templates/virtualization/cluster/base.html:24 msgid "Assign Device" msgstr "" -#: templates/virtualization/cluster_add_devices.html:9 +#: netbox/templates/virtualization/cluster_add_devices.html:9 #, python-format msgid "Add Device to Cluster %(cluster)s" msgstr "" -#: templates/virtualization/cluster_add_devices.html:23 +#: netbox/templates/virtualization/cluster_add_devices.html:23 msgid "Device Selection" msgstr "" -#: templates/virtualization/cluster_add_devices.html:31 +#: netbox/templates/virtualization/cluster_add_devices.html:31 msgid "Add Devices" msgstr "" -#: templates/virtualization/clustergroup.html:7 -#: templates/virtualization/clustertype.html:7 +#: netbox/templates/virtualization/clustergroup.html:7 +#: netbox/templates/virtualization/clustertype.html:7 msgid "Add Cluster" msgstr "" -#: templates/virtualization/panels/cluster_resources.html:5 +#: netbox/templates/virtualization/panels/cluster_resources.html:5 msgid "Allocated Resources" msgstr "" -#: templates/virtualization/panels/cluster_resources.html:8 -#: templates/virtualization/panels/virtual_machine_resources.html:8 +#: netbox/templates/virtualization/panels/cluster_resources.html:8 +#: netbox/templates/virtualization/panels/virtual_machine_resources.html:8 msgid "Virtual CPUs" msgstr "" -#: templates/virtualization/panels/cluster_resources.html:12 -#: templates/virtualization/panels/virtual_machine_resources.html:12 -#: virtualization/forms/bulk_edit.py:176 +#: netbox/templates/virtualization/panels/cluster_resources.html:12 +#: netbox/templates/virtualization/panels/virtual_machine_resources.html:12 +#: netbox/virtualization/forms/bulk_edit.py:176 msgid "Memory" msgstr "" -#: templates/virtualization/panels/cluster_resources.html:23 -#: templates/virtualization/panels/virtual_machine_resources.html:23 +#: netbox/templates/virtualization/panels/cluster_resources.html:23 +#: netbox/templates/virtualization/panels/virtual_machine_resources.html:23 msgid "Disk Space" msgstr "" -#: templates/virtualization/panels/virtual_machine_resources.html:5 -#: virtualization/forms/bulk_edit.py:191 -#: virtualization/forms/model_forms.py:268 +#: netbox/templates/virtualization/panels/virtual_machine_resources.html:5 +#: netbox/virtualization/forms/bulk_edit.py:191 +#: netbox/virtualization/forms/model_forms.py:268 msgid "Resources" msgstr "" -#: templates/vpn/attrs/preshared_key.html:3 -#: templates/wireless/attrs/auth_psk.html:3 +#: netbox/templates/vpn/attrs/preshared_key.html:3 +#: netbox/templates/wireless/attrs/auth_psk.html:3 msgid "Show Secret" msgstr "" -#: templates/vpn/tunnel.html:7 +#: netbox/templates/vpn/tunnel.html:7 msgid "Add Termination" msgstr "" -#: templates/vpn/tunnelgroup.html:7 +#: netbox/templates/vpn/tunnelgroup.html:7 msgid "Add Tunnel" msgstr "" -#: templates/wireless/panels/wirelesslink_interface.html:28 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:28 msgid "Channel Frequency" msgstr "" -#: templates/wireless/panels/wirelesslink_interface.html:31 -#: templates/wireless/panels/wirelesslink_interface.html:41 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:31 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:41 msgctxt "Abbreviation for megahertz" msgid "MHz" msgstr "" -#: templates/wireless/panels/wirelesslink_interface.html:38 +#: netbox/templates/wireless/panels/wirelesslink_interface.html:38 msgid "Channel Width" msgstr "" -#: templates/wireless/wirelesslangroup.html:14 +#: netbox/templates/wireless/wirelesslangroup.html:14 msgid "Add Wireless LAN" msgstr "" -#: tenancy/filtersets.py:37 +#: netbox/tenancy/filtersets.py:37 msgid "Parent contact group (ID)" msgstr "" -#: tenancy/filtersets.py:44 +#: netbox/tenancy/filtersets.py:44 msgid "Parent contact group (slug)" msgstr "" -#: tenancy/filtersets.py:50 tenancy/filtersets.py:84 tenancy/filtersets.py:129 +#: netbox/tenancy/filtersets.py:50 netbox/tenancy/filtersets.py:84 +#: netbox/tenancy/filtersets.py:129 msgid "Contact group (ID)" msgstr "" -#: tenancy/filtersets.py:57 tenancy/filtersets.py:91 tenancy/filtersets.py:136 +#: netbox/tenancy/filtersets.py:57 netbox/tenancy/filtersets.py:91 +#: netbox/tenancy/filtersets.py:136 msgid "Contact group (slug)" msgstr "" -#: tenancy/filtersets.py:62 tenancy/filtersets.py:123 +#: netbox/tenancy/filtersets.py:62 netbox/tenancy/filtersets.py:123 msgid "Contact (ID)" msgstr "" -#: tenancy/filtersets.py:141 +#: netbox/tenancy/filtersets.py:141 msgid "Contact role (ID)" msgstr "" -#: tenancy/filtersets.py:148 +#: netbox/tenancy/filtersets.py:148 msgid "Contact role (slug)" msgstr "" -#: tenancy/filtersets.py:168 tenancy/forms/bulk_edit.py:131 -#: tenancy/forms/filtersets.py:100 tenancy/forms/filtersets.py:131 -#: tenancy/forms/forms.py:58 tenancy/forms/model_forms.py:106 -#: tenancy/forms/model_forms.py:130 tenancy/tables/contacts.py:92 +#: netbox/tenancy/filtersets.py:168 netbox/tenancy/forms/bulk_edit.py:131 +#: netbox/tenancy/forms/filtersets.py:100 +#: netbox/tenancy/forms/filtersets.py:131 netbox/tenancy/forms/forms.py:58 +#: netbox/tenancy/forms/model_forms.py:106 +#: netbox/tenancy/forms/model_forms.py:130 netbox/tenancy/tables/contacts.py:92 msgid "Contact" msgstr "" -#: tenancy/filtersets.py:173 tenancy/forms/forms.py:63 -#: tenancy/forms/model_forms.py:83 +#: netbox/tenancy/filtersets.py:173 netbox/tenancy/forms/forms.py:63 +#: netbox/tenancy/forms/model_forms.py:83 msgid "Contact Role" msgstr "" -#: tenancy/filtersets.py:179 +#: netbox/tenancy/filtersets.py:179 msgid "Contact group" msgstr "" -#: tenancy/filtersets.py:192 +#: netbox/tenancy/filtersets.py:192 msgid "Parent tenant group (ID)" msgstr "" -#: tenancy/filtersets.py:199 +#: netbox/tenancy/filtersets.py:199 msgid "Parent tenant group (slug)" msgstr "" -#: tenancy/filtersets.py:205 tenancy/filtersets.py:226 +#: netbox/tenancy/filtersets.py:205 netbox/tenancy/filtersets.py:226 msgid "Tenant group (ID)" msgstr "" -#: tenancy/filtersets.py:259 +#: netbox/tenancy/filtersets.py:259 msgid "Tenant Group (ID)" msgstr "" -#: tenancy/filtersets.py:266 +#: netbox/tenancy/filtersets.py:266 msgid "Tenant Group (slug)" msgstr "" -#: tenancy/forms/bulk_edit.py:84 +#: netbox/tenancy/forms/bulk_edit.py:84 msgid "Add groups" msgstr "" -#: tenancy/forms/bulk_edit.py:89 +#: netbox/tenancy/forms/bulk_edit.py:89 msgid "Remove groups" msgstr "" -#: tenancy/forms/bulk_edit.py:94 +#: netbox/tenancy/forms/bulk_edit.py:94 msgid "Title" msgstr "" -#: tenancy/forms/bulk_edit.py:99 tenancy/tables/contacts.py:61 -#: tenancy/ui/panels.py:15 +#: netbox/tenancy/forms/bulk_edit.py:99 netbox/tenancy/tables/contacts.py:61 +#: netbox/tenancy/ui/panels.py:15 msgid "Phone" msgstr "" -#: tenancy/forms/bulk_import.py:88 +#: netbox/tenancy/forms/bulk_import.py:88 msgid "" "Group names separated by commas, encased with double quotes (e.g. \"Group 1," "Group 2\")" msgstr "" -#: tenancy/forms/bulk_import.py:111 +#: netbox/tenancy/forms/bulk_import.py:111 msgid "Assigned contact" msgstr "" -#: tenancy/forms/filtersets.py:40 tenancy/forms/model_forms.py:32 -#: tenancy/tables/columns.py:37 tenancy/tables/columns.py:47 +#: netbox/tenancy/forms/filtersets.py:40 netbox/tenancy/forms/model_forms.py:32 +#: netbox/tenancy/tables/columns.py:37 netbox/tenancy/tables/columns.py:47 msgid "Tenant Group" msgstr "" -#: tenancy/forms/filtersets.py:76 tenancy/forms/forms.py:68 -#: tenancy/forms/model_forms.py:73 +#: netbox/tenancy/forms/filtersets.py:76 netbox/tenancy/forms/forms.py:68 +#: netbox/tenancy/forms/model_forms.py:73 msgid "Contact Group" msgstr "" -#: tenancy/models/contacts.py:60 +#: netbox/tenancy/models/contacts.py:60 msgid "contact group" msgstr "" -#: tenancy/models/contacts.py:61 +#: netbox/tenancy/models/contacts.py:61 msgid "contact groups" msgstr "" -#: tenancy/models/contacts.py:70 +#: netbox/tenancy/models/contacts.py:70 msgid "contact role" msgstr "" -#: tenancy/models/contacts.py:71 +#: netbox/tenancy/models/contacts.py:71 msgid "contact roles" msgstr "" -#: tenancy/models/contacts.py:90 +#: netbox/tenancy/models/contacts.py:90 msgid "title" msgstr "" -#: tenancy/models/contacts.py:95 +#: netbox/tenancy/models/contacts.py:95 msgid "phone" msgstr "" -#: tenancy/models/contacts.py:100 +#: netbox/tenancy/models/contacts.py:100 msgid "email" msgstr "" -#: tenancy/models/contacts.py:109 +#: netbox/tenancy/models/contacts.py:109 msgid "link" msgstr "" -#: tenancy/models/contacts.py:122 +#: netbox/tenancy/models/contacts.py:122 msgid "contact" msgstr "" -#: tenancy/models/contacts.py:123 +#: netbox/tenancy/models/contacts.py:123 msgid "contacts" msgstr "" -#: tenancy/models/contacts.py:171 +#: netbox/tenancy/models/contacts.py:171 msgid "contact assignment" msgstr "" -#: tenancy/models/contacts.py:172 +#: netbox/tenancy/models/contacts.py:172 msgid "contact assignments" msgstr "" -#: tenancy/models/contacts.py:188 +#: netbox/tenancy/models/contacts.py:188 #, python-brace-format msgid "Contacts cannot be assigned to this object type ({type})." msgstr "" -#: tenancy/models/tenants.py:35 +#: netbox/tenancy/models/tenants.py:35 msgid "tenant group" msgstr "" -#: tenancy/models/tenants.py:36 +#: netbox/tenancy/models/tenants.py:36 msgid "tenant groups" msgstr "" -#: tenancy/models/tenants.py:71 +#: netbox/tenancy/models/tenants.py:71 msgid "Tenant name must be unique per group." msgstr "" -#: tenancy/models/tenants.py:81 +#: netbox/tenancy/models/tenants.py:81 msgid "Tenant slug must be unique per group." msgstr "" -#: tenancy/models/tenants.py:89 +#: netbox/tenancy/models/tenants.py:89 msgid "tenant" msgstr "" -#: tenancy/models/tenants.py:90 +#: netbox/tenancy/models/tenants.py:90 msgid "tenants" msgstr "" -#: tenancy/tables/contacts.py:106 +#: netbox/tenancy/tables/contacts.py:106 msgid "Contact Title" msgstr "" -#: tenancy/tables/contacts.py:110 +#: netbox/tenancy/tables/contacts.py:110 msgid "Contact Phone" msgstr "" -#: tenancy/tables/contacts.py:115 +#: netbox/tenancy/tables/contacts.py:115 msgid "Contact Email" msgstr "" -#: tenancy/tables/contacts.py:119 +#: netbox/tenancy/tables/contacts.py:119 msgid "Contact Address" msgstr "" -#: tenancy/tables/contacts.py:123 +#: netbox/tenancy/tables/contacts.py:123 msgid "Contact Link" msgstr "" -#: tenancy/tables/contacts.py:128 +#: netbox/tenancy/tables/contacts.py:128 msgid "Contact Description" msgstr "" -#: tenancy/views.py:65 +#: netbox/tenancy/views.py:65 msgid "Add Tenant Group" msgstr "" -#: tenancy/views.py:238 +#: netbox/tenancy/views.py:238 msgid "Add Contact Group" msgstr "" -#: users/choices.py:15 +#: netbox/users/choices.py:15 msgid "v1" msgstr "" -#: users/choices.py:16 +#: netbox/users/choices.py:16 msgid "v2" msgstr "" -#: users/filterset_mixins.py:19 +#: netbox/users/filterset_mixins.py:19 msgid "Owner Group (ID)" msgstr "" -#: users/filterset_mixins.py:26 +#: netbox/users/filterset_mixins.py:26 msgid "Owner Group (name)" msgstr "" -#: users/filterset_mixins.py:31 users/filtersets.py:36 users/filtersets.py:88 +#: netbox/users/filterset_mixins.py:31 netbox/users/filtersets.py:36 +#: netbox/users/filtersets.py:88 msgid "Owner (ID)" msgstr "" -#: users/filterset_mixins.py:38 users/filtersets.py:42 users/filtersets.py:94 +#: netbox/users/filterset_mixins.py:38 netbox/users/filtersets.py:42 +#: netbox/users/filtersets.py:94 msgid "Owner (name)" msgstr "" -#: users/filtersets.py:47 users/filtersets.py:99 +#: netbox/users/filtersets.py:47 netbox/users/filtersets.py:99 msgid "Permission (ID)" msgstr "" -#: users/filtersets.py:52 users/filtersets.py:104 +#: netbox/users/filtersets.py:52 netbox/users/filtersets.py:104 msgid "Notification group (ID)" msgstr "" -#: users/filtersets.py:297 +#: netbox/users/filtersets.py:297 msgid "User group (ID)" msgstr "" -#: users/filtersets.py:303 +#: netbox/users/filtersets.py:303 msgid "User group (name)" msgstr "" -#: users/filtersets.py:314 +#: netbox/users/filtersets.py:314 msgid "User (username)" msgstr "" -#: users/forms/bulk_edit.py:29 +#: netbox/users/forms/bulk_edit.py:29 msgid "First name" msgstr "" -#: users/forms/bulk_edit.py:34 +#: netbox/users/forms/bulk_edit.py:34 msgid "Last name" msgstr "" -#: users/forms/bulk_edit.py:46 +#: netbox/users/forms/bulk_edit.py:46 msgid "Superuser status" msgstr "" -#: users/forms/bulk_edit.py:110 +#: netbox/users/forms/bulk_edit.py:110 msgid "Write enabled" msgstr "" -#: users/forms/bulk_edit.py:120 users/forms/filtersets.py:144 -#: users/tables.py:41 +#: netbox/users/forms/bulk_edit.py:120 netbox/users/forms/filtersets.py:144 +#: netbox/users/tables.py:41 msgid "Expires" msgstr "" -#: users/forms/bulk_edit.py:125 users/forms/model_forms.py:140 -#: users/tables.py:47 +#: netbox/users/forms/bulk_edit.py:125 netbox/users/forms/model_forms.py:130 +#: netbox/users/tables.py:47 msgid "Allowed IPs" msgstr "" -#: users/forms/bulk_import.py:45 +#: netbox/users/forms/bulk_import.py:45 msgid "Specify version 1 or 2 (v2 will be used by default)" msgstr "" -#: users/forms/bulk_import.py:50 +#: netbox/users/forms/bulk_import.py:50 msgid "If no token is provided, one will be generated automatically." msgstr "" -#: users/forms/filtersets.py:55 users/tables.py:75 +#: netbox/users/forms/filtersets.py:55 netbox/users/tables.py:75 msgid "Is Superuser" msgstr "" -#: users/forms/filtersets.py:88 users/tables.py:116 +#: netbox/users/forms/filtersets.py:88 netbox/users/tables.py:116 msgid "Can View" msgstr "" -#: users/forms/filtersets.py:95 users/tables.py:120 +#: netbox/users/forms/filtersets.py:95 netbox/users/tables.py:120 msgid "Can Add" msgstr "" -#: users/forms/filtersets.py:102 users/tables.py:124 +#: netbox/users/forms/filtersets.py:102 netbox/users/tables.py:124 msgid "Can Change" msgstr "" -#: users/forms/filtersets.py:109 users/tables.py:128 +#: netbox/users/forms/filtersets.py:109 netbox/users/tables.py:128 msgid "Can Delete" msgstr "" -#: users/forms/filtersets.py:140 users/tables.py:33 +#: netbox/users/forms/filtersets.py:140 netbox/users/tables.py:33 msgid "Write Enabled" msgstr "" -#: users/forms/filtersets.py:149 users/tables.py:44 +#: netbox/users/forms/filtersets.py:149 netbox/users/tables.py:44 msgid "Last Used" msgstr "" -#: users/forms/filtersets.py:166 +#: netbox/users/forms/filtersets.py:166 msgid "Membership" msgstr "" -#: users/forms/model_forms.py:75 +#: netbox/users/forms/model_forms.py:75 msgid "User Interface" msgstr "" -#: users/forms/model_forms.py:130 -msgid "" -"Tokens must be at least 40 characters in length. Be sure to record " -"your token prior to submitting this form, as it will no longer be " -"accessible once the token has been created." -msgstr "" - -#: users/forms/model_forms.py:142 +#: netbox/users/forms/model_forms.py:132 msgid "" "Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for " "no restrictions. Example: 10.1.1.0/24,192.168.10.16/32,2001:" "db8:1::/64" msgstr "" -#: users/forms/model_forms.py:205 +#: netbox/users/forms/model_forms.py:196 msgid "Confirm password" msgstr "" -#: users/forms/model_forms.py:208 +#: netbox/users/forms/model_forms.py:199 msgid "Enter the same password as before, for verification." msgstr "" -#: users/forms/model_forms.py:257 +#: netbox/users/forms/model_forms.py:248 msgid "Passwords do not match! Please check your input and try again." msgstr "" -#: users/forms/model_forms.py:332 +#: netbox/users/forms/model_forms.py:323 msgid "Select the types of objects to which the permission will apply." msgstr "" -#: users/forms/model_forms.py:350 +#: netbox/users/forms/model_forms.py:341 msgid "" "Additional actions for models which have not yet registered their own actions" msgstr "" -#: users/forms/model_forms.py:364 users/forms/model_forms.py:380 -#: users/forms/model_forms.py:422 users/views.py:278 +#: netbox/users/forms/model_forms.py:355 netbox/users/forms/model_forms.py:371 +#: netbox/users/forms/model_forms.py:413 netbox/users/views.py:292 msgid "Constraints" msgstr "" -#: users/forms/model_forms.py:366 +#: netbox/users/forms/model_forms.py:357 msgid "" "JSON expression of a queryset filter that will return only permitted " "objects. Leave null to match all objects of this type. A list of multiple " "objects will result in a logical OR operation." msgstr "" -#: users/forms/model_forms.py:374 users/forms/model_forms.py:414 +#: netbox/users/forms/model_forms.py:365 netbox/users/forms/model_forms.py:405 msgid "Objects" msgstr "" -#: users/forms/model_forms.py:501 +#: netbox/users/forms/model_forms.py:492 msgid "At least one action must be selected." msgstr "" -#: users/forms/model_forms.py:519 +#: netbox/users/forms/model_forms.py:510 #, python-brace-format msgid "Invalid filter for {model}: {error}" msgstr "" -#: users/forms/model_forms.py:559 +#: netbox/users/forms/model_forms.py:550 msgid "User groups" msgstr "" -#: users/models/owners.py:26 +#: netbox/users/models/owners.py:26 msgid "owner group" msgstr "" -#: users/models/owners.py:27 +#: netbox/users/models/owners.py:27 msgid "owner groups" msgstr "" -#: users/models/owners.py:46 users/models/users.py:65 vpn/models/crypto.py:43 +#: netbox/users/models/owners.py:46 netbox/users/models/users.py:65 +#: netbox/vpn/models/crypto.py:43 msgid "group" msgstr "" -#: users/models/owners.py:70 +#: netbox/users/models/owners.py:70 msgid "owner" msgstr "" -#: users/models/owners.py:71 +#: netbox/users/models/owners.py:71 msgid "owners" msgstr "" -#: users/models/permissions.py:41 +#: netbox/users/models/permissions.py:41 msgid "The list of actions granted by this permission" msgstr "" -#: users/models/permissions.py:46 +#: netbox/users/models/permissions.py:46 msgid "constraints" msgstr "" -#: users/models/permissions.py:47 +#: netbox/users/models/permissions.py:47 msgid "Queryset filter matching the applicable objects of the selected type(s)" msgstr "" -#: users/models/permissions.py:61 +#: netbox/users/models/permissions.py:61 msgid "permission" msgstr "" -#: users/models/permissions.py:62 users/models/users.py:55 +#: netbox/users/models/permissions.py:62 netbox/users/models/users.py:55 msgid "permissions" msgstr "" -#: users/models/preferences.py:29 users/models/preferences.py:30 +#: netbox/users/models/preferences.py:29 netbox/users/models/preferences.py:30 msgid "user preferences" msgstr "" -#: users/models/preferences.py:97 +#: netbox/users/models/preferences.py:97 #, python-brace-format msgid "Key '{path}' is a leaf node; cannot assign new keys" msgstr "" -#: users/models/preferences.py:109 +#: netbox/users/models/preferences.py:109 #, python-brace-format msgid "Key '{path}' is a dictionary; cannot assign a non-dictionary value" msgstr "" -#: users/models/tokens.py:36 vpn/models/crypto.py:75 +#: netbox/users/models/tokens.py:36 netbox/vpn/models/crypto.py:75 msgid "version" msgstr "" -#: users/models/tokens.py:55 +#: netbox/users/models/tokens.py:55 msgid "expires" msgstr "" -#: users/models/tokens.py:60 +#: netbox/users/models/tokens.py:60 msgid "last used" msgstr "" -#: users/models/tokens.py:67 +#: netbox/users/models/tokens.py:67 msgid "Disable to temporarily revoke this token without deleting it." msgstr "" -#: users/models/tokens.py:70 +#: netbox/users/models/tokens.py:70 msgid "write enabled" msgstr "" -#: users/models/tokens.py:72 +#: netbox/users/models/tokens.py:72 msgid "Permit create/update/delete operations using this token" msgstr "" -#: users/models/tokens.py:76 +#: netbox/users/models/tokens.py:76 msgid "plaintext" msgstr "" -#: users/models/tokens.py:84 +#: netbox/users/models/tokens.py:84 msgid "key" msgstr "" -#: users/models/tokens.py:90 +#: netbox/users/models/tokens.py:90 msgid "v2 token identification key" msgstr "" -#: users/models/tokens.py:93 +#: netbox/users/models/tokens.py:93 msgid "pepper ID" msgstr "" -#: users/models/tokens.py:96 +#: netbox/users/models/tokens.py:96 msgid "ID of the cryptographic pepper used to hash the token (v2 only)" msgstr "" -#: users/models/tokens.py:99 +#: netbox/users/models/tokens.py:99 msgid "digest" msgstr "" -#: users/models/tokens.py:103 +#: netbox/users/models/tokens.py:103 msgid "SHA256 hash of the token and pepper (v2 only)" msgstr "" -#: users/models/tokens.py:109 +#: netbox/users/models/tokens.py:109 msgid "allowed IPs" msgstr "" -#: users/models/tokens.py:111 +#: netbox/users/models/tokens.py:111 msgid "" "Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for " "no restrictions. Ex: \"10.1.1.0/24, 192.168.10.16/32, 2001:DB8:1::/64\"" msgstr "" -#: users/models/tokens.py:123 users/tables.py:25 +#: netbox/users/models/tokens.py:123 netbox/users/tables.py:25 msgid "token" msgstr "" -#: users/models/tokens.py:124 +#: netbox/users/models/tokens.py:124 msgid "tokens" msgstr "" -#: users/models/tokens.py:221 +#: netbox/users/models/tokens.py:221 msgid "Unable to save v2 tokens: API_TOKEN_PEPPERS is not defined." msgstr "" -#: users/models/tokens.py:226 +#: netbox/users/models/tokens.py:226 #, python-brace-format msgid "Invalid pepper ID: {id}. Check configured API_TOKEN_PEPPERS." msgstr "" -#: users/models/tokens.py:239 +#: netbox/users/models/tokens.py:239 #, python-brace-format msgid "" "Expiration time must be in the future. Current server time is {current_time} " "({timezone})." msgstr "" -#: users/models/users.py:115 +#: netbox/users/models/users.py:115 msgid "username" msgstr "" -#: users/models/users.py:118 +#: netbox/users/models/users.py:118 msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." msgstr "" -#: users/models/users.py:121 +#: netbox/users/models/users.py:121 msgid "A user with that username already exists." msgstr "" -#: users/models/users.py:125 +#: netbox/users/models/users.py:125 msgid "first name" msgstr "" -#: users/models/users.py:130 +#: netbox/users/models/users.py:130 msgid "last name" msgstr "" -#: users/models/users.py:135 +#: netbox/users/models/users.py:135 msgid "email address" msgstr "" -#: users/models/users.py:139 +#: netbox/users/models/users.py:139 msgid "active" msgstr "" -#: users/models/users.py:142 +#: netbox/users/models/users.py:142 msgid "" "Designates whether this user should be treated as active. Unselect this " "instead of deleting accounts." msgstr "" -#: users/models/users.py:146 +#: netbox/users/models/users.py:146 msgid "date joined" msgstr "" -#: users/models/users.py:171 +#: netbox/users/models/users.py:171 msgid "user" msgstr "" -#: users/models/users.py:186 +#: netbox/users/models/users.py:186 msgid "A user with this username already exists." msgstr "" -#: users/tables.py:132 +#: netbox/users/tables.py:132 msgid "Custom Actions" msgstr "" -#: users/ui/panels.py:22 +#: netbox/users/ui/panels.py:22 msgid "Example Usage" msgstr "" -#: users/ui/panels.py:32 +#: netbox/users/ui/panels.py:32 msgid "Full name" msgstr "" -#: users/ui/panels.py:36 +#: netbox/users/ui/panels.py:36 msgid "Account created" msgstr "" -#: users/ui/panels.py:37 +#: netbox/users/ui/panels.py:37 msgid "Last login" msgstr "" -#: users/ui/panels.py:56 +#: netbox/users/ui/panels.py:56 msgid "View" msgstr "" -#: users/views.py:108 users/views.py:209 +#: netbox/users/views.py:122 netbox/users/views.py:223 msgid "Assigned Permissions" msgstr "" -#: users/views.py:112 users/views.py:213 +#: netbox/users/views.py:126 netbox/users/views.py:227 msgid "Owner Membership" msgstr "" -#: users/views.py:283 +#: netbox/users/views.py:297 msgid "Assigned Users" msgstr "" -#: utilities/api.py:207 +#: netbox/utilities/api.py:207 #, python-brace-format msgid "Related object not found using the provided attributes: {params}" msgstr "" -#: utilities/api.py:210 +#: netbox/utilities/api.py:210 #, python-brace-format msgid "Multiple objects match the provided attributes: {params}" msgstr "" -#: utilities/api.py:222 +#: netbox/utilities/api.py:222 #, python-brace-format msgid "" "Related objects must be referenced by numeric ID or by dictionary of " "attributes. Received an unrecognized value: {value}" msgstr "" -#: utilities/api.py:231 +#: netbox/utilities/api.py:231 #, python-brace-format msgid "Related object not found using the provided numeric ID: {id}" msgstr "" -#: utilities/choices.py:24 +#: netbox/utilities/choices.py:24 #, python-brace-format msgid "{name} has a key defined but CHOICES is not a list" msgstr "" -#: utilities/conversion.py:20 +#: netbox/utilities/conversion.py:20 msgid "Weight must be a positive number" msgstr "" -#: utilities/conversion.py:22 +#: netbox/utilities/conversion.py:22 #, python-brace-format msgid "Invalid value '{weight}' for weight (must be a number)" msgstr "" -#: utilities/conversion.py:33 utilities/conversion.py:64 +#: netbox/utilities/conversion.py:33 netbox/utilities/conversion.py:64 #, python-brace-format msgid "Unknown unit {unit}. Must be one of the following: {valid_units}" msgstr "" -#: utilities/conversion.py:47 +#: netbox/utilities/conversion.py:47 #, python-brace-format msgid "Invalid value '{length}' for length (must be a number)" msgstr "" -#: utilities/conversion.py:49 +#: netbox/utilities/conversion.py:49 msgid "Length must be a positive number" msgstr "" -#: utilities/error_handlers.py:31 +#: netbox/utilities/error_handlers.py:31 #, python-brace-format msgid "" "Unable to delete {objects}. {count} dependent objects were " "found: " msgstr "" -#: utilities/error_handlers.py:33 +#: netbox/utilities/error_handlers.py:33 msgid "More than 50" msgstr "" -#: utilities/export.py:27 utilities/export.py:61 +#: netbox/utilities/export.py:27 netbox/utilities/export.py:61 #, python-brace-format msgid "Invalid delimiter name: {name}" msgstr "" -#: utilities/fields.py:160 +#: netbox/utilities/fields.py:160 #, python-format msgid "" "%s(%r) is invalid. to_model parameter to CounterCacheField must be a string " "in the format 'app.model'" msgstr "" -#: utilities/fields.py:170 +#: netbox/utilities/fields.py:170 #, python-format msgid "" "%s(%r) is invalid. to_field parameter to CounterCacheField must be a string " "in the format 'field'" msgstr "" -#: utilities/forms/bulk_import.py:25 +#: netbox/utilities/forms/bulk_import.py:25 msgid "Enter object data in CSV, JSON or YAML format." msgstr "" -#: utilities/forms/bulk_import.py:39 +#: netbox/utilities/forms/bulk_import.py:39 msgid "The character which delimits CSV fields. Applies only to CSV format." msgstr "" -#: utilities/forms/bulk_import.py:53 +#: netbox/utilities/forms/bulk_import.py:53 msgid "Form data must be empty when uploading/selecting a file." msgstr "" -#: utilities/forms/bulk_import.py:82 +#: netbox/utilities/forms/bulk_import.py:82 #, python-brace-format msgid "Unknown data format: {format}" msgstr "" -#: utilities/forms/bulk_import.py:102 +#: netbox/utilities/forms/bulk_import.py:102 msgid "Unable to detect data format. Please specify." msgstr "" -#: utilities/forms/bulk_import.py:125 +#: netbox/utilities/forms/bulk_import.py:125 msgid "Invalid CSV delimiter" msgstr "" -#: utilities/forms/bulk_import.py:169 +#: netbox/utilities/forms/bulk_import.py:169 msgid "" "Invalid YAML data. Data must be in the form of multiple documents, or a " "single document comprising a list of dictionaries." msgstr "" -#: utilities/forms/fields/array.py:21 +#: netbox/utilities/forms/fields/array.py:21 #, python-brace-format msgid "" "Invalid list ({value}). Must be numeric and ranges must be in ascending " "order." msgstr "" -#: utilities/forms/fields/array.py:42 +#: netbox/utilities/forms/fields/array.py:42 #, python-brace-format msgid "" "Specify one or more individual numbers or numeric ranges separated by " "commas. Example: {example}" msgstr "" -#: utilities/forms/fields/array.py:50 +#: netbox/utilities/forms/fields/array.py:50 #, python-brace-format msgid "" "Invalid ranges ({value}). Must be a range of integers in ascending order." msgstr "" -#: utilities/forms/fields/csv.py:59 +#: netbox/utilities/forms/fields/csv.py:59 #, python-brace-format msgid "Invalid value for a multiple choice field: {value}" msgstr "" -#: utilities/forms/fields/csv.py:77 utilities/forms/fields/csv.py:98 +#: netbox/utilities/forms/fields/csv.py:77 +#: netbox/utilities/forms/fields/csv.py:98 #, python-format msgid "Object not found: %(value)s" msgstr "" -#: utilities/forms/fields/csv.py:85 +#: netbox/utilities/forms/fields/csv.py:85 #, python-brace-format msgid "" "\"{value}\" is not a unique value for this field; multiple objects were found" msgstr "" -#: utilities/forms/fields/csv.py:89 +#: netbox/utilities/forms/fields/csv.py:89 #, python-brace-format msgid "\"{field_name}\" is an invalid accessor field name." msgstr "" -#: utilities/forms/fields/csv.py:122 +#: netbox/utilities/forms/fields/csv.py:122 msgid "Object type must be specified as \".\"" msgstr "" -#: utilities/forms/fields/csv.py:126 +#: netbox/utilities/forms/fields/csv.py:126 msgid "Invalid object type" msgstr "" -#: utilities/forms/fields/expandable.py:26 +#: netbox/utilities/forms/fields/expandable.py:27 msgid "" "Alphanumeric ranges are supported for bulk creation. Mixed cases and types " "within a single range are not supported (example: [ge,xe]-0/0/[0-9])." msgstr "" -#: utilities/forms/fields/expandable.py:52 +#: netbox/utilities/forms/fields/expandable.py:53 msgid "" "Use bracket notation to specify numeric ranges for bulk creation (CIDR " "required).
Examples: 192.0.2.[1-10]/32, 10." "[0-3,10-13].0.0/16, 2001:db8:[a-f]::/64" msgstr "" -#: utilities/forms/fields/fields.py:65 +#: netbox/utilities/forms/fields/fields.py:65 #, python-brace-format msgid "" " Markdown syntax is supported" msgstr "" -#: utilities/forms/fields/fields.py:82 +#: netbox/utilities/forms/fields/fields.py:82 msgid "URL-friendly unique shorthand" msgstr "" -#: utilities/forms/fields/fields.py:147 +#: netbox/utilities/forms/fields/fields.py:147 msgid "Enter context data in JSON format." msgstr "" -#: utilities/forms/fields/fields.py:168 +#: netbox/utilities/forms/fields/fields.py:168 msgid "MAC address must be in EUI-48 format" msgstr "" -#: utilities/forms/forms.py:78 +#: netbox/utilities/forms/forms.py:78 msgid "Use regular expressions" msgstr "" -#: utilities/forms/forms.py:121 +#: netbox/utilities/forms/forms.py:121 msgid "" "Numeric ID of an existing object to update (if not creating a new object)" msgstr "" -#: utilities/forms/forms.py:138 +#: netbox/utilities/forms/forms.py:138 #, python-brace-format msgid "Unrecognized header: {name}" msgstr "" -#: utilities/forms/mixins.py:28 utilities/forms/mixins.py:40 -#: utilities/forms/mixins.py:50 utilities/forms/mixins.py:60 -#: utilities/forms/mixins.py:70 utilities/forms/mixins.py:76 -#: utilities/forms/mixins.py:88 utilities/forms/mixins.py:94 +#: netbox/utilities/forms/mixins.py:28 netbox/utilities/forms/mixins.py:40 +#: netbox/utilities/forms/mixins.py:50 netbox/utilities/forms/mixins.py:60 +#: netbox/utilities/forms/mixins.py:70 netbox/utilities/forms/mixins.py:76 +#: netbox/utilities/forms/mixins.py:88 netbox/utilities/forms/mixins.py:94 msgid "is" msgstr "" -#: utilities/forms/mixins.py:29 utilities/forms/mixins.py:41 -#: utilities/forms/mixins.py:51 utilities/forms/mixins.py:61 -#: utilities/forms/mixins.py:71 utilities/forms/mixins.py:77 -#: utilities/forms/mixins.py:89 utilities/forms/mixins.py:95 +#: netbox/utilities/forms/mixins.py:29 netbox/utilities/forms/mixins.py:41 +#: netbox/utilities/forms/mixins.py:51 netbox/utilities/forms/mixins.py:61 +#: netbox/utilities/forms/mixins.py:71 netbox/utilities/forms/mixins.py:77 +#: netbox/utilities/forms/mixins.py:89 netbox/utilities/forms/mixins.py:95 msgid "is not" msgstr "" -#: utilities/forms/mixins.py:30 +#: netbox/utilities/forms/mixins.py:30 msgid "contains" msgstr "" -#: utilities/forms/mixins.py:31 +#: netbox/utilities/forms/mixins.py:31 msgid "starts with" msgstr "" -#: utilities/forms/mixins.py:32 +#: netbox/utilities/forms/mixins.py:32 msgid "ends with" msgstr "" -#: utilities/forms/mixins.py:33 +#: netbox/utilities/forms/mixins.py:33 msgid "equals (case-insensitive)" msgstr "" -#: utilities/forms/mixins.py:34 +#: netbox/utilities/forms/mixins.py:34 msgid "matches pattern" msgstr "" -#: utilities/forms/mixins.py:35 +#: netbox/utilities/forms/mixins.py:35 msgid "matches pattern (case-insensitive)" msgstr "" -#: utilities/forms/mixins.py:36 utilities/forms/mixins.py:46 -#: utilities/forms/mixins.py:56 utilities/forms/mixins.py:66 -#: utilities/forms/mixins.py:72 utilities/forms/mixins.py:78 -#: utilities/forms/mixins.py:84 utilities/forms/mixins.py:90 -#: utilities/forms/mixins.py:96 +#: netbox/utilities/forms/mixins.py:36 netbox/utilities/forms/mixins.py:46 +#: netbox/utilities/forms/mixins.py:56 netbox/utilities/forms/mixins.py:66 +#: netbox/utilities/forms/mixins.py:72 netbox/utilities/forms/mixins.py:78 +#: netbox/utilities/forms/mixins.py:84 netbox/utilities/forms/mixins.py:90 +#: netbox/utilities/forms/mixins.py:96 msgid "is empty" msgstr "" -#: utilities/forms/mixins.py:37 utilities/forms/mixins.py:47 -#: utilities/forms/mixins.py:57 utilities/forms/mixins.py:67 -#: utilities/forms/mixins.py:73 utilities/forms/mixins.py:79 -#: utilities/forms/mixins.py:85 utilities/forms/mixins.py:91 -#: utilities/forms/mixins.py:97 +#: netbox/utilities/forms/mixins.py:37 netbox/utilities/forms/mixins.py:47 +#: netbox/utilities/forms/mixins.py:57 netbox/utilities/forms/mixins.py:67 +#: netbox/utilities/forms/mixins.py:73 netbox/utilities/forms/mixins.py:79 +#: netbox/utilities/forms/mixins.py:85 netbox/utilities/forms/mixins.py:91 +#: netbox/utilities/forms/mixins.py:97 msgid "is not empty" msgstr "" -#: utilities/forms/mixins.py:42 utilities/forms/mixins.py:52 +#: netbox/utilities/forms/mixins.py:42 netbox/utilities/forms/mixins.py:52 msgid "greater than" msgstr "" -#: utilities/forms/mixins.py:43 utilities/forms/mixins.py:53 +#: netbox/utilities/forms/mixins.py:43 netbox/utilities/forms/mixins.py:53 msgid "at least" msgstr "" -#: utilities/forms/mixins.py:44 utilities/forms/mixins.py:54 +#: netbox/utilities/forms/mixins.py:44 netbox/utilities/forms/mixins.py:54 msgid "less than" msgstr "" -#: utilities/forms/mixins.py:45 utilities/forms/mixins.py:55 +#: netbox/utilities/forms/mixins.py:45 netbox/utilities/forms/mixins.py:55 msgid "at most" msgstr "" -#: utilities/forms/mixins.py:62 +#: netbox/utilities/forms/mixins.py:62 msgid "after" msgstr "" -#: utilities/forms/mixins.py:63 +#: netbox/utilities/forms/mixins.py:63 msgid "on or after" msgstr "" -#: utilities/forms/mixins.py:64 +#: netbox/utilities/forms/mixins.py:64 msgid "before" msgstr "" -#: utilities/forms/mixins.py:65 +#: netbox/utilities/forms/mixins.py:65 msgid "on or before" msgstr "" -#: utilities/forms/mixins.py:82 +#: netbox/utilities/forms/mixins.py:82 msgid "has these tags" msgstr "" -#: utilities/forms/mixins.py:83 +#: netbox/utilities/forms/mixins.py:83 msgid "does not have these tags" msgstr "" -#: utilities/forms/mixins.py:104 +#: netbox/utilities/forms/mixins.py:104 msgid "Background job" msgstr "" -#: utilities/forms/mixins.py:105 +#: netbox/utilities/forms/mixins.py:105 msgid "Execute this task via a background job" msgstr "" -#: utilities/forms/mixins.py:152 +#: netbox/utilities/forms/mixins.py:152 msgid "" "This object has been modified since the form was rendered. Please consult " "the object's change log for details." msgstr "" -#: utilities/forms/utils.py:44 utilities/forms/utils.py:70 -#: utilities/forms/utils.py:87 utilities/forms/utils.py:89 +#: netbox/utilities/forms/utils.py:45 netbox/utilities/forms/utils.py:71 +#: netbox/utilities/forms/utils.py:88 netbox/utilities/forms/utils.py:90 #, python-brace-format msgid "Range \"{value}\" is invalid." msgstr "" -#: utilities/forms/utils.py:76 +#: netbox/utilities/forms/utils.py:77 #, python-brace-format msgid "" "Invalid range: Ending value ({end}) must be greater than beginning value " "({begin})." msgstr "" -#: utilities/forms/utils.py:244 +#: netbox/utilities/forms/utils.py:245 #, python-brace-format msgid "Duplicate or conflicting column header for \"{field}\"" msgstr "" -#: utilities/forms/utils.py:250 +#: netbox/utilities/forms/utils.py:251 #, python-brace-format msgid "Duplicate or conflicting column header for \"{header}\"" msgstr "" -#: utilities/forms/utils.py:259 +#: netbox/utilities/forms/utils.py:260 #, python-brace-format msgid "Row {row}: Expected {count_expected} columns but found {count_found}" msgstr "" -#: utilities/forms/utils.py:282 +#: netbox/utilities/forms/utils.py:283 #, python-brace-format msgid "Unexpected column header \"{field}\" found." msgstr "" -#: utilities/forms/utils.py:284 +#: netbox/utilities/forms/utils.py:285 #, python-brace-format msgid "Column \"{field}\" is not a related object; cannot use dots" msgstr "" -#: utilities/forms/utils.py:288 +#: netbox/utilities/forms/utils.py:289 #, python-brace-format msgid "Invalid related object attribute for column \"{field}\": {to_field}" msgstr "" -#: utilities/forms/utils.py:296 +#: netbox/utilities/forms/utils.py:297 #, python-brace-format msgid "Required column header \"{header}\" not found." msgstr "" -#: utilities/forms/widgets/apiselect.py:132 +#: netbox/utilities/forms/widgets/apiselect.py:132 #, python-brace-format msgid "Missing required value for dynamic query param: '{dynamic_params}'" msgstr "" -#: utilities/forms/widgets/apiselect.py:149 +#: netbox/utilities/forms/widgets/apiselect.py:149 #, python-brace-format msgid "Missing required value for static query param: '{static_params}'" msgstr "" -#: utilities/forms/widgets/modifiers.py:155 +#: netbox/utilities/forms/widgets/modifiers.py:155 msgid "(automatically set)" msgstr "" -#: utilities/jobs.py:42 +#: netbox/utilities/jobs.py:42 #, python-brace-format msgid "Created background job {id}: {name}" msgstr "" -#: utilities/jsonschema.py:162 +#: netbox/utilities/jsonschema.py:162 msgid "Invalid JSON schema definition" msgstr "" -#: utilities/jsonschema.py:167 +#: netbox/utilities/jsonschema.py:167 #, python-brace-format msgid "Invalid JSON schema definition: {error}" msgstr "" -#: utilities/password_validation.py:13 +#: netbox/utilities/password_validation.py:13 msgid "Password must have at least one numeral." msgstr "" -#: utilities/password_validation.py:18 +#: netbox/utilities/password_validation.py:18 msgid "Password must have at least one uppercase letter." msgstr "" -#: utilities/password_validation.py:23 +#: netbox/utilities/password_validation.py:23 msgid "Password must have at least one lowercase letter." msgstr "" -#: utilities/password_validation.py:27 +#: netbox/utilities/password_validation.py:27 msgid "" "Your password must contain at least one numeral, one uppercase letter and " "one lowercase letter." msgstr "" -#: utilities/permissions.py:89 +#: netbox/utilities/permissions.py:89 #, python-brace-format msgid "" "Invalid permission name: {name}. Must be in the format ." "_" msgstr "" -#: utilities/permissions.py:107 +#: netbox/utilities/permissions.py:107 #, python-brace-format msgid "Unknown app_label/model_name for {name}" msgstr "" -#: utilities/request.py:95 +#: netbox/utilities/request.py:95 #, python-brace-format msgid "Invalid IP address set for {header}: {ip}" msgstr "" -#: utilities/tables.py:76 +#: netbox/utilities/tables.py:76 #, python-brace-format msgid "A column named {name} is already defined for table {table_name}" msgstr "" -#: utilities/templates/builtins/customfield_value.html:50 +#: netbox/utilities/templates/builtins/customfield_value.html:50 msgid "Not defined" msgstr "" -#: utilities/templates/buttons/bookmark.html:9 +#: netbox/utilities/templates/buttons/bookmark.html:9 msgid "Unbookmark" msgstr "" -#: utilities/templates/buttons/bookmark.html:13 +#: netbox/utilities/templates/buttons/bookmark.html:13 msgid "Bookmark" msgstr "" -#: utilities/templates/buttons/export.html:7 +#: netbox/utilities/templates/buttons/export.html:7 msgid "Current View" msgstr "" -#: utilities/templates/buttons/export.html:8 +#: netbox/utilities/templates/buttons/export.html:8 msgid "All Data" msgstr "" -#: utilities/templates/buttons/export.html:28 +#: netbox/utilities/templates/buttons/export.html:28 msgid "Add export template" msgstr "" -#: utilities/templates/buttons/subscribe.html:10 +#: netbox/utilities/templates/buttons/subscribe.html:10 msgid "Unsubscribe" msgstr "" -#: utilities/templates/buttons/subscribe.html:14 +#: netbox/utilities/templates/buttons/subscribe.html:14 msgid "Subscribe" msgstr "" -#: utilities/templates/form_helpers/render_field.html:66 +#: netbox/utilities/templates/form_helpers/render_field.html:66 msgid "Set Null" msgstr "" -#: utilities/templates/helpers/applied_filters.html:11 +#: netbox/utilities/templates/helpers/applied_filters.html:11 msgid "Clear all" msgstr "" -#: utilities/templates/navigation/menu.html:14 +#: netbox/utilities/templates/navigation/menu.html:14 msgid "Search…" msgstr "" -#: utilities/templates/navigation/menu.html:14 +#: netbox/utilities/templates/navigation/menu.html:14 msgid "Search NetBox" msgstr "" -#: utilities/templates/widgets/apiselect.html:8 +#: netbox/utilities/templates/widgets/apiselect.html:8 msgid "Open selector" msgstr "" -#: utilities/templates/widgets/apiselect.html:22 +#: netbox/utilities/templates/widgets/apiselect.html:22 msgid "Quick add" msgstr "" -#: utilities/templates/widgets/markdown_input.html:6 +#: netbox/utilities/templates/widgets/markdown_input.html:6 msgid "Write" msgstr "" -#: utilities/templates/widgets/splitmultiselect.html:19 +#: netbox/utilities/templates/widgets/splitmultiselect.html:19 msgid "Selected" msgstr "" -#: utilities/testing/views.py:725 +#: netbox/utilities/testing/views.py:725 msgid "The test must define csv_update_data." msgstr "" -#: utilities/validators.py:71 +#: netbox/utilities/validators.py:71 #, python-brace-format msgid "{value} must be a multiple of {multiple}." msgstr "" -#: utilities/validators.py:83 +#: netbox/utilities/validators.py:83 #, python-brace-format msgid "{value} is not a valid regular expression." msgstr "" -#: utilities/views.py:84 +#: netbox/utilities/views.py:84 #, python-brace-format msgid "{self.__class__.__name__} must implement get_required_permission()" msgstr "" -#: utilities/views.py:120 +#: netbox/utilities/views.py:120 #, python-brace-format msgid "{class_name} must implement get_required_permission()" msgstr "" -#: utilities/views.py:144 +#: netbox/utilities/views.py:144 #, python-brace-format msgid "" "{class_name} has no queryset defined. ObjectPermissionRequiredMixin may only " "be used on views which define a base queryset" msgstr "" -#: virtualization/choices.py:50 +#: netbox/virtualization/choices.py:50 msgid "Paused" msgstr "" -#: virtualization/choices.py:62 +#: netbox/virtualization/choices.py:62 msgid "On" msgstr "" -#: virtualization/choices.py:63 +#: netbox/virtualization/choices.py:63 msgid "Off" msgstr "" -#: virtualization/choices.py:64 +#: netbox/virtualization/choices.py:64 msgid "Last State" msgstr "" -#: virtualization/filtersets.py:54 +#: netbox/virtualization/filtersets.py:54 msgid "Parent group (ID)" msgstr "" -#: virtualization/filtersets.py:61 +#: netbox/virtualization/filtersets.py:61 msgid "Parent group (slug)" msgstr "" -#: virtualization/filtersets.py:66 virtualization/filtersets.py:181 +#: netbox/virtualization/filtersets.py:66 +#: netbox/virtualization/filtersets.py:181 msgid "Cluster type (ID)" msgstr "" -#: virtualization/filtersets.py:145 +#: netbox/virtualization/filtersets.py:145 msgid "Virtual machine type (ID)" msgstr "" -#: virtualization/filtersets.py:152 +#: netbox/virtualization/filtersets.py:152 msgid "Virtual machine type (slug)" msgstr "" -#: virtualization/filtersets.py:193 virtualization/filtersets.py:334 +#: netbox/virtualization/filtersets.py:193 +#: netbox/virtualization/filtersets.py:334 msgid "Cluster (ID)" msgstr "" -#: virtualization/forms/bulk_edit.py:92 virtualization/forms/filtersets.py:127 -#: virtualization/ui/panels.py:28 +#: netbox/virtualization/forms/bulk_edit.py:92 +#: netbox/virtualization/forms/filtersets.py:127 +#: netbox/virtualization/ui/panels.py:28 msgid "Default vCPUs" msgstr "" -#: virtualization/forms/bulk_edit.py:96 +#: netbox/virtualization/forms/bulk_edit.py:96 msgid "Default Memory (MB)" msgstr "" -#: virtualization/forms/bulk_edit.py:102 -#: virtualization/forms/model_forms.py:184 +#: netbox/virtualization/forms/bulk_edit.py:102 +#: netbox/virtualization/forms/model_forms.py:184 msgid "Virtual Machine Type" msgstr "" -#: virtualization/forms/bulk_edit.py:103 -#: virtualization/forms/model_forms.py:185 +#: netbox/virtualization/forms/bulk_edit.py:103 +#: netbox/virtualization/forms/model_forms.py:185 msgid "Defaults" msgstr "" -#: virtualization/forms/bulk_edit.py:112 -#: virtualization/forms/bulk_import.py:106 -#: virtualization/forms/filtersets.py:168 +#: netbox/virtualization/forms/bulk_edit.py:112 +#: netbox/virtualization/forms/bulk_import.py:106 +#: netbox/virtualization/forms/filtersets.py:168 msgid "Virtual machine type" msgstr "" -#: virtualization/forms/bulk_edit.py:123 -#: virtualization/forms/bulk_import.py:118 -#: virtualization/forms/filtersets.py:227 -#: virtualization/tables/virtualmachines.py:70 +#: netbox/virtualization/forms/bulk_edit.py:123 +#: netbox/virtualization/forms/bulk_import.py:118 +#: netbox/virtualization/forms/filtersets.py:227 +#: netbox/virtualization/tables/virtualmachines.py:70 msgid "Start on boot" msgstr "" -#: virtualization/forms/bulk_edit.py:172 -#: virtualization/models/virtualmachines.py:205 +#: netbox/virtualization/forms/bulk_edit.py:172 +#: netbox/virtualization/models/virtualmachines.py:205 msgid "vCPUs" msgstr "" -#: virtualization/forms/bulk_edit.py:180 -#: virtualization/forms/model_forms.py:477 -#: virtualization/tables/virtualmachines.py:118 +#: netbox/virtualization/forms/bulk_edit.py:180 +#: netbox/virtualization/forms/model_forms.py:477 +#: netbox/virtualization/tables/virtualmachines.py:118 msgid "Disk" msgstr "" -#: virtualization/forms/bulk_edit.py:190 -#: virtualization/forms/model_forms.py:265 virtualization/ui/panels.py:62 +#: netbox/virtualization/forms/bulk_edit.py:190 +#: netbox/virtualization/forms/model_forms.py:265 +#: netbox/virtualization/ui/panels.py:62 msgid "Placement" msgstr "" -#: virtualization/forms/bulk_edit.py:203 -#: virtualization/forms/model_forms.py:284 +#: netbox/virtualization/forms/bulk_edit.py:207 +#: netbox/virtualization/forms/model_forms.py:284 #, python-brace-format msgid "Memory ({unit})" msgstr "" -#: virtualization/forms/bulk_edit.py:204 -#: virtualization/forms/model_forms.py:285 +#: netbox/virtualization/forms/bulk_edit.py:208 +#: netbox/virtualization/forms/model_forms.py:285 #, python-brace-format msgid "Disk ({unit})" msgstr "" -#: virtualization/forms/bulk_edit.py:377 virtualization/forms/filtersets.py:342 -#: virtualization/forms/model_forms.py:490 +#: netbox/virtualization/forms/bulk_edit.py:381 +#: netbox/virtualization/forms/filtersets.py:342 +#: netbox/virtualization/forms/model_forms.py:490 #, python-brace-format msgid "Size ({unit})" msgstr "" -#: virtualization/forms/bulk_import.py:47 +#: netbox/virtualization/forms/bulk_import.py:47 msgid "Type of cluster" msgstr "" -#: virtualization/forms/bulk_import.py:54 +#: netbox/virtualization/forms/bulk_import.py:54 msgid "Assigned cluster group" msgstr "" -#: virtualization/forms/bulk_import.py:93 +#: netbox/virtualization/forms/bulk_import.py:93 msgid "Assigned default platform" msgstr "" -#: virtualization/forms/bulk_import.py:110 +#: netbox/virtualization/forms/bulk_import.py:110 msgid "Optional virtual machine type" msgstr "" -#: virtualization/forms/bulk_import.py:120 +#: netbox/virtualization/forms/bulk_import.py:120 msgid "Start on boot in hypervisor" msgstr "" -#: virtualization/forms/bulk_import.py:128 +#: netbox/virtualization/forms/bulk_import.py:128 msgid "Assigned site (inferred from cluster or device if omitted)" msgstr "" -#: virtualization/forms/bulk_import.py:135 +#: netbox/virtualization/forms/bulk_import.py:135 msgid "Assigned cluster (required when the device belongs to a cluster)" msgstr "" -#: virtualization/forms/bulk_import.py:142 +#: netbox/virtualization/forms/bulk_import.py:142 msgid "Host device (standalone or within a cluster)" msgstr "" -#: virtualization/forms/filtersets.py:131 +#: netbox/virtualization/forms/filtersets.py:131 msgid "Default memory (MB)" msgstr "" -#: virtualization/forms/filtersets.py:136 +#: netbox/virtualization/forms/filtersets.py:136 msgid "Virtual machine count" msgstr "" -#: virtualization/forms/model_forms.py:40 +#: netbox/virtualization/forms/model_forms.py:40 msgid "Cluster Type" msgstr "" -#: virtualization/forms/model_forms.py:52 +#: netbox/virtualization/forms/model_forms.py:52 msgid "Cluster Group" msgstr "" -#: virtualization/forms/model_forms.py:156 +#: netbox/virtualization/forms/model_forms.py:156 #, python-brace-format msgid "" "{device} belongs to a different {scope_field} ({device_scope}) than the " "cluster ({cluster_scope})" msgstr "" -#: virtualization/forms/model_forms.py:208 +#: netbox/virtualization/forms/model_forms.py:208 msgid "" "The site where this VM resides. Will be inferred automatically from the " "assigned cluster or device if left blank." msgstr "" -#: virtualization/forms/model_forms.py:220 +#: netbox/virtualization/forms/model_forms.py:220 msgid "" "Assign this VM to a cluster. Required when selecting a device that belongs " "to a cluster." msgstr "" -#: virtualization/forms/model_forms.py:232 +#: netbox/virtualization/forms/model_forms.py:232 msgid "" "Optionally pin this VM to a specific host device within a cluster, or assign " "it directly to a standalone device." msgstr "" -#: virtualization/forms/model_forms.py:295 +#: netbox/virtualization/forms/model_forms.py:295 msgid "Disk size is managed via the attachment of virtual disks." msgstr "" -#: virtualization/models/clusters.py:26 +#: netbox/virtualization/models/clusters.py:26 msgid "cluster type" msgstr "" -#: virtualization/models/clusters.py:27 +#: netbox/virtualization/models/clusters.py:27 msgid "cluster types" msgstr "" -#: virtualization/models/clusters.py:43 +#: netbox/virtualization/models/clusters.py:43 msgid "cluster group" msgstr "" -#: virtualization/models/clusters.py:44 +#: netbox/virtualization/models/clusters.py:44 msgid "cluster groups" msgstr "" -#: virtualization/models/clusters.py:116 +#: netbox/virtualization/models/clusters.py:116 msgid "cluster" msgstr "" -#: virtualization/models/clusters.py:117 +#: netbox/virtualization/models/clusters.py:117 msgid "clusters" msgstr "" -#: virtualization/models/clusters.py:143 +#: netbox/virtualization/models/clusters.py:143 #, python-brace-format msgid "" "{count} devices are assigned as hosts for this cluster but are not in site " "{site}" msgstr "" -#: virtualization/models/clusters.py:150 +#: netbox/virtualization/models/clusters.py:150 #, python-brace-format msgid "" "{count} devices are assigned as hosts for this cluster but are not in " "location {location}" msgstr "" -#: virtualization/models/virtualmachines.py:57 +#: netbox/virtualization/models/virtualmachines.py:57 msgid "default vCPUs" msgstr "" -#: virtualization/models/virtualmachines.py:65 +#: netbox/virtualization/models/virtualmachines.py:65 msgid "default memory (MB)" msgstr "" -#: virtualization/models/virtualmachines.py:88 +#: netbox/virtualization/models/virtualmachines.py:88 msgid "Virtual machine type name must be unique." msgstr "" -#: virtualization/models/virtualmachines.py:94 +#: netbox/virtualization/models/virtualmachines.py:94 msgid "virtual machine type" msgstr "" -#: virtualization/models/virtualmachines.py:95 +#: netbox/virtualization/models/virtualmachines.py:95 msgid "virtual machine types" msgstr "" -#: virtualization/models/virtualmachines.py:175 +#: netbox/virtualization/models/virtualmachines.py:175 msgid "start on boot" msgstr "" -#: virtualization/models/virtualmachines.py:213 +#: netbox/virtualization/models/virtualmachines.py:213 msgid "memory" msgstr "" -#: virtualization/models/virtualmachines.py:218 +#: netbox/virtualization/models/virtualmachines.py:218 msgid "disk" msgstr "" -#: virtualization/models/virtualmachines.py:258 +#: netbox/virtualization/models/virtualmachines.py:258 msgid "Virtual machine name must be unique per cluster and tenant." msgstr "" -#: virtualization/models/virtualmachines.py:264 +#: netbox/virtualization/models/virtualmachines.py:264 msgid "Virtual machine name must be unique per cluster." msgstr "" -#: virtualization/models/virtualmachines.py:270 +#: netbox/virtualization/models/virtualmachines.py:270 msgid "Virtual machine name must be unique per device and tenant." msgstr "" -#: virtualization/models/virtualmachines.py:276 +#: netbox/virtualization/models/virtualmachines.py:276 msgid "Virtual machine name must be unique per device." msgstr "" -#: virtualization/models/virtualmachines.py:279 +#: netbox/virtualization/models/virtualmachines.py:279 msgid "virtual machine" msgstr "" -#: virtualization/models/virtualmachines.py:280 +#: netbox/virtualization/models/virtualmachines.py:280 msgid "virtual machines" msgstr "" -#: virtualization/models/virtualmachines.py:294 +#: netbox/virtualization/models/virtualmachines.py:294 msgid "A virtual machine must be assigned to a site, cluster, or device." msgstr "" -#: virtualization/models/virtualmachines.py:301 +#: netbox/virtualization/models/virtualmachines.py:301 #, python-brace-format msgid "The selected cluster ({cluster}) is not assigned to this site ({site})." msgstr "" -#: virtualization/models/virtualmachines.py:309 +#: netbox/virtualization/models/virtualmachines.py:309 #, python-brace-format msgid "The selected device ({device}) is not assigned to this site ({site})." msgstr "" -#: virtualization/models/virtualmachines.py:318 +#: netbox/virtualization/models/virtualmachines.py:318 #, python-brace-format msgid "" "Must specify the assigned device's cluster ({cluster}) when assigning host " "device {device}." msgstr "" -#: virtualization/models/virtualmachines.py:326 +#: netbox/virtualization/models/virtualmachines.py:326 #, python-brace-format msgid "" "The selected device ({device}) is not assigned to this cluster ({cluster})." msgstr "" -#: virtualization/models/virtualmachines.py:338 +#: netbox/virtualization/models/virtualmachines.py:338 #, python-brace-format msgid "" "The specified disk size ({size}) must match the aggregate size of assigned " "virtual disks ({total_size})." msgstr "" -#: virtualization/models/virtualmachines.py:352 +#: netbox/virtualization/models/virtualmachines.py:352 #, python-brace-format msgid "Must be an IPv{family} address. ({ip} is an IPv{version} address.)" msgstr "" -#: virtualization/models/virtualmachines.py:361 +#: netbox/virtualization/models/virtualmachines.py:361 #, python-brace-format msgid "The specified IP address ({ip}) is not assigned to this VM." msgstr "" -#: virtualization/models/virtualmachines.py:532 +#: netbox/virtualization/models/virtualmachines.py:532 #, python-brace-format msgid "" "The selected parent interface ({parent}) belongs to a different virtual " "machine ({virtual_machine})." msgstr "" -#: virtualization/models/virtualmachines.py:547 +#: netbox/virtualization/models/virtualmachines.py:547 #, python-brace-format msgid "" "The selected bridge interface ({bridge}) belongs to a different virtual " "machine ({virtual_machine})." msgstr "" -#: virtualization/models/virtualmachines.py:558 +#: netbox/virtualization/models/virtualmachines.py:558 #, python-brace-format msgid "" "The untagged VLAN ({untagged_vlan}) must belong to the same site as the " "interface's parent virtual machine, or it must be global." msgstr "" -#: virtualization/models/virtualmachines.py:574 +#: netbox/virtualization/models/virtualmachines.py:574 msgid "virtual disk" msgstr "" -#: virtualization/models/virtualmachines.py:575 +#: netbox/virtualization/models/virtualmachines.py:575 msgid "virtual disks" msgstr "" -#: virtualization/tables/virtualmachines.py:36 +#: netbox/virtualization/tables/virtualmachines.py:36 msgid "VM count" msgstr "" -#: virtualization/ui/panels.py:29 +#: netbox/virtualization/ui/panels.py:29 msgid "{} MB" msgstr "" -#: virtualization/ui/panels.py:29 +#: netbox/virtualization/ui/panels.py:29 msgid "Default memory" msgstr "" -#: virtualization/views.py:377 +#: netbox/virtualization/views.py:377 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "" -#: virtualization/views.py:677 +#: netbox/virtualization/views.py:677 msgid "Assigned VLANs" msgstr "" -#: vpn/choices.py:35 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "" -#: vpn/choices.py:36 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "" -#: vpn/choices.py:37 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "" -#: vpn/choices.py:38 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "" -#: vpn/choices.py:39 +#: netbox/vpn/choices.py:39 msgid "WireGuard" msgstr "" -#: vpn/choices.py:40 +#: netbox/vpn/choices.py:40 msgid "OpenVPN" msgstr "" -#: vpn/choices.py:41 +#: netbox/vpn/choices.py:41 msgid "L2TP" msgstr "" -#: vpn/choices.py:42 +#: netbox/vpn/choices.py:42 msgid "PPTP" msgstr "" -#: vpn/choices.py:88 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "" -#: vpn/choices.py:89 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "" -#: vpn/choices.py:100 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "" -#: vpn/choices.py:101 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "" -#: vpn/choices.py:102 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "" -#: vpn/choices.py:103 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "" -#: vpn/choices.py:186 vpn/choices.py:187 vpn/choices.py:188 vpn/choices.py:189 -#: vpn/choices.py:190 vpn/choices.py:191 vpn/choices.py:192 vpn/choices.py:193 -#: vpn/choices.py:194 vpn/choices.py:195 vpn/choices.py:196 vpn/choices.py:197 -#: vpn/choices.py:198 vpn/choices.py:199 vpn/choices.py:200 vpn/choices.py:201 -#: vpn/choices.py:202 vpn/choices.py:203 vpn/choices.py:204 vpn/choices.py:205 -#: vpn/choices.py:206 vpn/choices.py:207 vpn/choices.py:208 vpn/choices.py:209 +#: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 +#: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 +#: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 +#: netbox/vpn/choices.py:192 netbox/vpn/choices.py:193 +#: netbox/vpn/choices.py:194 netbox/vpn/choices.py:195 +#: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 +#: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 +#: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "" -#: vpn/choices.py:252 +#: netbox/vpn/choices.py:252 msgid "Ethernet Private LAN" msgstr "" -#: vpn/choices.py:253 +#: netbox/vpn/choices.py:253 msgid "Ethernet Virtual Private LAN" msgstr "" -#: vpn/choices.py:256 +#: netbox/vpn/choices.py:256 msgid "Ethernet Private Tree" msgstr "" -#: vpn/choices.py:257 +#: netbox/vpn/choices.py:257 msgid "Ethernet Virtual Private Tree" msgstr "" -#: vpn/choices.py:260 +#: netbox/vpn/choices.py:260 msgid "SPB" msgstr "" -#: vpn/filtersets.py:48 +#: netbox/vpn/filtersets.py:48 msgid "Tunnel group (ID)" msgstr "" -#: vpn/filtersets.py:55 +#: netbox/vpn/filtersets.py:55 msgid "Tunnel group (slug)" msgstr "" -#: vpn/filtersets.py:64 +#: netbox/vpn/filtersets.py:64 msgid "IPSec profile (ID)" msgstr "" -#: vpn/filtersets.py:71 +#: netbox/vpn/filtersets.py:71 msgid "IPSec profile (name)" msgstr "" -#: vpn/filtersets.py:94 +#: netbox/vpn/filtersets.py:94 msgid "Tunnel (ID)" msgstr "" -#: vpn/filtersets.py:101 +#: netbox/vpn/filtersets.py:101 msgid "Tunnel (name)" msgstr "" -#: vpn/filtersets.py:134 +#: netbox/vpn/filtersets.py:134 msgid "Outside IP (ID)" msgstr "" -#: vpn/filtersets.py:147 vpn/filtersets.py:295 +#: netbox/vpn/filtersets.py:147 netbox/vpn/filtersets.py:295 msgid "IKE policy (ID)" msgstr "" -#: vpn/filtersets.py:153 vpn/filtersets.py:302 +#: netbox/vpn/filtersets.py:153 netbox/vpn/filtersets.py:302 msgid "IKE policy (name)" msgstr "" -#: vpn/filtersets.py:225 vpn/filtersets.py:307 +#: netbox/vpn/filtersets.py:225 netbox/vpn/filtersets.py:307 msgid "IPSec policy (ID)" msgstr "" -#: vpn/filtersets.py:231 vpn/filtersets.py:314 +#: netbox/vpn/filtersets.py:231 netbox/vpn/filtersets.py:314 msgid "IPSec policy (name)" msgstr "" -#: vpn/filtersets.py:392 +#: netbox/vpn/filtersets.py:392 msgid "L2VPN (slug)" msgstr "" -#: vpn/filtersets.py:456 +#: netbox/vpn/filtersets.py:456 msgid "VM Interface (ID)" msgstr "" -#: vpn/filtersets.py:462 +#: netbox/vpn/filtersets.py:462 msgid "VLAN (name)" msgstr "" -#: vpn/forms/bulk_edit.py:39 vpn/forms/bulk_import.py:41 -#: vpn/forms/filtersets.py:64 +#: netbox/vpn/forms/bulk_edit.py:39 netbox/vpn/forms/bulk_import.py:41 +#: netbox/vpn/forms/filtersets.py:64 msgid "Tunnel group" msgstr "" -#: vpn/forms/bulk_edit.py:43 vpn/forms/bulk_import.py:47 -#: vpn/forms/filtersets.py:67 +#: netbox/vpn/forms/bulk_edit.py:43 netbox/vpn/forms/bulk_import.py:47 +#: netbox/vpn/forms/filtersets.py:67 msgid "Encapsulation" msgstr "" -#: vpn/forms/bulk_edit.py:49 vpn/forms/bulk_import.py:52 -#: vpn/forms/filtersets.py:74 vpn/models/crypto.py:246 vpn/tables/tunnels.py:52 -#: vpn/ui/panels.py:16 +#: netbox/vpn/forms/bulk_edit.py:49 netbox/vpn/forms/bulk_import.py:52 +#: netbox/vpn/forms/filtersets.py:74 netbox/vpn/models/crypto.py:246 +#: netbox/vpn/tables/tunnels.py:52 netbox/vpn/ui/panels.py:16 msgid "IPSec profile" msgstr "" -#: vpn/forms/bulk_edit.py:58 vpn/forms/filtersets.py:78 vpn/ui/panels.py:17 +#: netbox/vpn/forms/bulk_edit.py:58 netbox/vpn/forms/filtersets.py:78 +#: netbox/vpn/ui/panels.py:17 msgid "Tunnel ID" msgstr "" -#: vpn/forms/bulk_edit.py:85 vpn/forms/bulk_import.py:144 -#: vpn/forms/filtersets.py:112 vpn/ui/panels.py:34 +#: netbox/vpn/forms/bulk_edit.py:85 netbox/vpn/forms/bulk_import.py:144 +#: netbox/vpn/forms/filtersets.py:112 netbox/vpn/ui/panels.py:34 msgid "Authentication method" msgstr "" -#: vpn/forms/bulk_edit.py:90 vpn/forms/bulk_edit.py:148 -#: vpn/forms/bulk_import.py:148 vpn/forms/bulk_import.py:194 -#: vpn/forms/filtersets.py:117 vpn/forms/filtersets.py:167 vpn/ui/panels.py:35 -#: vpn/ui/panels.py:56 +#: netbox/vpn/forms/bulk_edit.py:90 netbox/vpn/forms/bulk_edit.py:148 +#: netbox/vpn/forms/bulk_import.py:148 netbox/vpn/forms/bulk_import.py:194 +#: netbox/vpn/forms/filtersets.py:117 netbox/vpn/forms/filtersets.py:167 +#: netbox/vpn/ui/panels.py:35 netbox/vpn/ui/panels.py:56 msgid "Encryption algorithm" msgstr "" -#: vpn/forms/bulk_edit.py:95 vpn/forms/bulk_edit.py:153 -#: vpn/forms/bulk_import.py:152 vpn/forms/bulk_import.py:199 -#: vpn/forms/filtersets.py:122 vpn/forms/filtersets.py:172 vpn/ui/panels.py:36 -#: vpn/ui/panels.py:57 +#: netbox/vpn/forms/bulk_edit.py:95 netbox/vpn/forms/bulk_edit.py:153 +#: netbox/vpn/forms/bulk_import.py:152 netbox/vpn/forms/bulk_import.py:199 +#: netbox/vpn/forms/filtersets.py:122 netbox/vpn/forms/filtersets.py:172 +#: netbox/vpn/ui/panels.py:36 netbox/vpn/ui/panels.py:57 msgid "Authentication algorithm" msgstr "" -#: vpn/forms/bulk_edit.py:105 vpn/models/crypto.py:48 +#: netbox/vpn/forms/bulk_edit.py:105 netbox/vpn/models/crypto.py:48 msgid "SA lifetime" msgstr "" -#: vpn/forms/bulk_edit.py:133 vpn/ui/panels.py:48 -#: wireless/forms/bulk_edit.py:76 wireless/forms/bulk_edit.py:118 -#: wireless/forms/filtersets.py:73 wireless/forms/filtersets.py:133 +#: netbox/vpn/forms/bulk_edit.py:133 netbox/vpn/ui/panels.py:48 +#: netbox/wireless/forms/bulk_edit.py:76 netbox/wireless/forms/bulk_edit.py:118 +#: netbox/wireless/forms/filtersets.py:73 +#: netbox/wireless/forms/filtersets.py:133 msgid "Pre-shared key" msgstr "" -#: vpn/forms/bulk_edit.py:158 vpn/models/crypto.py:146 vpn/ui/panels.py:38 -#: vpn/ui/panels.py:58 +#: netbox/vpn/forms/bulk_edit.py:158 netbox/vpn/models/crypto.py:146 +#: netbox/vpn/ui/panels.py:38 netbox/vpn/ui/panels.py:58 msgid "SA lifetime (seconds)" msgstr "" -#: vpn/forms/bulk_edit.py:162 vpn/models/crypto.py:152 vpn/ui/panels.py:59 +#: netbox/vpn/forms/bulk_edit.py:162 netbox/vpn/models/crypto.py:152 +#: netbox/vpn/ui/panels.py:59 msgid "SA lifetime (KB)" msgstr "" -#: vpn/forms/bulk_edit.py:180 vpn/models/crypto.py:191 vpn/ui/panels.py:65 -#: vpn/ui/panels.py:88 +#: netbox/vpn/forms/bulk_edit.py:180 netbox/vpn/models/crypto.py:191 +#: netbox/vpn/ui/panels.py:65 netbox/vpn/ui/panels.py:88 msgid "PFS group" msgstr "" -#: vpn/forms/bulk_edit.py:201 vpn/forms/bulk_import.py:238 -#: vpn/forms/filtersets.py:214 vpn/forms/model_forms.py:370 -#: vpn/models/crypto.py:104 +#: netbox/vpn/forms/bulk_edit.py:201 netbox/vpn/forms/bulk_import.py:238 +#: netbox/vpn/forms/filtersets.py:214 netbox/vpn/forms/model_forms.py:370 +#: netbox/vpn/models/crypto.py:104 msgid "IKE policy" msgstr "" -#: vpn/forms/bulk_edit.py:206 vpn/forms/bulk_import.py:243 -#: vpn/forms/filtersets.py:219 vpn/forms/model_forms.py:374 -#: vpn/models/crypto.py:207 +#: netbox/vpn/forms/bulk_edit.py:206 netbox/vpn/forms/bulk_import.py:243 +#: netbox/vpn/forms/filtersets.py:219 netbox/vpn/forms/model_forms.py:374 +#: netbox/vpn/models/crypto.py:207 msgid "IPSec policy" msgstr "" -#: vpn/forms/bulk_import.py:49 +#: netbox/vpn/forms/bulk_import.py:49 msgid "Tunnel encapsulation" msgstr "" -#: vpn/forms/bulk_import.py:89 +#: netbox/vpn/forms/bulk_import.py:89 msgid "Parent device of assigned interface" msgstr "" -#: vpn/forms/bulk_import.py:96 +#: netbox/vpn/forms/bulk_import.py:96 msgid "Parent VM of assigned interface" msgstr "" -#: vpn/forms/bulk_import.py:103 +#: netbox/vpn/forms/bulk_import.py:103 msgid "Device or virtual machine interface" msgstr "" -#: vpn/forms/bulk_import.py:106 vpn/forms/model_forms.py:100 -#: vpn/forms/model_forms.py:136 vpn/forms/model_forms.py:245 -#: vpn/tables/tunnels.py:101 vpn/ui/panels.py:28 +#: netbox/vpn/forms/bulk_import.py:106 netbox/vpn/forms/model_forms.py:100 +#: netbox/vpn/forms/model_forms.py:136 netbox/vpn/forms/model_forms.py:245 +#: netbox/vpn/tables/tunnels.py:101 netbox/vpn/ui/panels.py:28 msgid "Outside IP" msgstr "" -#: vpn/forms/bulk_import.py:182 +#: netbox/vpn/forms/bulk_import.py:182 msgid "IKE proposal(s)" msgstr "" -#: vpn/forms/bulk_import.py:214 vpn/models/crypto.py:195 +#: netbox/vpn/forms/bulk_import.py:214 netbox/vpn/models/crypto.py:195 msgid "Diffie-Hellman group for Perfect Forward Secrecy" msgstr "" -#: vpn/forms/bulk_import.py:221 +#: netbox/vpn/forms/bulk_import.py:221 msgid "IPSec proposal(s)" msgstr "" -#: vpn/forms/bulk_import.py:235 +#: netbox/vpn/forms/bulk_import.py:235 msgid "IPSec protocol" msgstr "" -#: vpn/forms/bulk_import.py:270 +#: netbox/vpn/forms/bulk_import.py:270 msgid "L2VPN type" msgstr "" -#: vpn/forms/bulk_import.py:292 +#: netbox/vpn/forms/bulk_import.py:292 msgid "Parent device (for interface)" msgstr "" -#: vpn/forms/bulk_import.py:299 +#: netbox/vpn/forms/bulk_import.py:299 msgid "Parent virtual machine (for interface)" msgstr "" -#: vpn/forms/bulk_import.py:306 +#: netbox/vpn/forms/bulk_import.py:306 msgid "Assigned interface (device or VM)" msgstr "" -#: vpn/forms/bulk_import.py:339 +#: netbox/vpn/forms/bulk_import.py:339 msgid "Cannot import device and VM interface terminations simultaneously." msgstr "" -#: vpn/forms/bulk_import.py:341 +#: netbox/vpn/forms/bulk_import.py:341 msgid "Each termination must specify either an interface or a VLAN." msgstr "" -#: vpn/forms/bulk_import.py:343 +#: netbox/vpn/forms/bulk_import.py:343 msgid "Cannot assign both an interface and a VLAN." msgstr "" -#: vpn/forms/filtersets.py:142 vpn/ui/panels.py:44 vpn/ui/panels.py:78 +#: netbox/vpn/forms/filtersets.py:142 netbox/vpn/ui/panels.py:44 +#: netbox/vpn/ui/panels.py:78 msgid "IKE version" msgstr "" -#: vpn/forms/filtersets.py:154 vpn/forms/filtersets.py:189 -#: vpn/forms/model_forms.py:296 vpn/forms/model_forms.py:333 +#: netbox/vpn/forms/filtersets.py:154 netbox/vpn/forms/filtersets.py:189 +#: netbox/vpn/forms/model_forms.py:296 netbox/vpn/forms/model_forms.py:333 msgid "Proposal" msgstr "" -#: vpn/forms/filtersets.py:273 +#: netbox/vpn/forms/filtersets.py:273 msgid "Assigned Object Type" msgstr "" -#: vpn/forms/model_forms.py:34 vpn/forms/model_forms.py:47 +#: netbox/vpn/forms/model_forms.py:34 netbox/vpn/forms/model_forms.py:47 msgid "Tunnel Group" msgstr "" -#: vpn/forms/model_forms.py:53 +#: netbox/vpn/forms/model_forms.py:53 msgid "IPSec Profile" msgstr "" -#: vpn/forms/model_forms.py:93 vpn/forms/model_forms.py:128 -#: vpn/forms/model_forms.py:238 vpn/tables/tunnels.py:90 +#: netbox/vpn/forms/model_forms.py:93 netbox/vpn/forms/model_forms.py:128 +#: netbox/vpn/forms/model_forms.py:238 netbox/vpn/tables/tunnels.py:90 msgid "Tunnel interface" msgstr "" -#: vpn/forms/model_forms.py:148 +#: netbox/vpn/forms/model_forms.py:148 msgid "First Termination" msgstr "" -#: vpn/forms/model_forms.py:151 +#: netbox/vpn/forms/model_forms.py:151 msgid "Second Termination" msgstr "" -#: vpn/forms/model_forms.py:195 +#: netbox/vpn/forms/model_forms.py:195 msgid "This parameter is required when defining a termination." msgstr "" -#: vpn/forms/model_forms.py:314 vpn/forms/model_forms.py:351 -#: vpn/tables/crypto.py:65 vpn/tables/crypto.py:125 vpn/views.py:371 -#: vpn/views.py:525 +#: netbox/vpn/forms/model_forms.py:314 netbox/vpn/forms/model_forms.py:351 +#: netbox/vpn/tables/crypto.py:65 netbox/vpn/tables/crypto.py:125 +#: netbox/vpn/views.py:371 netbox/vpn/views.py:525 msgid "Proposals" msgstr "" -#: vpn/forms/model_forms.py:485 +#: netbox/vpn/forms/model_forms.py:485 msgid "A termination must specify an interface or VLAN." msgstr "" -#: vpn/forms/model_forms.py:487 +#: netbox/vpn/forms/model_forms.py:487 msgid "" "A termination can only have one terminating object (an interface or VLAN)." msgstr "" -#: vpn/models/crypto.py:33 +#: netbox/vpn/models/crypto.py:33 msgid "encryption algorithm" msgstr "" -#: vpn/models/crypto.py:37 +#: netbox/vpn/models/crypto.py:37 msgid "authentication algorithm" msgstr "" -#: vpn/models/crypto.py:45 +#: netbox/vpn/models/crypto.py:45 msgid "Diffie-Hellman group ID" msgstr "" -#: vpn/models/crypto.py:51 +#: netbox/vpn/models/crypto.py:51 msgid "Security association lifetime (in seconds)" msgstr "" -#: vpn/models/crypto.py:60 +#: netbox/vpn/models/crypto.py:60 msgid "IKE proposal" msgstr "" -#: vpn/models/crypto.py:61 +#: netbox/vpn/models/crypto.py:61 msgid "IKE proposals" msgstr "" -#: vpn/models/crypto.py:88 vpn/models/crypto.py:188 +#: netbox/vpn/models/crypto.py:88 netbox/vpn/models/crypto.py:188 msgid "proposals" msgstr "" -#: vpn/models/crypto.py:91 wireless/models.py:42 +#: netbox/vpn/models/crypto.py:91 netbox/wireless/models.py:42 msgid "pre-shared key" msgstr "" -#: vpn/models/crypto.py:105 +#: netbox/vpn/models/crypto.py:105 msgid "IKE policies" msgstr "" -#: vpn/models/crypto.py:115 +#: netbox/vpn/models/crypto.py:115 msgid "Mode is required for selected IKE version" msgstr "" -#: vpn/models/crypto.py:119 +#: netbox/vpn/models/crypto.py:119 msgid "Mode cannot be used for selected IKE version" msgstr "" -#: vpn/models/crypto.py:134 +#: netbox/vpn/models/crypto.py:134 msgid "encryption" msgstr "" -#: vpn/models/crypto.py:140 +#: netbox/vpn/models/crypto.py:140 msgid "authentication" msgstr "" -#: vpn/models/crypto.py:149 +#: netbox/vpn/models/crypto.py:149 msgid "Security association lifetime (seconds)" msgstr "" -#: vpn/models/crypto.py:155 +#: netbox/vpn/models/crypto.py:155 msgid "Security association lifetime (in kilobytes)" msgstr "" -#: vpn/models/crypto.py:164 +#: netbox/vpn/models/crypto.py:164 msgid "IPSec proposal" msgstr "" -#: vpn/models/crypto.py:165 +#: netbox/vpn/models/crypto.py:165 msgid "IPSec proposals" msgstr "" -#: vpn/models/crypto.py:175 +#: netbox/vpn/models/crypto.py:175 msgid "Encryption and/or authentication algorithm must be defined" msgstr "" -#: vpn/models/crypto.py:208 +#: netbox/vpn/models/crypto.py:208 msgid "IPSec policies" msgstr "" -#: vpn/models/crypto.py:247 +#: netbox/vpn/models/crypto.py:247 msgid "IPSec profiles" msgstr "" -#: vpn/models/l2vpn.py:116 +#: netbox/vpn/models/l2vpn.py:116 msgid "L2VPN termination" msgstr "" -#: vpn/models/l2vpn.py:117 +#: netbox/vpn/models/l2vpn.py:117 msgid "L2VPN terminations" msgstr "" -#: vpn/models/l2vpn.py:132 +#: netbox/vpn/models/l2vpn.py:132 #, python-brace-format msgid "L2VPN Termination already assigned ({assigned_object})" msgstr "" -#: vpn/models/l2vpn.py:144 +#: netbox/vpn/models/l2vpn.py:144 #, python-brace-format msgid "" "{l2vpn_type} L2VPNs cannot have more than two terminations; found " "{terminations_count} already defined." msgstr "" -#: vpn/models/tunnels.py:26 +#: netbox/vpn/models/tunnels.py:26 msgid "tunnel group" msgstr "" -#: vpn/models/tunnels.py:27 +#: netbox/vpn/models/tunnels.py:27 msgid "tunnel groups" msgstr "" -#: vpn/models/tunnels.py:51 +#: netbox/vpn/models/tunnels.py:51 msgid "encapsulation" msgstr "" -#: vpn/models/tunnels.py:70 +#: netbox/vpn/models/tunnels.py:70 msgid "tunnel ID" msgstr "" -#: vpn/models/tunnels.py:92 +#: netbox/vpn/models/tunnels.py:92 msgid "tunnel" msgstr "" -#: vpn/models/tunnels.py:93 +#: netbox/vpn/models/tunnels.py:93 msgid "tunnels" msgstr "" -#: vpn/models/tunnels.py:145 +#: netbox/vpn/models/tunnels.py:145 msgid "An object may be terminated to only one tunnel at a time." msgstr "" -#: vpn/models/tunnels.py:151 +#: netbox/vpn/models/tunnels.py:151 msgid "tunnel termination" msgstr "" -#: vpn/models/tunnels.py:152 +#: netbox/vpn/models/tunnels.py:152 msgid "tunnel terminations" msgstr "" -#: vpn/models/tunnels.py:169 +#: netbox/vpn/models/tunnels.py:169 #, python-brace-format msgid "{name} is already attached to a tunnel ({tunnel})." msgstr "" -#: vpn/tables/crypto.py:22 +#: netbox/vpn/tables/crypto.py:22 msgid "Authentication Method" msgstr "" -#: vpn/tables/crypto.py:25 vpn/tables/crypto.py:91 +#: netbox/vpn/tables/crypto.py:25 netbox/vpn/tables/crypto.py:91 msgid "Encryption Algorithm" msgstr "" -#: vpn/tables/crypto.py:28 vpn/tables/crypto.py:94 +#: netbox/vpn/tables/crypto.py:28 netbox/vpn/tables/crypto.py:94 msgid "Authentication Algorithm" msgstr "" -#: vpn/tables/crypto.py:34 +#: netbox/vpn/tables/crypto.py:34 msgid "SA Lifetime" msgstr "" -#: vpn/tables/crypto.py:68 +#: netbox/vpn/tables/crypto.py:68 msgid "Pre-shared Key" msgstr "" -#: vpn/tables/crypto.py:97 +#: netbox/vpn/tables/crypto.py:97 msgid "SA Lifetime (Seconds)" msgstr "" -#: vpn/tables/crypto.py:100 +#: netbox/vpn/tables/crypto.py:100 msgid "SA Lifetime (KB)" msgstr "" -#: vpn/tables/crypto.py:128 +#: netbox/vpn/tables/crypto.py:128 msgid "PFS Group" msgstr "" -#: vpn/tables/crypto.py:154 vpn/ui/panels.py:75 +#: netbox/vpn/tables/crypto.py:154 netbox/vpn/ui/panels.py:75 msgid "IKE Policy" msgstr "" -#: vpn/tables/crypto.py:158 vpn/ui/panels.py:84 +#: netbox/vpn/tables/crypto.py:158 netbox/vpn/ui/panels.py:84 msgid "IPSec Policy" msgstr "" -#: vpn/tables/l2vpn.py:69 +#: netbox/vpn/tables/l2vpn.py:69 msgid "Object Parent" msgstr "" -#: vpn/tables/l2vpn.py:74 +#: netbox/vpn/tables/l2vpn.py:74 msgid "Object Site" msgstr "" -#: vpn/ui/panels.py:37 +#: netbox/vpn/ui/panels.py:37 msgid "DH group" msgstr "" -#: vpn/ui/panels.py:102 +#: netbox/vpn/ui/panels.py:102 msgid "Assigned object" msgstr "" -#: vpn/views.py:136 vpn/views.py:691 +#: netbox/vpn/views.py:136 netbox/vpn/views.py:691 msgid "Add a Termination" msgstr "" -#: vpn/views.py:228 +#: netbox/vpn/views.py:228 msgid "Peer Terminations" msgstr "" -#: vpn/views.py:675 +#: netbox/vpn/views.py:675 msgid "Import Route Targets" msgstr "" -#: vpn/views.py:678 +#: netbox/vpn/views.py:678 msgid "Export Route Targets" msgstr "" -#: wireless/choices.py:11 +#: netbox/wireless/choices.py:11 msgid "Access point" msgstr "" -#: wireless/choices.py:12 +#: netbox/wireless/choices.py:12 msgid "Station" msgstr "" -#: wireless/choices.py:467 +#: netbox/wireless/choices.py:467 msgid "Open" msgstr "" -#: wireless/choices.py:469 +#: netbox/wireless/choices.py:469 msgid "WPA Personal (PSK)" msgstr "" -#: wireless/choices.py:470 +#: netbox/wireless/choices.py:470 msgid "WPA Enterprise" msgstr "" -#: wireless/forms/bulk_edit.py:70 wireless/forms/bulk_edit.py:112 -#: wireless/forms/bulk_import.py:69 wireless/forms/bulk_import.py:72 -#: wireless/forms/bulk_import.py:149 wireless/forms/bulk_import.py:152 -#: wireless/forms/filtersets.py:68 wireless/forms/filtersets.py:128 +#: netbox/wireless/forms/bulk_edit.py:70 netbox/wireless/forms/bulk_edit.py:112 +#: netbox/wireless/forms/bulk_import.py:69 +#: netbox/wireless/forms/bulk_import.py:72 +#: netbox/wireless/forms/bulk_import.py:149 +#: netbox/wireless/forms/bulk_import.py:152 +#: netbox/wireless/forms/filtersets.py:68 +#: netbox/wireless/forms/filtersets.py:128 msgid "Authentication cipher" msgstr "" -#: wireless/forms/bulk_import.py:53 +#: netbox/wireless/forms/bulk_import.py:53 msgid "Bridged VLAN" msgstr "" -#: wireless/forms/bulk_import.py:99 +#: netbox/wireless/forms/bulk_import.py:99 msgid "Parent device of assigned interface A" msgstr "" -#: wireless/forms/bulk_import.py:102 wireless/tables/wirelesslink.py:27 -#: wireless/views.py:225 +#: netbox/wireless/forms/bulk_import.py:102 +#: netbox/wireless/tables/wirelesslink.py:27 netbox/wireless/views.py:225 msgid "Interface A" msgstr "" -#: wireless/forms/bulk_import.py:105 +#: netbox/wireless/forms/bulk_import.py:105 msgid "Assigned interface A" msgstr "" -#: wireless/forms/bulk_import.py:120 +#: netbox/wireless/forms/bulk_import.py:120 msgid "Parent device of assigned interface B" msgstr "" -#: wireless/forms/bulk_import.py:123 wireless/tables/wirelesslink.py:36 -#: wireless/views.py:231 +#: netbox/wireless/forms/bulk_import.py:123 +#: netbox/wireless/tables/wirelesslink.py:36 netbox/wireless/views.py:231 msgid "Interface B" msgstr "" -#: wireless/forms/bulk_import.py:126 +#: netbox/wireless/forms/bulk_import.py:126 msgid "Assigned interface B" msgstr "" -#: wireless/forms/model_forms.py:29 +#: netbox/wireless/forms/model_forms.py:29 msgid "Wireless LAN Group" msgstr "" -#: wireless/forms/model_forms.py:162 +#: netbox/wireless/forms/model_forms.py:162 msgid "Side B" msgstr "" -#: wireless/models.py:33 +#: netbox/wireless/models.py:33 msgid "authentication cipher" msgstr "" -#: wireless/models.py:76 +#: netbox/wireless/models.py:76 msgid "wireless LAN group" msgstr "" -#: wireless/models.py:77 +#: netbox/wireless/models.py:77 msgid "wireless LAN groups" msgstr "" -#: wireless/models.py:124 +#: netbox/wireless/models.py:124 msgid "wireless LAN" msgstr "" -#: wireless/models.py:142 +#: netbox/wireless/models.py:142 msgid "interface A" msgstr "" -#: wireless/models.py:148 +#: netbox/wireless/models.py:148 msgid "interface B" msgstr "" -#: wireless/models.py:196 +#: netbox/wireless/models.py:196 msgid "wireless link" msgstr "" -#: wireless/models.py:197 +#: netbox/wireless/models.py:197 msgid "wireless links" msgstr "" -#: wireless/models.py:212 wireless/models.py:218 +#: netbox/wireless/models.py:212 netbox/wireless/models.py:218 #, python-brace-format msgid "{type} is not a wireless interface." msgstr "" -#: wireless/ui/panels.py:24 +#: netbox/wireless/ui/panels.py:24 msgid "Cipher" msgstr "" -#: wireless/ui/panels.py:25 +#: netbox/wireless/ui/panels.py:25 msgid "PSK" msgstr "" -#: wireless/ui/panels.py:45 +#: netbox/wireless/ui/panels.py:45 msgid "Link Properties" msgstr "" -#: wireless/utils.py:17 +#: netbox/wireless/utils.py:17 #, python-brace-format msgid "Invalid channel value: {channel}" msgstr "" -#: wireless/utils.py:27 +#: netbox/wireless/utils.py:27 #, python-brace-format msgid "Invalid channel attribute: {name}" msgstr "" -#: wireless/views.py:60 +#: netbox/wireless/views.py:60 msgid "Add Wireless LAN Group" msgstr "" -#: wireless/views.py:160 +#: netbox/wireless/views.py:160 msgid "Attached Interfaces" msgstr "" From 4407505f870126c881d9a20fe4288fcfeeab4f27 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Tue, 5 May 2026 19:27:55 +0200 Subject: [PATCH 007/131] chore(ci): Collect coverage from parallel test workers Configure coverage.py for multiprocessing so Django's parallel test workers are included in the coverage data. Move coverage source and report settings into pyproject.toml, and combine per-process coverage data before generating the report. Fixes #22118 --- .github/workflows/ci.yml | 12 ++++++------ pyproject.toml | 13 +++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0234c28b5..db42fdd06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,12 +122,12 @@ jobs: - name: Run tests with coverage if: ${{ matrix.coverage }} - run: >- - coverage run --source="netbox/" - netbox/manage.py test netbox/ --parallel + run: coverage run netbox/manage.py test netbox/ --parallel + + - name: Combine coverage data + if: ${{ matrix.coverage }} + run: coverage combine - name: Show coverage report if: ${{ matrix.coverage }} - run: >- - coverage report --skip-covered - --omit '*/migrations/*,*/tests/*' + run: coverage report diff --git a/pyproject.toml b/pyproject.toml index f940a71ad..55cdec1a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,19 @@ Documentation = "https://netboxlabs.com/docs/netbox/" Source = "https://github.com/netbox-community/netbox" Issues = "https://github.com/netbox-community/netbox/issues" +[tool.coverage.run] +source = ["netbox/"] +concurrency = ["multiprocessing"] +parallel = true +sigterm = true + +[tool.coverage.report] +skip_covered = true +omit = [ + "*/migrations/*", + "*/tests/*", +] + [tool.pyright] include = ["netbox"] exclude = [ From b3bc4f8ef2a7b344048fcbaba7959bcfeffb40e6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 6 May 2026 16:04:23 -0400 Subject: [PATCH 008/131] Closes CAP-100: Adopt AI best practices (#22120) --- .claude/skills/README.md | 45 ++ .claude/skills/add-model-field/SKILL.md | 410 +++++++++++++++++++ .claude/skills/add-model/SKILL.md | 519 ++++++++++++++++++++++++ .claude/skills/run-tests/SKILL.md | 92 +++++ .gitignore | 3 + AGENTS.md | 299 ++++++++++++++ CLAUDE.md | 88 +--- 7 files changed, 1369 insertions(+), 87 deletions(-) create mode 100644 .claude/skills/README.md create mode 100644 .claude/skills/add-model-field/SKILL.md create mode 100644 .claude/skills/add-model/SKILL.md create mode 100644 .claude/skills/run-tests/SKILL.md create mode 100644 AGENTS.md diff --git a/.claude/skills/README.md b/.claude/skills/README.md new file mode 100644 index 000000000..2c1021aba --- /dev/null +++ b/.claude/skills/README.md @@ -0,0 +1,45 @@ +# .claude/ + +Project-local Claude Code configuration for NetBox. + +The tool-agnostic content layer for this repo is [`AGENTS.md`](../AGENTS.md) at the repo root, with its `CLAUDE.md` shim. This `.claude/` directory is the Claude-specific action layer that complements `AGENTS.md` with project-local skills, slash commands, and per-developer settings. + +## Layout + +- `skills/` — Project-local Claude Code skills. Each skill is its own subdirectory containing a `SKILL.md` describing what it does and when to use it. Use this for repo-specific procedures. +- `commands/` — Project-local slash commands. One Markdown file per command: `commands/.md`. Use this for `/foo` shortcuts that only make sense in this repo. +- `settings.local.json` — Per-developer Claude Code settings (tool permissions, MCP server paths, IDE preferences). **Never committed** — this filename is in the repo's `.gitignore`. + +## When to add a skill (vs. inlining in AGENTS.md or promoting upstream) + +Add a skill here when: + +- The procedure is repo-specific (it would not be useful in other NBL repos as-is). +- The procedure is non-trivial (more than a one-line note that fits naturally inside `AGENTS.md`). +- The procedure is a recipe an agent or engineer might re-run, not a one-off. + +## When to add a slash command + +Add a command here when: + +- The action is something you find yourself typing the same prompt for repeatedly. +- The repo has a non-obvious workflow that benefits from a shortcut. + +## Conventions + +- Skill and command names use `lowercase-kebab-case`, matching the [folder naming convention in `AGENTS.md`](../AGENTS.md). +- Each skill directory has a `SKILL.md` (the entry point); supporting files (references, examples, sample data) live alongside it inside the skill's directory. +- Each command is a single Markdown file named for the slash command: `commands/.md`. +- Skills and commands document *why* they make the choices they do — the rationale is more durable than the bare instruction. + +## How to add your first skill + +1. Pick a kebab-case name describing the action: e.g., `parse-linear-issues`, `render-delivery-row`. +2. `mkdir .claude/skills//` and create `SKILL.md` inside it. +3. The `SKILL.md` opens with a short YAML-ish header (name, description, version) and then the prompt content. +4. Open a PR — the new directory and its `SKILL.md` are tracked once committed. + +## References + +- [`AGENTS.md`](../AGENTS.md) — this repo's primary agent-context file (open standard). +- [Claude Code skills documentation](https://docs.claude.com/en/docs/claude-code/skills) — what a `SKILL.md` looks like and how Claude Code resolves them. diff --git a/.claude/skills/add-model-field/SKILL.md b/.claude/skills/add-model-field/SKILL.md new file mode 100644 index 000000000..a3ebaf3e2 --- /dev/null +++ b/.claude/skills/add-model-field/SKILL.md @@ -0,0 +1,410 @@ +--- +name: add-model-field +description: Step-by-step checklist for adding a new field to an existing NetBox model, covering all required touch points (model, migration, validation, serializer, forms, filterset, table, panel/template, search, GraphQL, tests, docs). Use when the user asks to add a field or attribute to an existing model. +--- + +# Adding a Field to an Existing NetBox Model + +Adding a field to an existing model touches many files. The scope depends on the field type and how it will be used. Work through the checklist below in order — each section builds on the previous. + +## Before You Start + +Determine upfront: +- **Field type**: scalar (CharField, IntegerField, etc.), FK/M2M, GenericForeignKey, or a special type like JSONField +- **Nullable/optional?** Most new fields should be `blank=True, null=True` unless there's a strong reason otherwise +- **Searchable?** Should it appear in global search results? +- **Filterable?** Should it be exposed in the FilterSet? +- **Displayable in list view?** Should it be a column in the object table? +- **Displayable in detail view?** Should it appear in the detail panel? + +## 1. Add the Field to the Model + +**File:** `netbox//models/.py` + +```python +class MyModel(PrimaryModel): + # ... existing fields ... + new_field = models.CharField( + verbose_name=_('new field'), + max_length=100, + blank=True, + ) + # FK example: + related_thing = models.ForeignKey( + to='app.RelatedModel', + on_delete=models.PROTECT, + related_name='my_models', + blank=True, + null=True, + ) +``` + +The `related_name` of a ForeignKey field should generally be the verbose form of the related model's name (e.g. `books` rather than the default `book_set`). + +**Special cases:** + +- **GenericForeignKey**: If this is a non-unique GFK, add a composite index in `Meta`: + ```python + class Meta: + indexes = ( + models.Index(fields=('object_type', 'object_id')), + ) + ``` + +- **`clone_fields`**: If the field should be pre-filled when cloning an object, add it to `clone_fields` on the model class: + ```python + clone_fields = ('existing_field', 'new_field') + ``` + +- **Validation**: If the new field introduces cross-field constraints, add logic to `clean()`: + ```python + def clean(self): + super().clean() + if self.new_field and not self.related_field: + raise ValidationError({'new_field': _('...')}) + ``` + +## 2. Generate the Migration + +**Do NOT write migrations manually.** Tell the user to run: + +```bash +python netbox/manage.py makemigrations -n --no-header +``` + +Set `DEVELOPER = True` in `configuration.py` if the command is blocked. + +For FK fields, also run: +```bash +python netbox/manage.py migrate +``` +before continuing, so the DB is in sync for manual testing. + +## 3. Update the API Serializer + +The serializer lives under `netbox//api/serializers_/` (note the trailing underscore — it's a directory of submodules star-imported by `serializers.py`). Find the submodule that owns the model and edit the serializer there. + +- **Simple field**: just add the field name to `fields` in `Meta`: + ```python + class Meta: + fields = [..., 'new_field', ...] + ``` + +- **FK field**: add a single serializer field with `nested=True`. NetBox does not use a separate `_id` companion field — the framework accepts a primary key (or brief object) when writing: + ```python + related_thing = RelatedThingSerializer( + nested=True, + required=False, + allow_null=True, + ) + # Add 'related_thing' to Meta.fields + ``` + +- **`brief_fields`**: only add to `brief_fields` if the field is truly essential for compact/nested representations. + +## 4. Update Forms + +There are typically up to four forms to update. Find them under `netbox//forms/`. + +### 4a. Model form (create/edit) — `model_forms.py` + +Add the field to the `fieldsets` tuple and to `Meta.fields`: + +```python +class MyModelForm(PrimaryModelForm): + fieldsets = ( + FieldSet('name', 'new_field', 'related_thing', name=_('My Model')), + ... + ) + class Meta: + model = MyModel + fields = ('name', 'new_field', 'related_thing', ...) +``` + +For FK fields, use `DynamicModelChoiceField`: +```python +related_thing = DynamicModelChoiceField( + queryset=RelatedModel.objects.all(), + required=False, +) +``` + +### 4b. Bulk edit form — `bulk_edit.py` + +Add the field as optional (so it can be blanked): +```python +new_field = forms.CharField(required=False) +# or for FK: +related_thing = DynamicModelChoiceField(queryset=..., required=False) +nullable_fields = ('new_field', 'related_thing') # if it can be set to null +``` +Add to `fieldsets` and `Meta.fields` here too. + +### 4c. Bulk import form — `bulk_import.py` + +If the field should be importable via CSV, add it to the import form: +```python +class MyModelImportForm(NetBoxModelImportForm): + new_field = forms.CharField(required=False) + class Meta: + model = MyModel + fields = ('name', 'new_field', ...) +``` + +### 4d. Filter form — `filtersets.py` (the forms version) + +The base class should match the model's base (`PrimaryModelFilterSetForm`, `OrganizationalModelFilterSetForm`, `NestedGroupModelFilterSetForm`, or `NetBoxModelFilterSetForm`). Add the new entries to the existing `fieldsets` and declare the filter field: + +```python +class MyModelFilterForm(PrimaryModelFilterSetForm): + fieldsets = ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('new_field', 'related_thing_id', name=_('Attributes')), + ) + new_field = forms.CharField(required=False) + related_thing_id = DynamicModelMultipleChoiceField( + queryset=RelatedModel.objects.all(), + required=False, + label=_('Related Thing'), + ) +``` + +## 5. Update the FilterSet + +**File:** `netbox//filtersets.py` + +- **Simple scalar field**: add to `Meta.fields` if a basic exact/contains filter suffices. +- **FK field**: add both `` (name lookup) and `_id` (PK lookup) explicitly — do not rely on `Meta.fields` to generate them: + +```python +class MyModelFilterSet(PrimaryModelFilterSet): + related_thing = django_filters.ModelMultipleChoiceFilter( + field_name='related_thing__name', + queryset=RelatedModel.objects.all(), + to_field_name='name', + label=_('Related thing (name)'), + ) + related_thing_id = django_filters.ModelMultipleChoiceFilter( + queryset=RelatedModel.objects.all(), + label=_('Related thing (ID)'), + ) + + class Meta: + model = MyModel + fields = ('id', 'name', 'new_field', ...) # add new_field here for simple fields +``` + +If the field should be searchable from the search box (`q=`), add it to the `search()` method: +```python +def search(self, queryset, name, value): + return queryset.filter( + Q(name__icontains=value) | + Q(new_field__icontains=value) | # add here + ... + ) +``` + +## 6. Update the Table + +**File:** `netbox//tables/.py` + +- **Simple field**: just add the field name to `Meta.fields`. Add to `default_columns` if it should show by default. +- **FK field** (linking to another object): + ```python + related_thing = tables.Column(linkify=True) + ``` + Add `related_thing` to both `Meta.fields` and `default_columns` if appropriate. +- **Choice field**: display just works if the model uses `get__display()`; no custom column needed. +- **Traversed FK** (field accessed through another relation): + ```python + related_thing = tables.Column( + accessor=tables.A('some_fk__related_thing'), + linkify=True, + ) + ``` + +## 7. Update the Detail View Panel + +The detail view display is controlled by a panel class (not an HTML template), defined under `netbox//ui/panels.py`. + +Find the panel for the model and add a new attribute declaration: + +```python +from netbox.ui import attrs, panels + +class MyModelPanel(panels.ObjectAttributesPanel): + existing_field = attrs.TextAttr('existing_field') + new_field = attrs.TextAttr('new_field') # simple text + related_thing = attrs.RelatedObjectAttr('related_thing', linkify=True) # FK + status = attrs.ChoiceAttr('status') # choice field with badge + is_active = attrs.BooleanAttr('is_active') # boolean + color = attrs.ColorAttr('color') # color swatch +``` + +**Available attr types** (from `netbox.ui.attrs`): + +| Class | Use for | +|---|---| +| `TextAttr` | Plain text / CharField | +| `NumericAttr` | Numbers, optionally with a unit | +| `ChoiceAttr` | Choice fields (renders a colored badge) | +| `BooleanAttr` | Boolean fields | +| `ColorAttr` | Color hex fields | +| `RelatedObjectAttr` | Direct ForeignKey | +| `NestedObjectAttr` | ForeignKey on a nested/hierarchical model (e.g. region.parent) | +| `RelatedObjectListAttr` | ManyToMany or reverse FK list | +| `GenericForeignKeyAttr` | GenericForeignKey | +| `DateTimeAttr` | DateTimeField | +| `TimezoneAttr` | Timezone fields | +| `AddressAttr` | Address text (optionally with map link) | +| `TemplatedAttr` | Custom per-field HTML template | + +If the model uses a legacy HTML template (under `netbox/templates//`) rather than a declarative panel, add a `` row to the relevant `` in that template instead. + +## 8. Update the SearchIndex (if applicable) + +**File:** `netbox//search.py` + +If the new field should be indexed for global search, add it to the model's `SearchIndex`: + +```python +@register_search +class MyModelIndex(SearchIndex): + model = models.MyModel + fields = ( + ('name', 100), + ('new_field', 300), # add here with an appropriate weight + ('description', 500), + ('comments', 5000), + ) +``` + +Weight guide: lower = higher search priority. Name fields ~100, short descriptors ~300–500, long-form comments ~5000. + +## 9. Update GraphQL + +### Filter — `graphql/filters.py` + +Add a filter field to the model's `Filter` class: + +```python +@strawberry_django.filter_type(models.MyModel, lookups=True) +class MyModelFilter(PrimaryModelFilter): + # simple field (lookups=True auto-generates eq/icontains/etc.) + new_field: StrFilterLookup[str] | None = strawberry_django.filter_field() + + # FK field: + related_thing: Annotated['RelatedThingFilter', strawberry.lazy('.graphql.filters')] | None = strawberry_django.filter_field() + related_thing_id: ID | None = strawberry_django.filter_field() +``` + +### Type — `graphql/types.py` + +For simple fields, `fields='__all__'` on the type decorator will pick up the new field automatically. No change needed unless: + +- The field is in an `exclude` list on the type — remove it. +- The field requires a custom type annotation (e.g. a lazy FK reference or a special scalar): + ```python + @strawberry_django.type(models.MyModel, fields='__all__', ...) + class MyModelType(PrimaryObjectType): + related_thing: Annotated['RelatedThingType', strawberry.lazy('.graphql.types')] | None + ``` + +> **Prefetch null failures:** If GraphQL unit tests fail citing null values on a non-nullable field, change the field definition to use `select_related`: +> ```python +> related_thing: ... = strawberry_django.field(select_related=['related_thing']) +> ``` + +## 10. Write Tests + +### FilterSet tests — `tests/test_filtersets.py` + +Add test methods for any new FilterSet fields: + +```python +def test_new_field(self): + params = {'new_field': ['value1', 'value2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), expected) + +def test_related_thing(self): + # Test both name and _id variants + related = RelatedModel.objects.filter(...) + params = {'related_thing_id': [related[0].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), expected) + params = {'related_thing': [related[0].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), expected) +``` + +Ensure `setUpTestData` creates test objects with diverse values for the new field. + +### API tests — `tests/test_api.py` + +- Update `setUpTestData` to populate the new field in test instances. +- Update `create_data` and (if applicable) `bulk_update_data` to include the new field. +- If the field is filterable via the API, add a `test_list_objects_by_` test. + +### View tests — `tests/test_views.py` + +- Update `form_data` in `setUpTestData` to include the new field. +- Update `bulk_edit_data` if the field is bulk-editable. +- Update `csv_data` if the field is importable. + +### Model tests — `tests/test_models.py` (if validation was added) + +Add a test for any custom `clean()` logic: + +```python +def test_clean_new_field_validation(self): + instance = MyModel(new_field='invalid_value', ...) + with self.assertRaises(ValidationError): + instance.clean() +``` + +## 11. Update Documentation + +**File:** `docs/models//.md` + +Add the new field to the model's documentation page. Include: +- The field name and description +- Valid values (for choice fields) +- Any constraints or dependencies + +## Summary Checklist + +| # | File(s) | Action | +|---|---|---| +| 1 | `models/.py` | Add field; add to `clone_fields`; add `clean()` validation | +| 2 | (user runs) | `makemigrations -n --no-header` | +| 3 | `api/serializers_/.py` | Add field to `fields`; for FK use a single `Serializer(nested=True)` field (no `_id` companion) | +| 4a | `forms/model_forms.py` | Add to `fieldsets` and `Meta.fields` | +| 4b | `forms/bulk_edit.py` | Add as optional; add to `nullable_fields` if nullable | +| 4c | `forms/bulk_import.py` | Add if CSV-importable | +| 4d | `forms/filtersets.py` | Add filter field and to `fieldsets` | +| 5 | `filtersets.py` | Add to FilterSet; add FK + FK_id pair; update `search()` | +| 6 | `tables/.py` | Add column; add to `Meta.fields`; update `default_columns` | +| 7 | `/ui/panels.py` | Add attr to the model's panel class | +| 8 | `search.py` | Add to SearchIndex `fields` tuple with appropriate weight | +| 9 | `graphql/filters.py`, `types.py` | Add filter field; update type if excluded or needs custom annotation | +| 10 | `tests/test_*.py` | Update filterset, API, view, and model tests | +| 11 | `docs/models//.md` | Document the new field | + +## Common Gotchas + +- **FilterSets need explicit `_id` variants for FK fields** — `Meta.fields` does not auto-generate them. (This is FilterSet-only — API serializers do **not** add a parallel `_id` field; see below.) +- **Serializer FK fields use `nested=True`, not a parallel `_id`.** Older code that defines both `foo = NestedFooSerializer(read_only=True)` and `foo_id = serializers.PrimaryKeyRelatedField(...)` is the legacy pattern; new code uses a single `foo = FooSerializer(nested=True, ...)` field. +- **Migrations must be generated, not written manually.** If `makemigrations` is blocked, ensure `DEVELOPER = True` is set in `configuration.py`. +- **List views and API serializers don't need manual `prefetch_related()`** — this is handled dynamically. Only add explicit prefetches in a viewset if required for a custom endpoint. +- **`clone_fields` must be declared explicitly** on the model. Fields not in this list are not copied when cloning an object. +- **`brief_fields` on serializers is explicit** — just listing a field in `Meta.fields` does not include it in brief/nested representations. +- **Panel attrs, not HTML templates** — new models use `ObjectAttributesPanel` subclasses in `/ui/panels.py`. Only fall back to editing `templates//` HTML files if the model predates the declarative layout system. +- **GraphQL `fields='__all__'`** picks up simple new fields automatically; only explicit overrides needed for FKs, excluded fields, or special scalars. +- **No `ruff format`** on existing files — use `ruff check` only. + +## References + +- Real example (adding FK filter field): `git show 87b17ff26` — adds `profile`/`profile_id` to the Module filterset, filter form, table, template, and tests +- Real example (adding a JSONField): `git show 5f802bb18` — adds `choice_colors` to CustomFieldChoiceSet across model, forms, filterset, serializer, GraphQL, and tests +- Panel attrs reference: `netbox/netbox/ui/attrs.py` +- Panel classes: `netbox//ui/panels.py` +- Base filterset classes: `netbox/netbox/filtersets.py` +- Contributing guide: `docs/development/extending-models.md` diff --git a/.claude/skills/add-model/SKILL.md b/.claude/skills/add-model/SKILL.md new file mode 100644 index 000000000..0fa5783c8 --- /dev/null +++ b/.claude/skills/add-model/SKILL.md @@ -0,0 +1,519 @@ +--- +name: add-model +description: Step-by-step guide for adding a new model to NetBox, including all required components (model, filterset, serializer, views, forms, tables, GraphQL, tests, docs, navigation). Use when the user asks to add a new model or object type to NetBox. +--- + +# Adding a New Model to NetBox + +Adding a model requires wiring up ~12 components. Work through them in order — each builds on the previous. If the user hasn't specified which app to place the model in, ask first. + +## 0. Before You Start + +Decide on: +- **App**: which existing app owns this model (`dcim`, `ipam`, `extras`, etc.) +- **Base class**: see the hierarchy below +- **URL slug**: the kebab-case name used in URLs (e.g. `virtual-chassis`) +- **Model name**: PascalCase (e.g. `VirtualChassis`) +- **Verbose names**: for `Meta.verbose_name` / `verbose_name_plural` + +### Base Class Hierarchy + +| Class | Use when | +|---|-------------------------------------------------------------------------------------| +| `PrimaryModel` | Real infrastructure objects with description, comments, and owner. Most new models. | +| `OrganizationalModel` | Purely organizational/grouping objects (roles, types, categories). | +| `NestedGroupModel` | Hierarchical tree objects (regions, locations). Uses MPTT. | +| `ChangeLoggedModel` | Lightweight ancillary objects; no custom fields, tags, etc. | +| `AdminModel` | Administrative resources (no change-logging in the user-facing changelog). | +| `NetBoxModel` | Direct subclass of the feature set — use only when no other class fits. | + +All of these live in `netbox/netbox/models/__init__.py`. The remainder of this skill assumes `PrimaryModel`; substitute the matching `Organizational…` / `NestedGroup…` / `ChangeLogged…` base classes (filterset, form, table, serializer, GraphQL) where appropriate. + +## 1. Define the Model + +**File:** `netbox//models/.py` (or `models.py` for smaller apps) + +```python +class MyModel(PrimaryModel): + name = models.CharField( + verbose_name=_('name'), + max_length=100, + db_collation='natural_sort', # for alphabetic-aware sorting + ) + some_fk = models.ForeignKey( + to='app.RelatedModel', + on_delete=models.PROTECT, + related_name='my_models', + blank=True, + null=True, + ) + + class Meta: + ordering = ['name'] + verbose_name = _('my model') + verbose_name_plural = _('my models') + + def __str__(self): + return self.name +``` + +- Add the model to `__all__` in the models module's `__init__.py`. +- `db_collation='natural_sort'` on name fields enables natural sort order; omit if not needed. +- Use `models.PROTECT` for FK `on_delete` unless cascade deletion is explicitly desired. +- `PrimaryModel` already provides `description`, `comments`, and `owner` — don't redeclare them. + +**Do NOT run `makemigrations` yourself.** Tell the user to run the following when finished: + +```bash +python netbox/manage.py makemigrations +``` + +## 2. Define Field Choices (if needed) + +**File:** `netbox//choices.py` + +```python +class MyModelStatusChoices(ChoiceSet): + STATUS_ACTIVE = 'active' + STATUS_PLANNED = 'planned' + + CHOICES = [ + (STATUS_ACTIVE, _('Active'), 'blue'), + (STATUS_PLANNED, _('Planned'), 'cyan'), + ] +``` + +Reference with `choices=MyModelStatusChoices` on the model field and `choices=MyModelStatusChoices.CHOICES` in forms. + +## 3. Create the FilterSet + +**File:** `netbox//filtersets.py` + +```python +class MyModelFilterSet(PrimaryModelFilterSet): + some_fk = django_filters.ModelMultipleChoiceFilter( + field_name='some_fk__name', + queryset=RelatedModel.objects.all(), + to_field_name='name', + label=_('Related model (name)'), + ) + some_fk_id = django_filters.ModelMultipleChoiceFilter( + queryset=RelatedModel.objects.all(), + label=_('Related model (ID)'), + ) + + class Meta: + model = MyModel + fields = ('id', 'name', 'description') +``` + +**Critical:** Always add both `` (name/slug lookup) and `_id` (PK lookup) for every FK. Do not rely on `Meta.fields` to auto-generate `_id` variants — it won't work correctly. + +Match the base class to the model: `PrimaryModelFilterSet`, `OrganizationalModelFilterSet`, `NetBoxModelFilterSet`, or `ChangeLoggedModelFilterSet`. + +## 4. Create Forms + +**File:** `netbox//forms/model_forms.py` + +```python +class MyModelForm(PrimaryModelForm): + fieldsets = ( + FieldSet('name', 'some_fk', name=_('My Model')), + FieldSet('description', 'tags', name=_('Other')), + ) + + class Meta: + model = MyModel + fields = ('name', 'some_fk', 'description', 'owner', 'comments', 'tags') +``` + +**File:** `netbox//forms/filtersets.py` (for the filter form) + +```python +class MyModelFilterForm(PrimaryModelFilterSetForm): + model = MyModel + fieldsets = ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('some_fk_id', name=_('Related')), + ) + some_fk_id = DynamicModelMultipleChoiceField( + queryset=RelatedModel.objects.all(), + required=False, + label=_('Related Model'), + ) + tag = TagFilterField(model) +``` + +Match the form base class to the model's base: `PrimaryModelFilterSetForm`, `OrganizationalModelFilterSetForm`, `NestedGroupModelFilterSetForm`, or `NetBoxModelFilterSetForm` (all in `netbox.forms`). + +### Bulk Edit Form — `netbox//forms/bulk_edit.py` + +```python +class MyModelBulkEditForm(PrimaryModelBulkEditForm): + model = MyModel + description = forms.CharField(max_length=200, required=False) + some_fk = DynamicModelChoiceField(queryset=RelatedModel.objects.all(), required=False) + + fieldsets = ( + FieldSet('some_fk', 'description', name=_('My Model')), + ) + nullable_fields = ('description', 'some_fk') +``` + +### Bulk Import Form — `netbox//forms/bulk_import.py` + +```python +class MyModelImportForm(PrimaryModelImportForm): + some_fk = CSVModelChoiceField( + queryset=RelatedModel.objects.all(), + to_field_name='name', + required=False, + ) + + class Meta: + model = MyModel + fields = ('name', 'some_fk', 'description', 'comments', 'tags') +``` + +Use the matching `Primary…` / `Organizational…` / `NestedGroup…` / `NetBoxModel…` variants of `…ImportForm` and `…BulkEditForm` for non-PrimaryModel bases. + +Export each new form from `netbox//forms/__init__.py`. + +## 5. Create the Table + +**File:** `netbox//tables/.py` + +```python +class MyModelTable(PrimaryModelTable): + name = tables.Column(linkify=True) + some_fk = tables.Column(linkify=True) + tags = columns.TagColumn(url_name=':mymodel_list') + + class Meta(PrimaryModelTable.Meta): + model = MyModel + fields = ('pk', 'id', 'name', 'some_fk', 'description', 'tags', 'created', 'last_updated') + default_columns = ('pk', 'name', 'some_fk', 'description') +``` + +Use custom columns provided by NetBox where appropriate. Otherwise, export from the tables package's `__init__.py`. + +## 6. Add Views + +**File:** `netbox//views.py` + +Common imports: + +```python +from extras.ui.panels import CustomFieldsPanel, TagsPanel +from netbox.ui import layout +from netbox.ui.panels import CommentsPanel +from netbox.views import generic +from utilities.views import register_model_view +``` + +```python +@register_model_view(MyModel, 'list', path='', detail=False) +class MyModelListView(generic.ObjectListView): + queryset = MyModel.objects.all() + table = tables.MyModelTable + filterset = filtersets.MyModelFilterSet + filterset_form = forms.MyModelFilterForm + +@register_model_view(MyModel) +class MyModelView(generic.ObjectView): + queryset = MyModel.objects.all() + template_name = 'generic/object.html' # opt out of model-specific template lookup + layout = layout.SimpleLayout( + left_panels=[panels.MyModelPanel(), TagsPanel(), CustomFieldsPanel()], + right_panels=[CommentsPanel()], + ) + +@register_model_view(MyModel, 'add', detail=False) +@register_model_view(MyModel, 'edit') +class MyModelEditView(generic.ObjectEditView): + queryset = MyModel.objects.all() + form = forms.MyModelForm + +@register_model_view(MyModel, 'delete') +class MyModelDeleteView(generic.ObjectDeleteView): + queryset = MyModel.objects.all() + +@register_model_view(MyModel, 'bulk_import', path='import', detail=False) +class MyModelBulkImportView(generic.BulkImportView): + queryset = MyModel.objects.all() + model_form = forms.MyModelImportForm + +@register_model_view(MyModel, 'bulk_edit', path='edit', detail=False) +class MyModelBulkEditView(generic.BulkEditView): + queryset = MyModel.objects.all() + filterset = filtersets.MyModelFilterSet + table = tables.MyModelTable + form = forms.MyModelBulkEditForm + +@register_model_view(MyModel, 'bulk_delete', path='delete', detail=False) +class MyModelBulkDeleteView(generic.BulkDeleteView): + queryset = MyModel.objects.all() + filterset = filtersets.MyModelFilterSet + table = tables.MyModelTable +``` + +`path='import'`/`'edit'`/`'delete'` keep URLs short and match existing apps. If the model has a `name` field amenable to find/replace, also register a `bulk_rename` view (`generic.BulkRenameView`, `path='rename'`). + +Define `MyModelPanel` as an `ObjectAttributesPanel` subclass in `netbox//ui/panels.py` (see `netbox/dcim/ui/panels.py` for examples and the field summary in `add-model-field`). + +## 7. Add URL Routes + +**File:** `netbox//urls.py` + +```python +from utilities.urls import get_model_urls + +urlpatterns = [ + # ...existing routes... + path('my-models/', include(get_model_urls('', 'mymodel', detail=False))), + path('my-models//', include(get_model_urls('', 'mymodel'))), +] +``` + +`get_model_urls()` auto-generates routes for all registered views. `detail=False` covers the list/create routes; the second `path` covers detail/edit/delete routes. + +## 8. REST API + +### Serializer + +Each app has a `netbox//api/serializers_/` package (note the trailing underscore — it's a directory). Add a new module like `mymodel.py` and re-export from `serializers_/__init__.py` (`netbox//api/serializers.py` star-imports each submodule). + +```python +class MyModelSerializer(PrimaryModelSerializer): + some_fk = RelatedModelSerializer(nested=True, required=False, allow_null=True) + + class Meta: + model = MyModel + fields = [ + 'id', 'url', 'display_url', 'display', + 'name', 'some_fk', + 'description', 'owner', 'comments', 'tags', 'custom_fields', + 'created', 'last_updated', + ] + brief_fields = ('id', 'url', 'display', 'name', 'description') +``` + +NetBox serializers use a single FK field with `nested=True` — no separate `_id` companion. Pass `nested=True` when the related serializer is referenced by another serializer; the framework renders it as a brief representation when reading and accepts a primary key (or brief object) when writing. Match the base class to the model: `PrimaryModelSerializer`, `OrganizationalModelSerializer`, `NestedGroupModelSerializer`, `NetBoxModelSerializer`. + +### ViewSet + +**File:** `netbox//api/views.py` + +```python +class MyModelViewSet(NetBoxModelViewSet): + queryset = MyModel.objects.all() + serializer_class = serializers.MyModelSerializer + filterset_class = filtersets.MyModelFilterSet +``` + +Skip `prefetch_related()` on the queryset — `NetBoxModelViewSet` resolves prefetches dynamically based on the serializer. + +### API URL Route + +**File:** `netbox//api/urls.py` + +```python +router.register('my-models', views.MyModelViewSet) +``` + +## 9. GraphQL + +### Filter + +**File:** `netbox//graphql/filters.py` + +```python +@strawberry_django.filter_type(models.MyModel, lookups=True) +class MyModelFilter(PrimaryModelFilter): + name: StrFilterLookup[str] | None = strawberry_django.filter_field() + some_fk: Annotated['RelatedModelFilter', strawberry.lazy('.graphql.filters')] | None = strawberry_django.filter_field() + some_fk_id: ID | None = strawberry_django.filter_field() +``` + +Add `'MyModelFilter'` to `__all__` at the top of the file. + +### Type + +**File:** `netbox//graphql/types.py` + +```python +@strawberry_django.type( + models.MyModel, + fields='__all__', + filters=MyModelFilter, + pagination=True, +) +class MyModelType(PrimaryObjectType): + some_fk: Annotated['RelatedModelType', strawberry.lazy('.graphql.types')] | None +``` + +Add `'MyModelType'` to `__all__`. + +### Schema + +**File:** `netbox//graphql/schema.py` + +```python +@strawberry.type +class MyAppQuery: + # ...existing fields... + my_model: MyModelType = strawberry_django.field() + my_model_list: list[MyModelType] = strawberry_django.field() +``` + +> **Note:** GraphQL unit tests may fail citing null values on a non-nullable field if related objects are prefetched. Fix by using `= strawberry_django.field(select_related=['some_fk'])` instead. + +## 10. Register in Search + +**File:** `netbox//search.py` + +```python +@register_search +class MyModelIndex(SearchIndex): + model = models.MyModel + fields = ( + ('name', 100), + ('description', 500), + ('comments', 5000), + ) + display_attrs = ('some_fk', 'description') +``` + +Field weights: lower = higher priority in results. Typical: name=100, description=500, comments=5000. + +## 11. Add Navigation Menu Entry + +**File:** `netbox/netbox/navigation/menu.py` + +Find the relevant `MenuGroup` and add: + +```python +get_model_item('', 'mymodel', _('My Models')), +``` + +The model name must be lowercase (not the URL slug). This auto-links to the list view. + +## 12. Add Documentation + +**File:** `docs/models//.md` (filename is the lowercase model name with no separators, e.g. `virtualchassis.md`). + +Include at minimum: +- A description of what the model represents +- A `## Fields` section with a subsection per field (see `docs/models/dcim/site.md` for the canonical structure) + +Then register the page in two indexes: + +- `mkdocs.yml` — add a line under the appropriate `nav:` group (e.g. `- MyModel: 'models//mymodel.md'`) +- `docs/development/models.md` — add to the relevant model-type list under "Models Index" (Primary, Organizational, Nested Group, etc.) + +There is no per-app `index.md` under `docs/models/` — `mkdocs.yml` is the single source of truth for navigation. + +## 13. Write Tests + +### API Tests + +**File:** `netbox//tests/test_api.py` + +```python +class MyModelTest(APIViewTestCases.APIViewTestCase): + model = MyModel + brief_fields = ['description', 'display', 'id', 'name', 'url'] + + @classmethod + def setUpTestData(cls): + # Create 3+ instances for list/bulk tests + my_models = ( + MyModel(name='My Model 1', ...), + MyModel(name='My Model 2', ...), + MyModel(name='My Model 3', ...), + ) + MyModel.objects.bulk_create(my_models) + + cls.create_data = [ + {'name': 'My Model 4', ...}, + {'name': 'My Model 5', ...}, + {'name': 'My Model 6', ...}, + ] +``` + +### View Tests + +**File:** `netbox//tests/test_views.py` + +```python +class MyModelTestCase(ViewTestCases.PrimaryObjectViewTestCase): + model = MyModel + + @classmethod + def setUpTestData(cls): + my_models = ( + MyModel(name='My Model 1', ...), + MyModel(name='My Model 2', ...), + MyModel(name='My Model 3', ...), + ) + MyModel.objects.bulk_create(my_models) + + cls.form_data = { + 'name': 'My Model X', + # all required form fields + } + cls.bulk_edit_data = { + 'description': 'New description', + } + cls.csv_data = ( + 'name', + 'My Model 4', + 'My Model 5', + 'My Model 6', + ) +``` + +### FilterSet Tests + +**File:** `netbox//tests/test_filtersets.py` + +```python +from utilities.testing import ChangeLoggedFilterSetTests + +class MyModelFilterSetTestCase(TestCase, ChangeLoggedFilterSetTests): + queryset = MyModel.objects.all() + filterset = MyModelFilterSet + + @classmethod + def setUpTestData(cls): + # Create diverse test data + + def test_name(self): + params = {'name': ['My Model 1', 'My Model 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_some_fk(self): + # Test FK and FK_id filters +``` + +`ChangeLoggedFilterSetTests` provides standard tests for `id`, `created`, `last_updated`, `q` search, etc. Always mix it in. + +## Common Gotchas + +- **Never write migrations manually.** Always run `python netbox/manage.py makemigrations` and let Django generate them. Set `DEVELOPER = True` in `configuration.py` to enable this. +- **FK filters need explicit `_id` variants** in FilterSets. `Meta.fields` does not auto-generate them. +- **`manage.py` lives in `netbox/`**, not the repo root. +- **Brief fields** in API serializers must be declared explicitly via `brief_fields` on the `Meta` class; they are used for nested representations. +- **GraphQL null prefetch failures**: if tests fail on non-nullable fields, add `select_related=[...]` to the `strawberry_django.field()` call. +- **Template**: by default `generic.ObjectView` auto-resolves to `/.html`. If you only define a panel-driven `layout`, set `template_name = 'generic/object.html'` on the view to opt out of that lookup. Add a real per-model template only when you need markup that panels can't express. +- **Serializer FK fields**: write a single field like `some_fk = RelatedModelSerializer(nested=True, ...)` — do **not** add a separate `some_fk_id` companion. The framework accepts a PK or brief object on write. +- **Modern pattern check**: cargo-culting older nested serializer code (`NestedFooSerializer(read_only=True)` plus `_id` field) is wrong for new code — use the `nested=True` form. +- **`PrimaryModel`** already has `description`, `comments`, `owner`. Don't re-add them. +- **No `ruff format`** on existing files. Use ruff check only. + +## References + +- Model base classes: `netbox/netbox/models/__init__.py` +- Concrete example (VirtualChassis): `netbox/dcim/models/devices.py`, `netbox/dcim/filtersets.py`, `netbox/dcim/api/`, `netbox/dcim/graphql/`, `netbox/dcim/tests/` +- Contributing guide: `docs/development/adding-models.md` +- Navigation menu: `netbox/netbox/navigation/menu.py` diff --git a/.claude/skills/run-tests/SKILL.md b/.claude/skills/run-tests/SKILL.md new file mode 100644 index 000000000..a42c68fb1 --- /dev/null +++ b/.claude/skills/run-tests/SKILL.md @@ -0,0 +1,92 @@ +--- +name: run-tests +description: Run NetBox's Django test suite locally. Use when the user asks to run tests, run a specific test module/class/method, or verify changes pass before opening a PR. +--- + +# Run the NetBox test suite + +NetBox uses `django.test.TestCase` (not pytest). The suite is invoked via `manage.py test` from the repo root. CI runs this exact command in `.github/workflows/ci.yml`. + +## Canonical command + +From the repo root, with the venv active: + +```bash +NETBOX_CONFIGURATION=netbox.configuration_testing python netbox/manage.py test netbox/ --parallel +``` + +`--parallel` runs test processes in parallel and is used in CI. Drop it to debug failures that only appear in parallel mode. + +## Prerequisites + +1. PostgreSQL and Redis reachable on localhost at their default ports (credentials: `netbox`/`netbox`/`netbox`). +2. `configuration.py` in place — copy from the example and fill in DATABASE, REDIS, SECRET_KEY, ALLOWED_HOSTS. This file is gitignored and must never be committed. +3. Dependencies installed: `pip install -r requirements.txt`. +4. `NETBOX_CONFIGURATION` set to `netbox.configuration_testing` — the test config sets `DATABASES`, `REDIS`, and `PLUGINS` appropriately. + +If any of these are missing, surface the gap to the user — do not silently skip. + +## Useful variants + +Run a single app's tests: + +```bash +NETBOX_CONFIGURATION=netbox.configuration_testing python netbox/manage.py test dcim --parallel +``` + +Run a single module, class, or method (Django dotted-path target): + +```bash +NETBOX_CONFIGURATION=netbox.configuration_testing python netbox/manage.py test dcim.tests.test_api +NETBOX_CONFIGURATION=netbox.configuration_testing python netbox/manage.py test dcim.tests.test_api.RackTestCase +NETBOX_CONFIGURATION=netbox.configuration_testing python netbox/manage.py test dcim.tests.test_api.RackTestCase.test_list_objects +``` + +Speed options: + +- `--keepdb` — skip DB rebuild between runs (safe for most iterative work) +- `--parallel` — run tests in parallel across CPU cores (used in CI; don't combine with `--keepdb` without testing first) +- `--failfast` — stop on first failure +- `-v 2` — print each test name as it runs + +## Standard test modules per app + +| Module | Coverage area | +|---|---| +| `test_api.py` | REST API endpoints (CRUD, filtering, bulk operations) | +| `test_filtersets.py` | FilterSet fields and query behavior | +| `test_models.py` | Model methods, validation, constraints | +| `test_views.py` | UI views (list, create, edit, delete, bulk actions) | +| `test_forms.py` | Form validation | +| `test_tables.py` | Table column rendering | + +Specialized modules in some apps: `test_cablepaths.py` (dcim), `test_lookups.py` (ipam). + +## After model changes + +Always generate migrations before running tests; the test DB build will fail if migrations are missing: + +```bash +python netbox/manage.py makemigrations +``` + +Never write migrations manually — let Django generate them. + +## Coverage (matches CI) + +```bash +coverage run --source="netbox/" netbox/manage.py test netbox/ --parallel +coverage report --skip-covered --omit '*/migrations/*,*/tests/*' +``` + +## Why these choices + +- **Don't substitute pytest.** The suite uses `django.test.TestCase`; switching to pytest requires `pytest-django` configured against NetBox's settings, which is not set up. Run via `manage.py test` to match CI. +- **Always set `NETBOX_CONFIGURATION`.** Without it, Django loads `configuration.py` (the production config), which likely has a different database or may not exist in dev environments. +- **`--parallel` for full-suite runs.** CI runs parallel; running without it locally can mask race conditions (rare) and is slower on multi-core machines. + +## References + +- [`AGENTS.md`](../../../AGENTS.md) — Testing and development sections. +- [`.github/workflows/ci.yml`](../../../.github/workflows/ci.yml) — Authoritative CI invocation. +- [`netbox/netbox/configuration_testing.py`](../../../netbox/netbox/configuration_testing.py) — Test configuration used by the runner. diff --git a/.gitignore b/.gitignore index 71d517354..42f47b8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ __pycache__/ yarn-debug.log* yarn-error.log* +# AI tooling +.claude/settings.local.json + # Documentation generated by the upgrade/build workflow /netbox/project-static/docs/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..6d948793b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,299 @@ +# NetBox + +## Repository Overview + +NetBox is an extensible open-source network source-of-truth application powering network automation. It manages network infrastructure data including data center infrastructure (DCIM), IP address management (IPAM), circuits, virtualization, wireless, VPNs, and more. It supports a plugin ecosystem and exposes both a REST API and GraphQL API. + +NetBox is the core product maintained by NetBox Labs. The current version is 4.6 (Python 3.12+, Django 6.x). + +## Tech Stack + +- Python 3.12+ / Django 6.x / Django REST Framework 3.x +- PostgreSQL (required), Redis (required for caching/queuing) +- GraphQL via Strawberry, background jobs via django-rq +- django-tables2 for list views, django-filter for filtering +- drf-spectacular for OpenAPI/Swagger schema generation +- Docs: MkDocs with mkdocs-material theme (in `docs/`) +- Ruff for lint (config in `pyproject.toml`) + +## Repository Map + +```text +. +├── netbox/ — Django project root (run manage.py from here) +│ ├── manage.py +│ ├── netbox/ — Core settings, URLs, WSGI, plugin infrastructure +│ │ ├── settings.py — Main Django settings +│ │ ├── configuration.py — Instance configuration (gitignored) +│ │ ├── configuration_example.py — Configuration template +│ │ ├── configuration_testing.py — Test configuration +│ │ ├── urls.py — Root URL routing +│ │ ├── wsgi.py — WSGI entrypoint +│ │ ├── api/ — Core REST API infrastructure +│ │ ├── graphql/ — Core GraphQL schema +│ │ ├── models/ — Core model infrastructure (features, mixins) +│ │ ├── navigation/ — Navigation menu system +│ │ ├── plugins/ — Plugin system infrastructure +│ │ ├── registry.py — Object registry +│ │ ├── search/ — Full-text search implementation +│ │ ├── ui/ — UI utilities +│ │ └── tests/ — Core framework tests +│ ├── account/ — User account management +│ ├── circuits/ — Circuit and provider management +│ ├── core/ — Core data management (data sources, jobs) +│ ├── dcim/ — Data center infrastructure (devices, racks, cables, etc.) +│ ├── extras/ — Cross-cutting features (custom fields, tags, webhooks, scripts) +│ ├── ipam/ — IP address management (prefixes, addresses, VLANs, etc.) +│ ├── tenancy/ — Tenancy and organization +│ ├── users/ — User management and tokens +│ ├── utilities/ — Shared utilities (no models) +│ ├── virtualization/ — Virtual machines and clusters +│ ├── vpn/ — VPN tunnels and configurations +│ ├── wireless/ — Wireless LANs and links +│ ├── templates/ — Django templates (per-app subdirectories) +│ ├── static/ — Compiled static assets +│ ├── project-static/ — Source static assets +│ ├── media/ — User-uploaded media +│ └── translations/ — i18n translation files +├── docs/ — MkDocs documentation source +│ ├── administration/ +│ ├── configuration/ +│ ├── customization/ +│ ├── development/ — Contributing guide, code style +│ ├── features/ +│ ├── getting-started/ +│ ├── installation/ +│ ├── integrations/ +│ ├── models/ — Per-model documentation (by app) +│ ├── plugins/ +│ ├── reference/ +│ └── release-notes/ +├── scripts/ — Database management and verification scripts +├── contrib/ — Example configs (systemd, nginx, generated schemas) +├── pyproject.toml — Project metadata, ruff config +├── requirements.txt — Python dependencies +└── mkdocs.yml — Docs site configuration +``` + +## Architecture + +### App Structure + +Each Django app (account, circuits, core, dcim, extras, ipam, tenancy, users, virtualization, vpn, wireless) follows a standard layout: + +```text +/ +├── __init__.py +├── models/ — Database models (or models.py for smaller apps) +├── migrations/ — Database migrations +├── api/ +│ ├── serializers.py +│ ├── views.py — DRF viewsets +│ └── urls.py — NetBoxRouter registrations +├── forms/ — Django forms (model forms, filter forms, bulk edit, etc.) +├── tables/ — django-tables2 table definitions +├── graphql/ +│ └── types.py — Strawberry GraphQL types +├── filtersets.py — django-filter FilterSets +├── choices.py — ChoiceSet subclasses +├── views.py — UI views (registered with register_model_view()) +├── urls.py — URL routing +├── search.py — SearchIndex registrations +├── signals.py — Django signal definitions (where applicable) +└── tests/ + ├── test_api.py + ├── test_filtersets.py + ├── test_models.py + ├── test_views.py + └── test_forms.py +``` + +### Views + +Use `register_model_view()` to register model views by action (e.g. "add", "list", etc.). List views typically don't need to add `select_related()` or `prefetch_related()` on their querysets — prefetching is handled dynamically by the table class so that only relevant fields are prefetched. + +### REST API + +DRF serializers live in `/api/serializers.py`; viewsets in `/api/views.py`; URLs auto-registered in `/api/urls.py`. `NetBoxModelSerializer` provides standard fields including `url`, `display`, `tags`, and `custom_fields`. drf-spectacular generates the OpenAPI schema automatically. REST API views typically don't need to add `select_related()` or `prefetch_related()` — prefetching is handled dynamically by the serializer. + +### GraphQL + +Strawberry types live in `/graphql/types.py`. The core GraphQL schema is assembled in `netbox/netbox/graphql/`. Use Strawberry's `@strawberry.type` and `auto` field resolution, following the patterns in existing apps. + +### Background Jobs + +django-rq drives background task processing. Job classes live in `core/jobs.py` and app-specific `jobs.py` files. Use `JobRunner` subclasses (from `netbox.jobs`) for all background work. The `core` app exposes job status in the UI. + +### Plugin System + +Plugin infrastructure lives in `netbox/netbox/plugins/`. Plugins are Django apps registered in `PLUGINS` (configuration.py). The plugin API exposes stable extension points: custom models, views, navigation, template extensions, search indexes, object actions, and event rules. Internal NetBox APIs are subject to change without notice. + +### Filtering + +FilterSets live in `/filtersets.py`, using `NetBoxModelFilterSet` as the base. Used for both UI filtering and API `?field=` params. FK filters must declare an explicit `_id = ModelMultipleChoiceFilter(field_name='', ...)` — don't rely on `Meta.fields` to auto-generate `_id` variants. + +### Extras App + +`extras` is a catch-all for cross-cutting features: custom fields, custom links, tags, webhooks/event rules, export templates, config contexts, saved filters, bookmarks, notifications, scripts, and reports. New cross-cutting features belong here. Use `FeatureQuery` for generic relations (config contexts, custom fields, tags, etc.). + +## Commands + +All commands run from the `netbox/` subdirectory with the venv active. There is no Makefile or Justfile; use raw commands. + +| Command | What it does | +|---|---| +| `python manage.py runserver` | Start development server | +| `python manage.py test` | Run full test suite (set `NETBOX_CONFIGURATION` first — see Testing) | +| `python manage.py test --keepdb --parallel 4` | Faster test run (no DB rebuild, parallel) | +| `python manage.py test dcim.tests.test_api` | Run a single test module | +| `python manage.py makemigrations` | Generate migrations after model changes | +| `python manage.py migrate` | Apply migrations | +| `python manage.py nbshell` | NetBox-enhanced interactive shell | +| `python manage.py collectstatic` | Collect static assets | +| `ruff check` | Lint (run from repo root) | +| `mkdocs serve` | Preview documentation | +| `mkdocs build` | Build static docs site | + +## Development Setup + +```bash +python -m venv ~/.venv/netbox +source ~/.venv/netbox/bin/activate +pip install -r requirements.txt + +# Copy and configure +cp netbox/netbox/configuration.example.py netbox/netbox/configuration.py +# Edit configuration.py: set DATABASE, REDIS, SECRET_KEY, ALLOWED_HOSTS + +cd netbox/ +python manage.py migrate +python manage.py runserver +``` + +Requires PostgreSQL and Redis on localhost at their default ports. + +## Testing + +Tests use `django.test.TestCase` (not pytest). Test modules mirror the app structure in `/tests/`. Always set the `NETBOX_CONFIGURATION` environment variable before running tests: + +```bash +export NETBOX_CONFIGURATION=netbox.configuration_testing +python manage.py test + +# Faster runs +python manage.py test --keepdb --parallel 4 + +# Single module +python manage.py test dcim.tests.test_api +``` + +**Standard test modules per app:** + +| Module | Coverage area | +|---|---| +| `test_api.py` | REST API endpoints (CRUD, filtering, bulk operations) | +| `test_filtersets.py` | FilterSet fields and query behavior | +| `test_models.py` | Model methods, validation, constraints | +| `test_views.py` | UI views (list, create, edit, delete, bulk actions) | +| `test_forms.py` | Form validation | +| `test_tables.py` | Table column rendering | + +Additional specialized test modules exist in some apps (e.g., `test_cablepaths.py` in dcim, `test_lookups.py` in ipam). + +## CI/CD + +GitHub Actions workflows in `.github/workflows/`: + +- **`ci.yml`** — Main CI pipeline: runs on every PR. Executes linting (ruff) and the full test suite across the supported Python version matrix. +- **`codeql.yml`** — CodeQL security scanning. +- **`claude.yml`** — Claude Code automation hook; triggers on issue/PR comments mentioning `@claude`. +- **`claude-issue-triage.yml`** — Automated issue triage via Claude AI. +- **`close-stale-issues.yml`** / **`close-incomplete-issues.yml`** — Issue hygiene automation. +- **`lock-threads.yml`** — Locks closed issue/PR threads after a period. +- **`update-translation-strings.yml`** — Extracts and updates i18n translation strings. + +## Common Tasks + +### Add a new model + +1. Add the model to the appropriate app's `models/` directory (or create a new module imported from `models/__init__.py`). Inherit from `NetBoxModel` for full feature support (custom fields, tags, etc.). +2. Prompt the user to run `python manage.py makemigrations` — never write migrations manually. +3. Wire up the full surface area: filterset (`filtersets.py`), forms (`forms/`), table (`tables/`), serializer (`api/serializers.py`), viewset (`api/views.py`), URL routes (`api/urls.py`, `urls.py`), UI views (`views.py`), navigation, and a template under `templates//`. +4. Register a `SearchIndex` in `search.py` if the model should appear in global search. +5. Add tests covering model logic, API, filtersets, forms, and views. + +### Add a REST API endpoint + +1. Add the serializer to `api/serializers.py` using `NetBoxModelSerializer` for `NetBoxModel`-based models. Include a `url` field. +2. Add the viewset to `api/views.py`. For custom actions use `@action(detail=True, methods=['post'])`. +3. Register the route in `api/urls.py` via `NetBoxRouter`. +4. Ensure a corresponding `FilterSet` exists in `filtersets.py`; add explicit `_id = ModelMultipleChoiceFilter(field_name='', ...)` for FK filters. +5. Add an integration test in `tests/test_api.py`. + +### Add a GraphQL type + +1. Add a Strawberry type to `/graphql/types.py`, inheriting from the appropriate base (see existing types for examples). +2. Register any new query fields in the app's GraphQL module and ensure it is included in the root schema. +3. Follow the patterns in existing apps — use `auto` fields and lazy-resolve relations. + +### Add a filterset field + +1. Add the field to `/filtersets.py`. Use `NetBoxModelFilterSet` as the base. +2. For FK relations, add both `` (name/slug lookup) and `_id` (ID lookup) as explicit `ModelMultipleChoiceFilter` entries. +3. Update the filter form in `forms/filtersets.py` to expose the field in the UI. +4. Add a test in `tests/test_filtersets.py`. + +### Cut a release + +1. Bump `version` in `pyproject.toml`. +2. Update `docs/release-notes/`. +3. Tag and publish a GitHub release. + +## Conventions and Patterns + +- **Apps**: Each app owns its models, views, serializers, filtersets, forms, and tests. Don't reach across app boundaries except via FK relations and public APIs. +- **Views**: Use `register_model_view()`. List views don't need manual `select_related()`/`prefetch_related()` — the table handles it. +- **REST API**: Serializers don't need manual `select_related()`/`prefetch_related()` — handled dynamically. +- **New models**: Inherit from `NetBoxModel`; include `created` and `last_updated` fields. +- **Every UI model**: Needs model, serializer, filterset, form, table, views, URL route, and tests. +- **API serializers**: Must include a `url` field (absolute URL of the object). +- **Generic relations**: Use `FeatureQuery` for config contexts, custom fields, tags, etc. +- **FK filters**: Always add explicit `_id` variants in FilterSets; don't rely on `Meta.fields`. +- **No new dependencies** without strong justification. +- **No manual migrations**: Prompt the user to run `manage.py makemigrations`. +- **No `ruff format`** on existing files — tends to introduce unnecessary style changes. +- **Linting**: Ruff config in `pyproject.toml`. Line length 120, single quotes. Enabled rules: E/W/F/I/RET/UP/RUF022. Ignored: F403, F405, RET504, UP032. +- **Extras**: Cross-cutting features (custom fields, tags, webhooks, scripts) belong in the `extras` app. +- **Plugin API**: Only documented public APIs are stable. Internal code may change without notice. + +## Branch & PR Conventions + +- Branch naming: `-short-description` (e.g., `1234-device-typerror`) +- Use the `main` branch for patch releases; `feature` tracks work for the upcoming minor/major release. +- Every PR must reference an approved GitHub issue. +- PRs must include tests for new functionality. + +## Troubleshooting + +- **Wrong directory for `manage.py`** — `manage.py` lives in `netbox/`, not the repo root. Always `cd netbox/` first or use the full path. +- **Wrong configuration loaded** — Set `NETBOX_CONFIGURATION=netbox.configuration_testing` for tests. +- **`configuration.py` not found** — Copy `configuration.example.py` to `configuration.py` and fill in DATABASE, REDIS, SECRET_KEY, ALLOWED_HOSTS. This file is gitignored and must never be committed. +- **Migration errors** — Never write migrations manually. Run `python manage.py makemigrations` and let Django generate them. +- **Plugin issues** — Only documented public APIs are stable. Internal NetBox code may change without notice. + +## Gotchas + +- `configuration.py` is gitignored — never commit it. +- `manage.py` lives in `netbox/`, NOT the repo root. Running from the wrong directory is a common mistake. +- `NETBOX_CONFIGURATION` env var controls which settings module loads; set to `netbox.configuration_testing` for tests. +- The `extras` app is a catch-all for cross-cutting features (custom fields, tags, webhooks, scripts). +- Plugins API: only documented public APIs are stable. Internal NetBox code is subject to change without notice. +- See `docs/development/` for the full contributing guide and code style details. + +## References + +- Documentation: [`docs/`](./docs/) +- Contributing guide: [`docs/development/`](./docs/development/) +- Release notes: [`docs/release-notes/`](./docs/release-notes/) +- Plugin development: [`docs/plugins/`](./docs/plugins/) +- NetBox Labs: diff --git a/CLAUDE.md b/CLAUDE.md index 5ba40d78a..285e0f5b3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,87 +1 @@ -# NetBox - -Network source-of-truth and infrastructure resource modeling (IRM) tool combining DCIM and IPAM. Built on Django + PostgreSQL + Redis. - -## Tech Stack -- Python 3.12+ / Django / Django REST Framework -- PostgreSQL (required), Redis (required for caching/queuing) -- GraphQL via Strawberry, background jobs via RQ -- Docs: MkDocs (in `docs/`) - -## Repository Layout -- `netbox/` — Django project root; run all `manage.py` commands from here -- `netbox/netbox/` — Core settings, URLs, WSGI entrypoint -- `netbox//` — Django apps: `circuits`, `core`, `dcim`, `ipam`, `extras`, `tenancy`, `virtualization`, `wireless`, `users`, `vpn` -- `docs/` — MkDocs documentation source -- `contrib/` — Example configs (systemd, nginx, etc.) and other resources - -## Development Setup -```bash -python -m venv ~/.venv/netbox -source ~/.venv/netbox/bin/activate -pip install -r requirements.txt - -# Copy and configure -cp netbox/netbox/configuration.example.py netbox/netbox/configuration.py -# Edit configuration.py: set DATABASE, REDIS, SECRET_KEY, ALLOWED_HOSTS - -cd netbox/ -python manage.py migrate -python manage.py runserver -``` - -## Key Commands -All commands run from the `netbox/` subdirectory with venv active. - -```bash -# Development server -python manage.py runserver - -# Run full test suite -export NETBOX_CONFIGURATION=netbox.configuration_testing -python manage.py test - -# Faster test runs (no DB rebuild, parallel) -python manage.py test --keepdb --parallel 4 - -# Migrations -python manage.py makemigrations -python manage.py migrate - -# Shell -python manage.py nbshell # NetBox-enhanced shell -``` - -## Architecture Conventions -- **Apps**: Each Django app owns its models, views, API serializers, filtersets, forms, and tests. -- **Views**: Use `register_model_view()` to register model views by action (e.g. "add", "list", etc.). List views typically don't need to add `select_related()` or `prefetch_related()` on their querysets: Prefetching is handled dynamically by the table class so that only relevant fields are prefetched. -- **REST API**: DRF serializers live in `/api/serializers.py`; viewsets in `/api/views.py`; URLs auto-registered in `/api/urls.py`. REST API views typically don't need to add `select_related()` or `prefetch_related()` on their querysets: Prefetching is handled dynamically by the serializer so that only relevant fields are prefetched. -- **GraphQL**: Strawberry types in `/graphql/types.py`. -- **Filtersets**: `/filtersets.py` — used for both UI filtering and API `?filter=` params. -- **Tables**: `django-tables2` used for all object list views (`/tables.py`). -- **Templates**: Django templates in `netbox/templates//`. -- **Tests**: Mirror the app structure in `/tests/`. Use `netbox.configuration_testing` for test config. - -## Coding Standards -- Follow existing Django conventions; don't reinvent patterns already present in the codebase. -- New models must include `created`, `last_updated` fields (inherit from `NetBoxModel` where appropriate). -- Every model exposed in the UI needs: model, serializer, filterset, form, table, views, URL route, and tests. -- API serializers must include a `url` field (absolute URL of the object). -- Use `FeatureQuery` for generic relations (config contexts, custom fields, tags, etc.). -- Avoid adding new dependencies without strong justification. -- Avoid running `ruff format` on existing files, as this tends to introduce unnecessary style changes. -- Don't craft Django database migrations manually: Prompt the user to run `manage.py makemigrations` instead. - -## Branch & PR Conventions -- Branch naming: `-short-description` (e.g., `1234-device-typerror`) -- Use the `main` branch for patch releases; `feature` tracks work for the upcoming minor/major release. -- Every PR must reference an approved GitHub issue. -- PRs must include tests for new functionality. - -## Gotchas -- `configuration.py` is gitignored — never commit it. -- `manage.py` lives in `netbox/`, NOT the repo root. Running from the wrong directory is a common mistake. -- `NETBOX_CONFIGURATION` env var controls which settings module loads; set to `netbox.configuration_testing` for tests. -- The `extras` app is a catch-all for cross-cutting features (custom fields, tags, webhooks, scripts). -- Plugins API: only documented public APIs are stable. Internal NetBox code is subject to change without notice. -- See `docs/development/` for the full contributing guide and code style details. +@./AGENTS.md From e50aff873636f62f017c4e1283507c9153f00cdf Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 6 May 2026 17:58:08 -0400 Subject: [PATCH 009/131] Documentation cleanup (#22127) --- docs/configuration/error-reporting.md | 8 +-- docs/configuration/security.md | 6 +- docs/features/context-data.md | 6 ++ docs/features/devices-cabling.md | 21 ++++++- docs/features/facilities.md | 8 ++- docs/integrations/rest-api.md | 53 ++++++++++++++++++ docs/models/core/objectchange.md | 43 ++++++++++++++ docs/models/core/objecttype.md | 26 +++++++++ docs/models/dcim/cablebundle.md | 6 +- docs/models/dcim/macaddress.md | 20 ++++++- docs/models/dcim/moduletypeprofile.md | 20 +++++-- docs/models/extras/configcontextprofile.md | 20 ++++++- docs/models/users/group.md | 19 +++++++ docs/models/users/objectpermission.md | 50 +++++++++++++++++ docs/models/users/ownergroup.md | 8 ++- docs/models/users/token.md | 51 +++++++++++++++++ docs/models/users/user.md | 47 ++++++++++++++++ docs/plugins/development/index.md | 3 +- docs/plugins/development/permissions.md | 65 +++++++++++++++++++--- mkdocs.yml | 6 ++ netbox/netbox/configuration_example.py | 2 +- 21 files changed, 452 insertions(+), 36 deletions(-) create mode 100644 docs/models/core/objectchange.md create mode 100644 docs/models/core/objecttype.md create mode 100644 docs/models/users/group.md create mode 100644 docs/models/users/objectpermission.md create mode 100644 docs/models/users/token.md create mode 100644 docs/models/users/user.md diff --git a/docs/configuration/error-reporting.md b/docs/configuration/error-reporting.md index 2d287ef06..de0d7091b 100644 --- a/docs/configuration/error-reporting.md +++ b/docs/configuration/error-reporting.md @@ -18,7 +18,7 @@ Additionally, `http_proxy` and `https_proxy` are set to the HTTP and HTTPS proxi ## SENTRY_DSN -!!! warning "This parameter will be removed in NetBox v4.5." +!!! warning "This parameter will be removed in NetBox v4.7." Set this using `SENTRY_CONFIG` instead: ``` @@ -50,7 +50,7 @@ Set to `True` to enable automatic error reporting via [Sentry](https://sentry.io ## SENTRY_SAMPLE_RATE -!!! warning "This parameter will be removed in NetBox v4.5." +!!! warning "This parameter will be removed in NetBox v4.7." Set this using `SENTRY_CONFIG` instead: ``` @@ -67,7 +67,7 @@ The sampling rate for errors. Must be a value between 0 (disabled) and 1.0 (repo ## SENTRY_SEND_DEFAULT_PII -!!! warning "This parameter will be removed in NetBox v4.5." +!!! warning "This parameter will be removed in NetBox v4.7." Set this using `SENTRY_CONFIG` instead: ``` @@ -103,7 +103,7 @@ SENTRY_TAGS = { ## SENTRY_TRACES_SAMPLE_RATE -!!! warning "This parameter will be removed in NetBox v4.5." +!!! warning "This parameter will be removed in NetBox v4.7." Set this using `SENTRY_CONFIG` instead: ``` diff --git a/docs/configuration/security.md b/docs/configuration/security.md index 3fc789f4c..38dcf5d51 100644 --- a/docs/configuration/security.md +++ b/docs/configuration/security.md @@ -153,7 +153,7 @@ EXEMPT_VIEW_PERMISSIONS = ['*'] Default: `False` -If `True`, the lifetime of a user's authentication session will be automatically reset upon each valid request. For example, if [`LOGIN_TIMEOUT`](#login_timeout) is configured to 14 days (the default), and a user whose session is due to expire in five days makes a NetBox request (with a valid session cookie), the session's lifetime will be reset to 14 days. +If `True`, the lifetime of a user's authentication session will be automatically reset upon each valid request. For example, if [`LOGIN_TIMEOUT`](#login_timeout) is configured to 14 days, and a user whose session is due to expire in five days makes a NetBox request (with a valid session cookie), the session's lifetime will be reset to 14 days. Note that enabling this setting causes NetBox to update a user's session in the database (or file, as configured per [`SESSION_FILE_PATH`](#session_file_path)) with each request, which may introduce significant overhead in very active environments. It also permits an active user to remain authenticated to NetBox indefinitely. @@ -175,9 +175,9 @@ When enabled, only authenticated users are permitted to access any part of NetBo ## LOGIN_TIMEOUT -Default: `1209600` seconds (14 days) +Default: `None` -The lifetime (in seconds) of the authentication cookie issued to a NetBox user upon login. +The lifetime (in seconds) of the authentication cookie issued to a NetBox user upon login. If set to `None` (the default), Django's [`SESSION_COOKIE_AGE`](https://docs.djangoproject.com/en/stable/ref/settings/#session-cookie-age) is used, which defaults to two weeks (1,209,600 seconds). --- diff --git a/docs/features/context-data.md b/docs/features/context-data.md index 22aeccea2..d893fde2a 100644 --- a/docs/features/context-data.md +++ b/docs/features/context-data.md @@ -84,3 +84,9 @@ Devices and virtual machines may also have a local context data defined. This lo !!! warning If you find that you're routinely defining local context data for many individual devices or virtual machines, [custom fields](./customization.md#custom-fields) may offer a more effective solution. + +## Profiles & Schema Validation + +A [config context profile](../models/extras/configcontextprofile.md) provides an organizational grouping for related config contexts and may optionally enforce a [JSON schema](https://json-schema.org/) describing the shape of their data. When a profile is assigned to a config context, NetBox validates the context's data against the profile's schema on save and rejects any context that fails validation. This makes it possible to constrain which keys may appear in a context, require certain keys to be present, or limit values to a defined enumeration — guarding against typos and drift as contexts proliferate. + +A profile's schema may be authored directly in NetBox or populated from an external [data source](../models/core/datasource.md), enabling teams to maintain schemas alongside the code or configurations that consume them. diff --git a/docs/features/devices-cabling.md b/docs/features/devices-cabling.md index 03f386977..7a890f538 100644 --- a/docs/features/devices-cabling.md +++ b/docs/features/devices-cabling.md @@ -6,18 +6,23 @@ NetBox uses device types to represent unique real-world device models. This allo ```mermaid flowchart TD - Manufacturer -.-> Platform & DeviceType & ModuleType + Manufacturer -.-> Platform Manufacturer --> DeviceType & ModuleType + ModuleTypeProfile -.-> ModuleType DeviceRole & Platform & DeviceType --> Device Device & ModuleType ---> Module Device & Module --> Interface & ConsolePort & PowerPort & ... + Interface --> MACAddress click Device "../../models/dcim/device/" click DeviceRole "../../models/dcim/devicerole/" click DeviceType "../../models/dcim/devicetype/" +click Interface "../../models/dcim/interface/" +click MACAddress "../../models/dcim/macaddress/" click Manufacturer "../../models/dcim/manufacturer/" click Module "../../models/dcim/module/" click ModuleType "../../models/dcim/moduletype/" +click ModuleTypeProfile "../../models/dcim/moduletypeprofile/" click Platform "../../models/dcim/platform/" ``` @@ -69,15 +74,23 @@ Sometimes it is necessary to model a set of physical devices as sharing a single A virtual device context (VDC) is a logical partition within a device. Each VDC operates autonomously but shares a common pool of resources. Each interface can be assigned to one or more VDCs on its device. -## Module Types & Modules +## Module Types, Profiles & Modules Much like device types and devices, module types can instantiate discrete modules, which are hardware components installed within devices. Modules often have their own child components, which become available to the parent device. For example, when modeling a chassis-based switch with multiple line cards in NetBox, the chassis would be created (from a device type) as a device, and each of its line cards would be instantiated from a module type as a module installed in one of the device's module bays. +### Module Type Profiles + +A [module type profile](../models/dcim/moduletypeprofile.md) classifies module types (e.g. `Power Supply`, `Disk`) and may optionally define a [JSON schema](https://json-schema.org/) describing custom attributes that module types of that profile may carry. This is useful for tracking domain-specific specifications such as a power supply's input voltage, a CPU's clock speed, or a disk's capacity, without needing to add a custom field to every module type in NetBox. + !!! tip "Device Bays vs. Module Bays" What's the difference between device bays and module bays? Device bays are appropriate when the installed hardware has its own management plane, isolated from the parent device. A common example is a blade server chassis in which the blades share power but operate independently. In contrast, a module bay holds a module which does _not_ operate independently of its parent device, as with the chassis switch line card example mentioned above. One especially nice feature of modules is that templated components can be automatically renamed according to the module bay into which the parent module is installed. For example, if we create a module type with interfaces named `Gi{module}/0/1-48` and install a module of this type into module bay 7 of a device, NetBox will create interfaces named `Gi7/0/1-48`. +## MAC Addresses + +[MAC addresses](../models/dcim/macaddress.md) are modeled as first-class objects in NetBox so that an interface may have multiple MAC addresses assigned to it, with one optionally designated as the interface's primary MAC. This accommodates virtual interfaces and modular hardware where the link-layer address is not necessarily fixed at the factory. MAC addresses can be assigned to both [device interfaces](../models/dcim/interface.md) and [virtual machine interfaces](../models/virtualization/vminterface.md). + ## Cables NetBox models cables as connections among certain types of device components and other objects. Each cable can be assigned a type, color, length, and label. NetBox will enforce basic sanity checks to prevent invalid connections. (For example, a network interface cannot be connected to a power outlet.) @@ -89,3 +102,7 @@ flowchart LR Interface --> Cable Cable --> fp1[Front Port] & fp2[Front Port] ``` + +### Cable Bundles + +Related cables can optionally be grouped into a [cable bundle](../models/dcim/cablebundle.md), representing a logical collection such as a conduit, trunk, or wiring harness. Bundle membership is purely organizational: it does not affect cable tracing or connectivity. Deleting a cable removes it from its bundle but does not delete the bundle itself, allowing bundles to outlive any specific member cable. diff --git a/docs/features/facilities.md b/docs/features/facilities.md index 1421281eb..32f8402b5 100644 --- a/docs/features/facilities.md +++ b/docs/features/facilities.md @@ -13,10 +13,12 @@ flowchart TD Rack --> Device Site --> Rack RackRole --> Rack + RackGroup --> Rack click Device "../../models/dcim/device/" click Location "../../models/dcim/location/" click Rack "../../models/dcim/rack/" +click RackGroup "../../models/dcim/rackgroup/" click RackRole "../../models/dcim/rackrole/" click Region "../../models/dcim/region/" click Site "../../models/dcim/site/" @@ -60,11 +62,15 @@ A location can be any logical subdivision within a building, such as a floor or A rack type represents a unique specification of a rack which exists in the real world. Each rack type can be setup with weight, height, and unit ordering. New racks of this type can then be created in NetBox, and any associated specifications will be automatically replicated from the device type. +## Rack Groups + +In addition to being assigned to a [location](#locations), racks may optionally be assigned to a [rack group](../models/dcim/rackgroup.md). Rack groups are flat (non-hierarchical) and exist alongside locations as a secondary axis of grouping — particularly handy for organizing racks by row, aisle, or pod within a single location, or for scoping [VLAN groups](../models/ipam/vlangroup.md) to a subset of racks. + ## Racks Finally, NetBox models each equipment rack as a discrete object within a site and location. These are physical objects into which devices are installed. Each rack can be assigned an operational status, type, facility ID, and other attributes related to inventory tracking. Each rack also must define a height (in rack units) and width, and may optionally specify its physical dimensions. -Each rack must be associated to a site, but the assignment to a location within that site is optional. Users can also create custom roles to which racks can be assigned. NetBox supports tracking rack space in half-unit increments, so it's possible to mount devices at e.g. position 2.5 within a rack. +Each rack must be associated to a site, but the assignment to a location or rack group within that site is optional. Users can also create custom roles to which racks can be assigned. NetBox supports tracking rack space in half-unit increments, so it's possible to mount devices at e.g. position 2.5 within a rack. !!! tip "Devices" You'll notice in the diagram above that a device can be installed within a site, location, or rack. This approach affords plenty of flexibility as not all sites need to define child locations, and not all devices reside in racks. diff --git a/docs/integrations/rest-api.md b/docs/integrations/rest-api.md index 74b421456..a9cbda4dc 100644 --- a/docs/integrations/rest-api.md +++ b/docs/integrations/rest-api.md @@ -663,6 +663,51 @@ Note that there is no requirement for the attributes to be identical among objec !!! note The bulk update of objects is an all-or-none operation, meaning that if NetBox fails to successfully update any of the specified objects (e.g. due a validation error), the entire operation will be aborted and none of the objects will be updated. +### Concurrent Update Protection + +!!! info "This feature was introduced in NetBox v4.6." + +To guard against the lost-update problem when multiple clients modify the same object, NetBox returns a weak `ETag` response header on detail-view responses (`GET`, `POST`, `PATCH`, `PUT`) for individual objects. Clients may supply this value back on a subsequent `PATCH` or `PUT` request via the `If-Match` request header. If the object's current ETag does not match any of the values supplied, the server rejects the request with a `412 Precondition Failed` response and includes the current ETag in the response so the client can retry. + +```no-highlight +# Capture the ETag returned with the object +$ curl -s -i -H "Authorization: Bearer $TOKEN" http://netbox/api/dcim/sites/1/ | grep -i ^etag +ETag: W/"2026-05-01T17:42:11.123456+00:00" + +# Submit an update with If-Match referencing that ETag +$ curl -s -X PATCH \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -H 'If-Match: W/"2026-05-01T17:42:11.123456+00:00"' \ + http://netbox/api/dcim/sites/1/ \ + --data '{"status": "decommissioning"}' +``` + +A literal `If-Match: *` value matches any current ETag and may be used to assert simply that the object exists. Submitting `If-Match` is optional; requests without the header retain prior (last-write-wins) behavior. + +### Adding and Removing Tags + +!!! info "This feature was introduced in NetBox v4.6." + +In addition to replacing an object's tag set wholesale via the `tags` field, taggable models accept two write-only fields, `add_tags` and `remove_tags`, which apply only the specified additions or removals without disturbing existing tags. This is convenient when concurrent clients each manage a distinct subset of an object's tags. + +```no-highlight +curl -s -X PATCH \ +-H "Authorization: Bearer $TOKEN" \ +-H "Content-Type: application/json" \ +http://netbox/api/dcim/sites/1/ \ +--data '{ + "add_tags": [{"name": "production"}], + "remove_tags": [{"name": "staging"}] +}' +``` + +Constraints: + +* `tags` may not be combined with `add_tags` or `remove_tags` in the same request. +* `remove_tags` is only valid on updates; it cannot be used when creating a new object. +* The same tag may not appear in both `add_tags` and `remove_tags`. + ### Deleting an Object To delete an object from NetBox, make a `DELETE` request to the model's _detail_ endpoint specifying its unique numeric ID. The `Authorization` header must be included to specify an authorization token, however this type of request does not support passing any data in the body. @@ -871,3 +916,11 @@ GET /api/dcim/sites/?created_by_request=e39c84bc-f169-4d5f-bc1c-94487a1b18b5 !!! note This header is included with _all_ NetBox responses, although it is most practical when working with an API. + +### `ETag` + +A weak entity tag (e.g. `W/"2026-05-01T17:42:11.123456+00:00"`) returned on detail-view responses for individual objects. The value is derived from the object's `last_updated` timestamp (or `created`, if the object has no `last_updated`). Clients may supply this value on a subsequent write request via the `If-Match` header to perform a conditional update. See [Concurrent Update Protection](#concurrent-update-protection) for details. + +### `If-Match` + +A request header which may be supplied on `PATCH` or `PUT` requests targeting a single object. If the object's current ETag does not match any value supplied, the request is rejected with a `412 Precondition Failed` response. A literal value of `*` matches any existing object. See [Concurrent Update Protection](#concurrent-update-protection) for details. diff --git a/docs/models/core/objectchange.md b/docs/models/core/objectchange.md new file mode 100644 index 000000000..57c9e1e88 --- /dev/null +++ b/docs/models/core/objectchange.md @@ -0,0 +1,43 @@ +# Object Changes + +An object change is a record of a single create, update, or delete operation against an object whose model supports [change logging](../../features/change-logging.md). Object changes form a complete audit trail: each one captures the user that initiated the change, the request that caused it, the action performed, and a JSON snapshot of the object before and after. + +For component objects (e.g. an interface on a device), an object change can also reference a related parent object so that the change appears in the parent's changelog as well as the component's own. + +## Fields + +### Time + +The date and time at which the change was recorded. + +### User & User Name + +The [user](../users/user.md) who initiated the change. The user's username is also stored as a static string (`user_name`) so that change records remain readable even after the user account is deleted. + +### Request ID + +A UUID identifying the request that produced the change. All changes resulting from a single request share the same request ID, which makes it easy to correlate related modifications. The same value is returned on REST API responses via the `X-Request-ID` header. + +### Action + +The type of operation performed: `create`, `update`, or `delete`. + +### Changed Object + +A generic foreign key (`changed_object_type` + `changed_object_id`) identifying the object that was modified. + +### Related Object + +An optional generic foreign key referencing a related object (e.g. the parent device for a changed interface). When set, the change is also surfaced in the related object's changelog. + +### Object Representation + +A static text representation of the changed object, captured at the time of the change. Preserved so that the change record is meaningful even after the underlying object is deleted. + +### Message + +An optional free-form message attached to the change. May be supplied via the UI (in eligible forms) or via the [REST API](../../integrations/rest-api.md#changelog-messages) using the `changelog_message` field. + +### Pre-Change Data & Post-Change Data + +JSON snapshots of the object's serialized state immediately before and immediately after the change. For `create` actions, only post-change data is recorded; for `delete` actions, only pre-change data. The diff displayed in the UI is computed from these snapshots. diff --git a/docs/models/core/objecttype.md b/docs/models/core/objecttype.md new file mode 100644 index 000000000..73b2f129e --- /dev/null +++ b/docs/models/core/objecttype.md @@ -0,0 +1,26 @@ +# Object Types + +An object type identifies a NetBox model by its app label and model name (e.g. `dcim.device`). Object types are used wherever NetBox needs to refer to a model dynamically — most commonly in [custom fields](../extras/customfield.md), [object permissions](../users/objectpermission.md), [export templates](../extras/exporttemplate.md), [event rules](../extras/eventrule.md), and generic relations such as the assignment of an [IP address](../ipam/ipaddress.md) to either a device or VM interface. + +Object types extend Django's stock `ContentType` model with two additional attributes that NetBox uses to reason about model capabilities: `public` (whether the model is intended for direct reference) and `features` (the set of NetBox model features the model supports, such as change logging or custom fields). + +!!! note "For plugin authors" + NetBox code should generally use `ObjectType.objects.get_for_model()` rather than Django's `ContentType.objects.get_for_model()`, so that the resulting object exposes NetBox's `public` and `features` attributes. The two managers are otherwise interchangeable. + +## Fields + +### App Label + +The Django application label to which the model belongs (e.g. `dcim`, `ipam`, or a plugin's app label). + +### Model + +The lowercase model name (e.g. `device`, `prefix`). + +### Public + +Indicates whether the model is part of NetBox's public data model. Public models are those intended to be referenced from other objects (e.g. via custom fields or generic relations). Internal models — those backing implementation details — are non-public and are excluded from interfaces that expose model selection to end users. + +### Features + +The list of NetBox model features the underlying model supports (for example: `change_logging`, `custom_fields`, `tags`, `webhooks`). This list is consulted when filtering object types for a particular feature, e.g. when populating the model selector for an event rule. diff --git a/docs/models/dcim/cablebundle.md b/docs/models/dcim/cablebundle.md index cf585b378..15d6ba4da 100644 --- a/docs/models/dcim/cablebundle.md +++ b/docs/models/dcim/cablebundle.md @@ -1,8 +1,8 @@ # Cable Bundles -A cable bundle is a logical grouping of individual [cables](./cable.md). Bundles can be used to organize cables that share a common purpose, route, or physical grouping (such as a conduit or harness). +A cable bundle is a logical grouping of individual [cables](./cable.md). Bundles are useful for organizing cables that share a common purpose, route, or physical grouping such as a conduit, trunk, or wiring harness. -Assigning cables to a bundle is optional and does not affect cable tracing or connectivity. Bundles persist independently of their member cables: deleting a cable clears its bundle assignment but does not delete the bundle itself. +Assigning cables to a bundle is optional and does not affect cable tracing or connectivity. Bundles persist independently of their member cables: deleting a cable clears its bundle assignment but does not delete the bundle itself, allowing the bundle to be reused for replacement cables. ## Fields @@ -12,4 +12,4 @@ A unique name for the cable bundle. ### Description -A brief description of the bundle's purpose or contents. +An optional short description of the bundle's purpose or contents. diff --git a/docs/models/dcim/macaddress.md b/docs/models/dcim/macaddress.md index fe3d1f0e3..4931f5eb7 100644 --- a/docs/models/dcim/macaddress.md +++ b/docs/models/dcim/macaddress.md @@ -1,11 +1,25 @@ # MAC Addresses -A MAC address object in NetBox comprises a single Ethernet link layer address, and represents a MAC address as reported by or assigned to a network interface. MAC addresses can be assigned to [device](../dcim/device.md) and [virtual machine](../virtualization/virtualmachine.md) interfaces. A MAC address can be specified as the primary MAC address for a given device or VM interface. +A MAC address object in NetBox represents a single Ethernet link-layer address as reported by or assigned to a network interface. MAC addresses can be assigned to [device interfaces](./interface.md) and [virtual machine interfaces](../virtualization/vminterface.md), and any one of an interface's assigned MAC addresses may be designated as its **primary** MAC address. -Most interfaces have only a single MAC address, hard-coded at the factory. However, on some devices (particularly virtual interfaces) it is possible to assign additional MAC addresses or change existing ones. For this reason NetBox allows multiple MACAddress objects to be assigned to a single interface. +Most physical interfaces have only a single MAC address, hard-coded at the factory. However, some interfaces (particularly virtual interfaces and modular hardware) support multiple or reassignable MAC addresses. To accommodate this, NetBox models MAC addresses as first-class objects which may be created, modified, and reassigned independently of any specific interface. ## Fields ### MAC Address -The 48-bit MAC address, in colon-hexadecimal notation (e.g. `aa:bb:cc:11:22:33`). +The 48-bit MAC address, expressed in colon-hexadecimal notation (for example, `aa:bb:cc:11:22:33`). + +### Assigned Object + +A generic reference to the [device interface](./interface.md) or [virtual machine interface](../virtualization/vminterface.md) to which this MAC address is assigned. A MAC address may exist without being assigned to any interface. + +A MAC address that is currently designated as the primary MAC of its parent interface cannot be reassigned to (or unassigned from) another interface without first clearing the primary designation. + +### Description + +An optional human-readable description of the MAC address. + +### Comments + +Free-form Markdown-supported notes regarding the MAC address. diff --git a/docs/models/dcim/moduletypeprofile.md b/docs/models/dcim/moduletypeprofile.md index 8e9879398..3ab8a51cc 100644 --- a/docs/models/dcim/moduletypeprofile.md +++ b/docs/models/dcim/moduletypeprofile.md @@ -1,8 +1,8 @@ # Module Type Profiles -Each [module type](./moduletype.md) may optionally be assigned a profile according to its classification. A profile can extend module types with user-configured attributes. For example, you might want to specify the input current and voltage of a power supply, or the clock speed and number of cores for a processor. +Each [module type](./moduletype.md) may optionally be assigned a profile according to its classification. A profile can extend module types with user-configured attributes — for example, the input current and voltage of a power supply, or the clock speed and number of cores for a processor. -Module type attributes are managed via the configuration of a [JSON schema](https://json-schema.org/) on the profile. For example, the following schema introduces three module type attributes, two of which are designated as required attributes. +Module type attributes are managed by configuring a [JSON schema](https://json-schema.org/) on the profile. The schema below introduces three module type attributes, two of which are designated as required: ```json { @@ -29,10 +29,22 @@ Module type attributes are managed via the configuration of a [JSON schema](http } ``` -The assignment of module types to a profile is optional. The designation of a schema for a profile is also optional: A profile can be used simply as a mechanism for classifying module types if the addition of custom attributes is not needed. +Both the assignment of module types to a profile and the designation of a schema for a profile are optional: a profile can be used purely as a classification mechanism if the addition of custom attributes is not needed. ## Fields +### Name + +A unique name for the profile (for example, `Power Supply` or `Disk`). + +### Description + +An optional description of the profile. + ### Schema -This field holds the [JSON schema](https://json-schema.org/) for the profile. The configured JSON schema must be valid (or the field must be null). +An optional [JSON schema](https://json-schema.org/) defining the attributes that may (or must) be set on each assigned module type. The schema must be valid JSON Schema, or else null. + +### Comments + +Free-form Markdown-supported notes about the profile. diff --git a/docs/models/extras/configcontextprofile.md b/docs/models/extras/configcontextprofile.md index 289cce20a..118329330 100644 --- a/docs/models/extras/configcontextprofile.md +++ b/docs/models/extras/configcontextprofile.md @@ -1,6 +1,6 @@ # Config Context Profiles -Profiles can be used to organize [configuration contexts](./configcontext.md) and to enforce a desired structure for their data. The later is achieved by defining a [JSON schema](https://json-schema.org/) to which all config context with this profile assigned must comply. +Profiles can be used to organize [configuration contexts](./configcontext.md) and to enforce a desired structure for their data. The latter is achieved by defining a [JSON schema](https://json-schema.org/) to which all config contexts assigned to the profile must comply. Any context whose data fails validation against the profile's schema cannot be saved. For example, the following schema defines two keys, `size` and `priority`, of which the former is required: @@ -22,12 +22,26 @@ For example, the following schema defines two keys, `size` and `priority`, of wh } ``` +A profile's schema may also be populated from a [data source](../core/datasource.md), enabling the schema to be maintained externally (for example, in a git repository) and synchronized into NetBox. + ## Fields ### Name -A unique human-friendly name. +A unique, human-friendly name for the profile. + +### Description + +An optional description of the profile's purpose. ### Schema -The JSON schema to be enforced for all assigned config contexts (optional). +An optional [JSON schema](https://json-schema.org/) document. When set, the schema is enforced for every config context assigned to this profile. Leaving the schema blank allows the profile to be used purely as an organizational grouping. + +### Data Source / Data File / Data Path + +Optional pointers to a remote [data source](../core/datasource.md) and file from which the schema is populated. When configured, the schema field is overwritten on synchronization. + +### Auto Sync Enabled + +When set, the profile's schema is automatically refreshed whenever the upstream data file is updated. diff --git a/docs/models/users/group.md b/docs/models/users/group.md new file mode 100644 index 000000000..a7d0df697 --- /dev/null +++ b/docs/models/users/group.md @@ -0,0 +1,19 @@ +# Groups + +A group is a collection of [users](./user.md) which share a common set of permissions. Assigning [object permissions](./objectpermission.md) to a group, rather than to individual users, simplifies the administration of permissions for related users (e.g. members of a particular team). + +A user inherits the union of all permissions assigned to each group of which they are a member, in addition to any permissions assigned directly to the user. + +## Fields + +### Name + +A unique name for the group. + +### Description + +A short description of the group's role or membership. + +### Object Permissions + +The set of [object permissions](./objectpermission.md) granted to all members of this group. diff --git a/docs/models/users/objectpermission.md b/docs/models/users/objectpermission.md new file mode 100644 index 000000000..67d7a20e0 --- /dev/null +++ b/docs/models/users/objectpermission.md @@ -0,0 +1,50 @@ +# Object Permissions + +An object permission grants the ability to perform one or more actions (e.g. view, add, change, delete) against a defined set of object types, and may be restricted to a subset of objects matching a configured filter. Permissions are assigned to [users](./user.md) and/or [groups](./group.md); a user's effective permissions are the union of those assigned directly and those inherited via group membership. + +See the [permissions documentation](../../administration/permissions.md) for a detailed walkthrough of how permissions are evaluated. + +## Fields + +### Name + +A short, human-readable name for the permission. + +### Description + +An optional longer description of what the permission grants. + +### Enabled + +When unset, the permission is effectively disabled: it remains assigned to its users and groups, but is ignored during permission checks. This is useful for temporarily revoking access without altering assignments. + +### Object Types + +The list of NetBox model types to which this permission applies (e.g. `dcim.device`, `ipam.prefix`). + +### Actions + +The list of actions granted by the permission. The standard CRUD actions are `view`, `add`, `change`, and `delete`. Models may also register custom actions (e.g. `napalm` on `dcim.device`); custom actions appear here when supported by the selected object types. + +### Constraints + +An optional [Django ORM-style filter](https://docs.djangoproject.com/en/stable/topics/db/queries/#field-lookups) expressed as JSON. When set, the permission applies only to objects matching the filter. Multiple constraint sets may be supplied as a JSON list; an object matches if it satisfies any of the sets (logical OR). + +For example, to grant a permission only over devices in a specific site: + +```json +{"site__slug": "ny-dc1"} +``` + +Or, to apply the permission to devices in either of two sites: + +```json +[ + {"site__slug": "ny-dc1"}, + {"site__slug": "sj-dc2"} +] +``` + +### Users & Groups + +The [users](./user.md) and [groups](./group.md) to which this permission is assigned. diff --git a/docs/models/users/ownergroup.md b/docs/models/users/ownergroup.md index 61c279438..db6420325 100644 --- a/docs/models/users/ownergroup.md +++ b/docs/models/users/ownergroup.md @@ -1,9 +1,13 @@ # Owner Groups -Groups are used to correlate and organize [owners](./owner.md). The assignment of an owner to a group has no bearing on the relationship of owned objects to their owners. +Groups are used to correlate and organize [owners](./owner.md). The assignment of an owner to a group has no bearing on the relationship of owned objects to their owners; groups exist purely as an organizational convenience for administrators. ## Fields ### Name -The name of the group. +A unique name for the group. + +### Description + +An optional description of the group's role or membership. diff --git a/docs/models/users/token.md b/docs/models/users/token.md new file mode 100644 index 000000000..2899a703b --- /dev/null +++ b/docs/models/users/token.md @@ -0,0 +1,51 @@ +# Tokens + +A token is a secret credential associated with a [user](./user.md) which authenticates requests to NetBox's REST and GraphQL APIs. A user may hold multiple tokens; each can be independently expired, restricted, or revoked. + +Beginning with NetBox v4.5, two token versions are supported. v2 tokens (the default for newly-created tokens) are stored only as a salted HMAC digest, and the plaintext is shown to the user only once at creation time. Legacy v1 tokens store the plaintext directly and are retained for backward compatibility; their use is discouraged. See the [REST API authentication](../../integrations/rest-api.md#authentication) documentation for the request header formats used by each version. + +## Fields + +### Version + +Indicates whether this is a v1 (legacy) or v2 token. v2 is the default and is strongly preferred. + +### User + +The [user](./user.md) which owns the token. All requests authenticated with the token are performed as this user. + +### Description + +A free-form description of the token (e.g. naming the application or automation that uses it). + +### Created + +The date and time at which the token was created. + +### Expires + +An optional date and time after which the token will no longer be valid. Tokens without an expiration never expire. + +### Last Used + +The date and time at which the token was most recently used to authenticate a request. This value is updated at most once per minute to limit database write overhead. + +### Enabled + +When unset, the token is temporarily revoked. Disabled tokens cannot be used to authenticate requests but are not deleted, allowing them to be re-enabled later. + +### Write Enabled + +When unset, the token may only be used for read operations (e.g. `GET`). All write operations (`POST`, `PATCH`, `PUT`, `DELETE`) made with the token will be rejected. + +### Allowed IPs + +An optional list of IPv4 and/or IPv6 prefixes from which the token may be used. If set, requests originating from any other source address will be rejected. + +### Key (v2 only) + +A short, randomly-generated identifier transmitted in plaintext alongside each request. The key allows the server to locate the matching token record before validating the secret portion. + +### Plaintext (v1 only) + +The full plaintext value of a v1 token. Stored as-is in the database, which is one of the reasons v2 tokens are preferred. diff --git a/docs/models/users/user.md b/docs/models/users/user.md new file mode 100644 index 000000000..0bbfeeed0 --- /dev/null +++ b/docs/models/users/user.md @@ -0,0 +1,47 @@ +# Users + +A user represents an individual account in NetBox. Users authenticate to access the application, and may be granted permissions either directly or through their assigned [groups](./group.md). Each user can hold one or more API [tokens](./token.md) for use with the REST and GraphQL APIs. + +NetBox extends Django's stock user model to support multiple API tokens per user, configurable [object permissions](./objectpermission.md), and integration with [remote authentication backends](../../administration/authentication/overview.md). + +## Fields + +### Username + +A unique identifier used to log in. May contain letters, digits, and the characters `@ . + - _`. Username comparison is case-insensitive: a new user cannot be created whose username differs from an existing one only in letter case. + +### First Name + +The user's given name. Optional. + +### Last Name + +The user's family name. Optional. + +### Email Address + +The user's email address. Used by NetBox to send notifications (e.g. error reports) when configured to do so. + +### Active + +When unset, the user is treated as inactive and may not log in. Disabling a user is generally preferable to deletion, as it preserves the user's history in change records and other related objects. + +### Staff Status + +Designates whether the user can log into the (legacy) Django admin site. Most NetBox functionality is exposed via the standard UI; staff status is rarely needed. + +### Superuser Status + +Designates that the user is granted all permissions implicitly, bypassing all permission checks. Use sparingly. + +### Date Joined + +The date and time at which the user account was created. + +### Groups + +The set of [groups](./group.md) to which the user belongs. A user inherits all permissions assigned to each of their groups. + +### Object Permissions + +The set of [object permissions](./objectpermission.md) assigned directly to the user, in addition to those granted via group membership. diff --git a/docs/plugins/development/index.md b/docs/plugins/development/index.md index 25f8b68df..b94639300 100644 --- a/docs/plugins/development/index.md +++ b/docs/plugins/development/index.md @@ -116,9 +116,10 @@ NetBox looks for the `config` variable within a plugin's `__init__.py` to load i | `middleware` | A list of middleware classes to append after NetBox's build-in middleware | | `queues` | A list of custom background task queues to create | | `events_pipeline` | A list of handlers to add to [`EVENTS_PIPELINE`](../../configuration/miscellaneous.md#events_pipeline), identified by dotted paths | -| `search_extensions` | The dotted path to the list of search index classes (default: `search.indexes`) | +| `search_indexes` | The dotted path to the list of search index classes (default: `search.indexes`) | | `data_backends` | The dotted path to the list of data source backend classes (default: `data_backends.backends`) | | `template_extensions` | The dotted path to the list of template extension classes (default: `template_content.template_extensions`) | +| `menu` | The dotted path to a top-level navigation menu provided by the plugin (default: `navigation.menu`) | | `menu_items` | The dotted path to the list of menu items provided by the plugin (default: `navigation.menu_items`) | | `graphql_schema` | The dotted path to the plugin's GraphQL schema class, if any (default: `graphql.schema`) | | `user_preferences` | The dotted path to the dictionary mapping of user preferences defined by the plugin (default: `preferences.preferences`) | diff --git a/docs/plugins/development/permissions.md b/docs/plugins/development/permissions.md index 62a1ede1b..0fb3b0618 100644 --- a/docs/plugins/development/permissions.md +++ b/docs/plugins/development/permissions.md @@ -1,24 +1,71 @@ # Custom Model Actions -Plugins can register custom permission actions for their models. These actions appear as checkboxes in the ObjectPermission form, making it easy for administrators to grant or restrict access to plugin-specific functionality without manually entering action names. +Plugins can register custom permission actions for their models. These actions appear as checkboxes in the [ObjectPermission](../../models/users/objectpermission.md) form alongside the standard view/add/change/delete actions, making it easy for administrators to grant or restrict access to plugin-specific functionality without manually entering action names. -For example, a plugin might define a "sync" action for a model that syncs data from an external source, or a "bypass" action that allows users to bypass certain restrictions. +For example, a plugin might define a `sync` action for a model that fetches data from an external source, or a `bypass` action that allows users to skip certain restrictions. ## Registering Model Actions -The preferred way to register custom actions is via Django's `Meta.permissions` on the model class. NetBox will automatically register these as model actions when the app is loaded: +The preferred way to register custom actions is via Django's `Meta.permissions` on the model class. NetBox automatically registers these as model actions when the app is loaded: -```python +```python title="models.py" from netbox.models import NetBoxModel -class MyModel(NetBoxModel): - # ... +class WidgetSync(NetBoxModel): + # ... fields ... class Meta: permissions = [ - ('sync', 'Synchronize data from external source'), - ('export', 'Export data to external system'), + ('sync', 'Synchronize widgets from external source'), + ('export', 'Export widgets to external system'), ] ``` -Once registered, these actions appear as checkboxes in a flat list when creating or editing an ObjectPermission. +Once registered, these actions appear as checkboxes in a flat list when creating or editing an ObjectPermission. The first element of each tuple is the action's identifier (used in code) and the second is the help text shown to administrators in the UI. + +!!! note "Reserved action names" + Action names that conflict with NetBox's built-in CRUD verbs (`view`, `add`, `change`, `delete`) are reserved and cannot be reused as custom actions. + +## Granting an Action + +Custom actions are granted just like any standard permission: + +1. Open **Admin → Object Permissions** and create a new permission. +2. Select the relevant object type(s) (e.g. `my_plugin | widget sync`). +3. Tick the custom action's checkbox (e.g. `sync`). +4. Assign the permission to the desired users and/or groups. + +Optional [constraints](../../models/users/objectpermission.md#constraints) may be added to limit the permission to a subset of objects. + +## Checking an Action at Runtime + +Custom actions follow Django's standard permission naming convention `._`. To check whether the current user is authorized to perform a custom action against a model, call `user.has_perm()`: + +```python +if request.user.has_perm('my_plugin.sync_widgetsync'): + # User is permitted to invoke the sync action + ... +``` + +Per-object permission checks (which respect any [constraints](../../models/users/objectpermission.md#constraints) on the granting permission) work the same way: + +```python +if request.user.has_perm('my_plugin.sync_widgetsync', obj=widget): + ... +``` + +For class-based views, NetBox provides `ObjectPermissionRequiredMixin` from `utilities.views`, which integrates cleanly with these custom actions: + +```python title="views.py" +from utilities.views import ObjectPermissionRequiredMixin +from django.views.generic import View + +class SyncWidgetView(ObjectPermissionRequiredMixin, View): + queryset = WidgetSync.objects.all() + permission_required = 'my_plugin.sync_widgetsync' + + def post(self, request, pk): + widget = self.get_object() + widget.sync() + return redirect(widget.get_absolute_url()) +``` diff --git a/mkdocs.yml b/mkdocs.yml index 60bc2c643..36a1abcaf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -189,6 +189,8 @@ nav: - DataFile: 'models/core/datafile.md' - DataSource: 'models/core/datasource.md' - Job: 'models/core/job.md' + - ObjectChange: 'models/core/objectchange.md' + - ObjectType: 'models/core/objecttype.md' - DCIM: - Cable: 'models/dcim/cable.md' - CableBundle: 'models/dcim/cablebundle.md' @@ -280,8 +282,12 @@ nav: - Tenant: 'models/tenancy/tenant.md' - TenantGroup: 'models/tenancy/tenantgroup.md' - Users: + - Group: 'models/users/group.md' + - ObjectPermission: 'models/users/objectpermission.md' - Owner: 'models/users/owner.md' - OwnerGroup: 'models/users/ownergroup.md' + - Token: 'models/users/token.md' + - User: 'models/users/user.md' - Virtualization: - Cluster: 'models/virtualization/cluster.md' - ClusterGroup: 'models/virtualization/clustergroup.md' diff --git a/netbox/netbox/configuration_example.py b/netbox/netbox/configuration_example.py index ad73b11c7..528d5ed48 100644 --- a/netbox/netbox/configuration_example.py +++ b/netbox/netbox/configuration_example.py @@ -168,7 +168,7 @@ LOGGING = {} LOGIN_PERSISTENCE = False # The length of time (in seconds) for which a user will remain logged into the web UI before being prompted to -# re-authenticate. (Default: 1209600 [14 days]) +# re-authenticate. If set to None (the default), Django's SESSION_COOKIE_AGE is used (two weeks). LOGIN_TIMEOUT = None # Hide the login form. Useful when only allowing SSO authentication. From 734a69c9a761d9eaaeb888d4cbd17e4e2e49c73f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 11:14:02 -0400 Subject: [PATCH 010/131] Closes #22141: Deprecate support for PostgreSQL 14 (#22142) --- docs/configuration/required-parameters.md | 2 +- docs/installation/1-postgresql.md | 3 +++ docs/installation/index.md | 4 ++- docs/installation/upgrading.md | 5 +++- docs/introduction.md | 4 ++- netbox/core/apps.py | 2 +- netbox/core/checks.py | 30 ++++++++++++++++++++++- 7 files changed, 44 insertions(+), 6 deletions(-) diff --git a/docs/configuration/required-parameters.md b/docs/configuration/required-parameters.md index 72573afad..6411fdea7 100644 --- a/docs/configuration/required-parameters.md +++ b/docs/configuration/required-parameters.md @@ -59,7 +59,7 @@ See the [`DATABASES`](#databases) configuration below for usage. ## DATABASES -NetBox requires access to a PostgreSQL 14 or later database service to store data. This service can run locally on the NetBox server or on a remote system. Databases are defined as named dictionaries: +NetBox requires access to a PostgreSQL 14 or later database service to store data. Note that support for PostgreSQL 14 is deprecated and will be removed in NetBox v4.7; PostgreSQL 15 or later will be required. This service can run locally on the NetBox server or on a remote system. Databases are defined as named dictionaries: ```python DATABASES = { diff --git a/docs/installation/1-postgresql.md b/docs/installation/1-postgresql.md index 41751fc10..adb535aaf 100644 --- a/docs/installation/1-postgresql.md +++ b/docs/installation/1-postgresql.md @@ -5,6 +5,9 @@ This section entails the installation and configuration of a local PostgreSQL da !!! warning "PostgreSQL 14 or later required" NetBox requires PostgreSQL 14 or later. Please note that MySQL and other relational databases are **not** supported. +!!! warning "PostgreSQL 14 deprecation notice" + Support for PostgreSQL 14 is deprecated as of NetBox v4.6 and will be removed in NetBox v4.7. Please plan to upgrade to PostgreSQL 15 or later. + ## Installation ```no-highlight diff --git a/docs/installation/index.md b/docs/installation/index.md index 7ef8dd0d4..53e39ec5a 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -28,9 +28,11 @@ The following sections detail how to set up a new instance of NetBox: | Dependency | Supported Versions | |------------|--------------------| | Python | 3.12, 3.13, 3.14 | -| PostgreSQL | 14+ | +| PostgreSQL | 14+ [^1] | | Redis | 4.0+ | +[^1]: Support for PostgreSQL 14 is deprecated and will be removed in NetBox v4.7. PostgreSQL 15 or later will be required. + Below is a simplified overview of the NetBox application stack for reference: ![NetBox UI as seen by a non-authenticated user](../media/installation/netbox_application_stack.png) diff --git a/docs/installation/upgrading.md b/docs/installation/upgrading.md index 5110def57..938fcc68c 100644 --- a/docs/installation/upgrading.md +++ b/docs/installation/upgrading.md @@ -20,13 +20,16 @@ NetBox requires the following dependencies: | Dependency | Supported Versions | |------------|--------------------| | Python | 3.12, 3.13, 3.14 | -| PostgreSQL | 14+ | +| PostgreSQL | 14+ [^1] | | Redis | 4.0+ | +[^1]: Support for PostgreSQL 14 is deprecated and will be removed in NetBox v4.7. PostgreSQL 15 or later will be required. + ### Version History | NetBox Version | Python min | Python max | PostgreSQL min | Redis min | Documentation | |:--------------:|:----------:|:----------:|:--------------:|:---------:|:-----------------------------------------------------------------------------------------:| +| 4.6 | 3.12 | 3.14 | 14 | 4.0 | [Link](https://github.com/netbox-community/netbox/blob/v4.6.0/docs/installation/index.md) | | 4.5 | 3.12 | 3.14 | 14 | 4.0 | [Link](https://github.com/netbox-community/netbox/blob/v4.5.0/docs/installation/index.md) | | 4.4 | 3.10 | 3.12 | 14 | 4.0 | [Link](https://github.com/netbox-community/netbox/blob/v4.4.0/docs/installation/index.md) | | 4.3 | 3.10 | 3.12 | 14 | 4.0 | [Link](https://github.com/netbox-community/netbox/blob/v4.3.0/docs/installation/index.md) | diff --git a/docs/introduction.md b/docs/introduction.md index c8e5ee8ac..fee89559a 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -79,5 +79,7 @@ NetBox is built on the [Django](https://djangoproject.com/) Python framework and | HTTP service | nginx or Apache | | WSGI service | gunicorn or uWSGI | | Application | Django/Python | -| Database | PostgreSQL 14+ | +| Database | PostgreSQL 14+ [^1] | | Task queuing | Redis/django-rq | + +[^1]: Support for PostgreSQL 14 is deprecated and will be removed in NetBox v4.7. PostgreSQL 15 or later will be required. diff --git a/netbox/core/apps.py b/netbox/core/apps.py index 68b65f58c..86ed763b5 100644 --- a/netbox/core/apps.py +++ b/netbox/core/apps.py @@ -22,7 +22,7 @@ class CoreConfig(AppConfig): def ready(self): from core.api import schema # noqa: F401 - from core.checks import check_duplicate_indexes # noqa: F401 + from core.checks import check_duplicate_indexes, check_postgresql_version # noqa: F401 from netbox import context_managers # noqa: F401 from netbox.models.features import register_models diff --git a/netbox/core/checks.py b/netbox/core/checks.py index 430eacbec..90300bdd3 100644 --- a/netbox/core/checks.py +++ b/netbox/core/checks.py @@ -1,9 +1,11 @@ from django.apps import apps -from django.core.checks import Error, Tags, register +from django.core.checks import Error, Tags, Warning, register +from django.db import connection from django.db.models import Index, UniqueConstraint __all__ = ( 'check_duplicate_indexes', + 'check_postgresql_version', ) @@ -39,3 +41,29 @@ def check_duplicate_indexes(app_configs, **kwargs): ) return errors + + +@register(Tags.database) +def check_postgresql_version(app_configs, **kwargs): + """ + Warn if the PostgreSQL version is less than 15, as support for PostgreSQL 14 + will be removed in NetBox v4.7. + """ + warnings = [] + try: + with connection.cursor() as cursor: + cursor.execute('SHOW server_version_num') + row = cursor.fetchone() + pg_version = int(row[0]) + if pg_version < 150000: + major_version = pg_version // 10000 + warnings.append( + Warning( + f'Support for PostgreSQL {major_version} is deprecated and will be removed in NetBox v4.7.', + hint='Please upgrade to PostgreSQL 15 or later.', + id='netbox.W001', + ) + ) + except Exception: + pass + return warnings From 2703ff98a3d611f2b4b2950f08866ce423e5d8cb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 11:48:25 -0400 Subject: [PATCH 011/131] Closes #22128: Deprecate v1 API tokens (#22143) Display a warning in the UI whenever a user goes to provision a v1 token (both via the admin token form and the user profile token form). Update documentation to note that v1 tokens are deprecated and will be removed in NetBox v5.0. --- docs/integrations/rest-api.md | 5 ++++- docs/models/users/token.md | 4 ++-- netbox/templates/account/usertoken_edit.html | 22 +++++++++++++++++++ .../templates/users/inc/v1_token_warning.html | 17 ++++++++++++++ netbox/templates/users/token_edit.html | 18 +++++++++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 netbox/templates/users/inc/v1_token_warning.html diff --git a/docs/integrations/rest-api.md b/docs/integrations/rest-api.md index a9cbda4dc..d55471168 100644 --- a/docs/integrations/rest-api.md +++ b/docs/integrations/rest-api.md @@ -792,7 +792,10 @@ Additionally, a token can be set to expire at a specific time. This can be usefu #### v1 and v2 Tokens -Beginning with NetBox v4.5, two versions of API token are supported, denoted as v1 and v2. Users are strongly encouraged to create only v2 tokens and to discontinue the use of v1 tokens. Support for v1 tokens will be removed in a future NetBox release. +!!! warning "v1 Tokens Are Deprecated" + v1 API tokens are deprecated as of NetBox v4.6 and will be removed in NetBox v5.0. All users should migrate to v2 tokens. + +Beginning with NetBox v4.5, two versions of API token are supported, denoted as v1 and v2. Users are strongly encouraged to create only v2 tokens and to discontinue the use of v1 tokens. v2 API tokens offer much stronger security. The token plaintext given at creation time is hashed together with a configured [cryptographic pepper](../configuration/required-parameters.md#api_token_peppers) to generate a unique checksum. This checksum is irreversible; the token plaintext is never stored on the server and thus cannot be retrieved even with database-level access. diff --git a/docs/models/users/token.md b/docs/models/users/token.md index 2899a703b..0d8481760 100644 --- a/docs/models/users/token.md +++ b/docs/models/users/token.md @@ -2,13 +2,13 @@ A token is a secret credential associated with a [user](./user.md) which authenticates requests to NetBox's REST and GraphQL APIs. A user may hold multiple tokens; each can be independently expired, restricted, or revoked. -Beginning with NetBox v4.5, two token versions are supported. v2 tokens (the default for newly-created tokens) are stored only as a salted HMAC digest, and the plaintext is shown to the user only once at creation time. Legacy v1 tokens store the plaintext directly and are retained for backward compatibility; their use is discouraged. See the [REST API authentication](../../integrations/rest-api.md#authentication) documentation for the request header formats used by each version. +Beginning with NetBox v4.5, two token versions are supported. v2 tokens (the default for newly-created tokens) are stored only as a salted HMAC digest, and the plaintext is shown to the user only once at creation time. Legacy v1 tokens store the plaintext directly; **their use is deprecated and support will be removed in NetBox v5.0.** See the [REST API authentication](../../integrations/rest-api.md#authentication) documentation for the request header formats used by each version. ## Fields ### Version -Indicates whether this is a v1 (legacy) or v2 token. v2 is the default and is strongly preferred. +Indicates whether this is a v1 (legacy) or v2 token. v2 is the default and is strongly preferred. **v1 tokens are deprecated and will be removed in NetBox v5.0.** ### User diff --git a/netbox/templates/account/usertoken_edit.html b/netbox/templates/account/usertoken_edit.html index 7f88d4f0c..fb2d315b2 100644 --- a/netbox/templates/account/usertoken_edit.html +++ b/netbox/templates/account/usertoken_edit.html @@ -1,6 +1,28 @@ {% extends 'generic/object_edit.html' %} {% load i18n %} +{% block content %} + {% include 'users/inc/v1_token_warning.html' %} + {{ block.super }} +{% endblock %} + +{% block javascript %} +{{ block.super }} + +{% endblock javascript %} + {% block buttons %} {# Omit the "Create & Add Another" button: that flow would redirect away from the detail page before the #} {# one-time plaintext can be displayed, leaving the new token unrecoverable. #} diff --git a/netbox/templates/users/inc/v1_token_warning.html b/netbox/templates/users/inc/v1_token_warning.html new file mode 100644 index 000000000..940ea4a23 --- /dev/null +++ b/netbox/templates/users/inc/v1_token_warning.html @@ -0,0 +1,17 @@ +{% load i18n %} + diff --git a/netbox/templates/users/token_edit.html b/netbox/templates/users/token_edit.html index 6ca2fe860..0b39a4ceb 100644 --- a/netbox/templates/users/token_edit.html +++ b/netbox/templates/users/token_edit.html @@ -5,9 +5,27 @@ {% if not request.user.is_superuser %} {% include 'inc/alerts/warning.html' with title="Creating API Tokens" message="Non-superusers should generally create and modify API tokens under their user profile." %} {% endif %} + {% include 'users/inc/v1_token_warning.html' %} {{ block.super }} {% endblock %} +{% block javascript %} +{{ block.super }} + +{% endblock javascript %} + {% block buttons %} {# Omit the "Create & Add Another" button: that flow would redirect away from the detail page before the #} {# one-time plaintext can be displayed, leaving the new token unrecoverable. #} From 088de70b1087fd4c0a181d5792ed090bea41955a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 12:13:02 -0400 Subject: [PATCH 012/131] Remove prohibition on AI-generated PRs and add guidance to AGENTS.md (#22133) --- AGENTS.md | 20 ++++++++++++++++++++ CONTRIBUTING.md | 3 --- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6d948793b..c6c9b5cbf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -273,6 +273,26 @@ GitHub Actions workflows in `.github/workflows/`: - Every PR must reference an approved GitHub issue. - PRs must include tests for new functionality. +## PR Submission Requirements + +**Do not open a PR unless all the following conditions are met:** + +1. **Issue reference required** — The PR body must include a `Closes: #` line identifying the associated GitHub issue. PRs without this line must not be submitted. +2. **Issue must be open** — Before opening a PR, verify via `gh issue view ` that the referenced issue is currently open. Do not submit a PR against a closed issue. +3. **Issue must be assigned to you** — Verify that the referenced issue is assigned to the submitting user. Do not open a PR for an issue that is unassigned or assigned to someone else. +4. **No exceptions without maintainer status** — These three requirements are waived only for project maintainers (members of the `netboxlabs` GitHub organization). All other contributors must satisfy all three checks before a PR is opened. + +**Pre-submission checklist for AI agents:** + +```bash +# Confirm the issue is open and assigned before opening a PR +gh issue view --json state,assignees +``` + +Reject the PR submission and report the problem if the issue is closed, unassigned, or assigned to a different user. + +Do not include an entry in the release notes for the PR unless explicitly instructed to do so. (Release notes are typically generated in aggregate as part of the release process to avoid merge conflicts.) + ## Troubleshooting - **Wrong directory for `manage.py`** — `manage.py` lives in `netbox/`, not the repo root. Always `cd netbox/` first or use the full path. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 577268bef..a98f40e5c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -102,9 +102,6 @@ intake policy](https://github.com/netbox-community/netbox/wiki/Issue-Intake-Poli * All tests pass when run with `NETBOX_CONFIGURATION=netbox.configuration_testing ./manage.py test` * `ruff check` successfully validates style compliance -> [!CAUTION] -> Any contributions which include solely AI-generated content will be rejected. All PRs must be submitted by a human. - * Some other tips to keep in mind: * If you'd like to volunteer for someone else's issue, please post a comment on that issue letting us know. (GitHub allows only people who have commented on an issue to be assigned as its owner.) * Check out our [developer docs](https://docs.netbox.dev/en/stable/development/getting-started/) for tips on setting up your development environment. From f2187ceb8f61004a5335701ff8aef65d68f00bae Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 12:22:14 -0400 Subject: [PATCH 013/131] Closes #22102: Add a GIN index on CablePath to optimize filtering of cable paths by node (#22144) --- .../dcim/migrations/0234_cablepath_nodes_index.py | 15 +++++++++++++++ netbox/dcim/models/cables.py | 6 ++++++ 2 files changed, 21 insertions(+) create mode 100644 netbox/dcim/migrations/0234_cablepath_nodes_index.py diff --git a/netbox/dcim/migrations/0234_cablepath_nodes_index.py b/netbox/dcim/migrations/0234_cablepath_nodes_index.py new file mode 100644 index 000000000..af4f506a5 --- /dev/null +++ b/netbox/dcim/migrations/0234_cablepath_nodes_index.py @@ -0,0 +1,15 @@ +import django.contrib.postgres.indexes +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0233_device_render_config_permission'), + ] + + operations = [ + migrations.AddIndex( + model_name='cablepath', + index=django.contrib.postgres.indexes.GinIndex(fields=['_nodes'], name='dcim_cablep__nodes_b23b96_gin'), + ), + ] diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index 06b5606bc..fb0d87067 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -5,6 +5,7 @@ from collections import Counter from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.fields import ArrayField +from django.contrib.postgres.indexes import GinIndex from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models @@ -730,6 +731,11 @@ class CablePath(models.Model): _netbox_private = True class Meta: + indexes = ( + # GIN index supports @> operator used by `_nodes__contains` lookups, + # which fire on every cable/termination delete and path retrace. + GinIndex(fields=('_nodes',)), + ) verbose_name = _('cable path') verbose_name_plural = _('cable paths') From c20e6dd2ee562888261330c99266165e36ad0664 Mon Sep 17 00:00:00 2001 From: Jason Novinger Date: Thu, 7 May 2026 11:23:00 -0500 Subject: [PATCH 014/131] Closes #20776: Add changelog message to bulk rename process (#22100) Add changelog message support to BulkRenameView for models that support change logging. Introduce NetBoxModelBulkRenameForm as a changelog-aware wrapper around the existing utilities.forms.BulkRenameForm, preserving the existing import path while avoiding circular imports. Set _changelog_message before saving renamed objects in both MPTT and non-MPTT rename paths, and add a regression test to verify that the submitted message is recorded on the resulting ObjectChange records. Remove unused VMInterfaceBulkRenameForm and VirtualDiskBulkRenameForm, along with their unused view references, since BulkRenameView constructs its form dynamically. --- netbox/netbox/forms/__init__.py | 1 + netbox/netbox/forms/bulk_rename.py | 14 +++++++++ netbox/netbox/views/generic/bulk_views.py | 13 +++++++-- netbox/utilities/testing/views.py | 35 +++++++++++++++++++++++ netbox/virtualization/forms/bulk_edit.py | 18 +----------- netbox/virtualization/views.py | 2 -- 6 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 netbox/netbox/forms/bulk_rename.py diff --git a/netbox/netbox/forms/__init__.py b/netbox/netbox/forms/__init__.py index fe5e5f7d3..e61824035 100644 --- a/netbox/netbox/forms/__init__.py +++ b/netbox/netbox/forms/__init__.py @@ -1,5 +1,6 @@ from .bulk_edit import * from .bulk_import import * +from .bulk_rename import * from .filtersets import * from .model_forms import * from .search import * diff --git a/netbox/netbox/forms/bulk_rename.py b/netbox/netbox/forms/bulk_rename.py new file mode 100644 index 000000000..975466f6a --- /dev/null +++ b/netbox/netbox/forms/bulk_rename.py @@ -0,0 +1,14 @@ +from utilities.forms import BulkRenameForm + +from .mixins import ChangelogMessageMixin + +__all__ = ( + 'NetBoxModelBulkRenameForm', +) + + +class NetBoxModelBulkRenameForm(ChangelogMessageMixin, BulkRenameForm): + """ + Extends BulkRenameForm with a changelog message field for NetBox models that support change logging. + """ + pass diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index 8f0a98b50..41eeaba88 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -22,6 +22,7 @@ from core.models import ObjectType from core.signals import clear_events from extras.choices import CustomFieldUIEditableChoices from extras.models import CustomField, ExportTemplate +from netbox.forms.bulk_rename import NetBoxModelBulkRenameForm from netbox.models.features import ChangeLoggingMixin from netbox.object_actions import AddObject, BulkDelete, BulkEdit, BulkExport, BulkImport, BulkRename from utilities.error_handlers import handle_protectederror @@ -881,8 +882,14 @@ class BulkRenameView(GetReturnURLMixin, BaseMultiObjectView): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Create a new Form class from BulkRenameForm - class _Form(BulkRenameForm): + # Use the changelog-aware form for models that support change logging + base_form = ( + NetBoxModelBulkRenameForm + if issubclass(self.queryset.model, ChangeLoggingMixin) + else BulkRenameForm + ) + + class _Form(base_form): pk = ModelMultipleChoiceField( queryset=self.queryset, widget=MultipleHiddenInput() @@ -940,10 +947,12 @@ class BulkRenameView(GetReturnURLMixin, BaseMultiObjectView): with self.queryset.model.objects.delay_mptt_updates(): for obj in selected_objects: setattr(obj, self.field_name, obj.new_name) + obj._changelog_message = form.cleaned_data.get('changelog_message', '') obj.save() else: for obj in selected_objects: setattr(obj, self.field_name, obj.new_name) + obj._changelog_message = form.cleaned_data.get('changelog_message', '') obj.save() # Enforce constrained permissions diff --git a/netbox/utilities/testing/views.py b/netbox/utilities/testing/views.py index 6abea2f98..38edc8aa9 100644 --- a/netbox/utilities/testing/views.py +++ b/netbox/utilities/testing/views.py @@ -1049,6 +1049,41 @@ class ViewTestCases: for i, instance in enumerate(self._get_queryset().filter(pk__in=pk_list)): self.assertEqual(instance.name, f'{objects[i].name}X') + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_bulk_rename_objects_with_changelog_message(self): + if not issubclass(self.model, ChangeLoggingMixin): + self.skipTest("Model does not support change logging") + objects = self._get_queryset().all()[:3] + pk_list = [obj.pk for obj in objects] + data = { + 'pk': pk_list, + '_apply': True, + 'changelog_message': 'Bulk rename test message', + } + data.update(self.rename_data) + + # Assign model-level permission + obj_perm = ObjectPermission( + name='Test permission', + actions=['change'] + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) + + self.assertHttpStatus(self.client.post(self._get_url('bulk_rename'), data), 302) + + # Verify changelog message was recorded on each renamed object + object_type = ObjectType.objects.get_for_model(self.model) + for pk in pk_list: + oc = ObjectChange.objects.filter( + changed_object_type=object_type, + changed_object_id=pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ).order_by('-time').first() + self.assertIsNotNone(oc) + self.assertEqual(oc.message, 'Bulk rename test message') + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) def test_bulk_rename_objects_with_constrained_permission(self): objects = self._get_queryset().all()[:3] diff --git a/netbox/virtualization/forms/bulk_edit.py b/netbox/virtualization/forms/bulk_edit.py index f51e51e60..6f0feaf0e 100644 --- a/netbox/virtualization/forms/bulk_edit.py +++ b/netbox/virtualization/forms/bulk_edit.py @@ -11,7 +11,7 @@ from ipam.models import VLAN, VRF, VLANGroup, VLANTranslationPolicy from netbox.forms import NetBoxModelBulkEditForm, OrganizationalModelBulkEditForm, PrimaryModelBulkEditForm from netbox.forms.mixins import OwnerMixin from tenancy.models import Tenant -from utilities.forms import BulkRenameForm, add_blank_choice +from utilities.forms import add_blank_choice from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField from utilities.forms.rendering import FieldSet from utilities.forms.utils import get_capacity_unit_label @@ -25,9 +25,7 @@ __all__ = ( 'ClusterGroupBulkEditForm', 'ClusterTypeBulkEditForm', 'VMInterfaceBulkEditForm', - 'VMInterfaceBulkRenameForm', 'VirtualDiskBulkEditForm', - 'VirtualDiskBulkRenameForm', 'VirtualMachineBulkEditForm', 'VirtualMachineTypeBulkEditForm', ) @@ -343,13 +341,6 @@ class VMInterfaceBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): self.fields['bridge'].widget.attrs['disabled'] = True -class VMInterfaceBulkRenameForm(BulkRenameForm): - pk = forms.ModelMultipleChoiceField( - queryset=VMInterface.objects.all(), - widget=forms.MultipleHiddenInput() - ) - - class VirtualDiskBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): virtual_machine = forms.ModelChoiceField( label=_('Virtual machine'), @@ -379,10 +370,3 @@ class VirtualDiskBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): # Set unit label based on configured DISK_BASE_UNIT (MB vs MiB) self.fields['size'].label = _('Size ({unit})').format(unit=get_capacity_unit_label(settings.DISK_BASE_UNIT)) - - -class VirtualDiskBulkRenameForm(BulkRenameForm): - pk = forms.ModelMultipleChoiceField( - queryset=VirtualDisk.objects.all(), - widget=forms.MultipleHiddenInput() - ) diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index d6a758dad..a90a20a73 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -744,7 +744,6 @@ class VMInterfaceBulkEditView(generic.BulkEditView): class VMInterfaceBulkRenameView(generic.BulkRenameView): queryset = VMInterface.objects.all() filterset = filtersets.VMInterfaceFilterSet - form = forms.VMInterfaceBulkRenameForm @register_model_view(VMInterface, 'bulk_delete', path='delete', detail=False) @@ -817,7 +816,6 @@ class VirtualDiskBulkEditView(generic.BulkEditView): class VirtualDiskBulkRenameView(generic.BulkRenameView): queryset = VirtualDisk.objects.all() filterset = filtersets.VirtualDiskFilterSet - form = forms.VirtualDiskBulkRenameForm @register_model_view(VirtualDisk, 'bulk_delete', path='delete', detail=False) From 3d0308a95fd1b8b9a9fb982440034b948609ddf9 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 13:28:38 -0400 Subject: [PATCH 015/131] Add Claude skills for removing models & fields --- .claude/skills/remove-model-field/SKILL.md | 213 +++++++++++++++++++++ .claude/skills/remove-model/SKILL.md | 194 +++++++++++++++++++ 2 files changed, 407 insertions(+) create mode 100644 .claude/skills/remove-model-field/SKILL.md create mode 100644 .claude/skills/remove-model/SKILL.md diff --git a/.claude/skills/remove-model-field/SKILL.md b/.claude/skills/remove-model-field/SKILL.md new file mode 100644 index 000000000..39629f674 --- /dev/null +++ b/.claude/skills/remove-model-field/SKILL.md @@ -0,0 +1,213 @@ +--- +name: remove-model-field +description: Step-by-step checklist for removing a field from an existing NetBox model, covering all required touch points (model, migration, serializer, forms, filterset, table, panel/template, search, GraphQL, tests, docs). Use when the user asks to remove or delete a field or attribute from an existing model. +--- + +# Removing a Field from an Existing NetBox Model + +Removing a field touches many files. Work through the checklist below in order — remove outer consumers first (tests, docs, GraphQL, API, forms) before touching the model definition itself. + +## Before You Start + +Determine upfront: +- **Field name** and which **model/app** owns it +- **Field type**: scalar, FK/M2M, GenericForeignKey, or special (JSONField, etc.) +- **All references** — run a broad grep before touching anything: + +```bash +grep -r 'new_field\|related_thing' netbox/ --include='*.py' -l +grep -r 'new_field\|related_thing' docs/ -l +``` + +For FK/M2M fields, also check for FilterSet `_id` companions and GraphQL lazy annotations referencing this field. + +**Check dependents**: if other models or code use this field (e.g. ordering, constraints, signal handlers), those references must be cleaned up too. + +## 1. Update Tests + +Update test files to remove references to the field being deleted. Specifically: + +- **`tests/test_filtersets.py`** — remove `test_` and `test__id` methods; remove the field from `setUpTestData` test objects. +- **`tests/test_api.py`** — remove the field from `setUpTestData`, `create_data`, and `bulk_update_data`; remove any `test_list_objects_by_` methods. +- **`tests/test_views.py`** — remove the field from `form_data`, `bulk_edit_data`, and `csv_data` in `setUpTestData`. +- **`tests/test_models.py`** — remove any `test_clean_` or constraint tests specific to this field. + +## 2. Update Documentation + +**File:** `docs/models//.md` + +Remove the field's entry from the `## Fields` section. If the field had any cross-references in other doc pages, remove those too. + +## 3. Update GraphQL + +### Filter — `graphql/filters.py` + +Remove the filter field declaration(s) for the deleted field: + +```python +# Remove lines like: +new_field: StrFilterLookup[str] | None = strawberry_django.filter_field() + +# Or for FK: +related_thing: Annotated[...] | None = strawberry_django.filter_field() +related_thing_id: ID | None = strawberry_django.filter_field() +``` + +### Type — `graphql/types.py` + +For simple fields, `fields='__all__'` means no change is needed — the field disappears automatically once removed from the model. + +For FK fields with an explicit annotation, remove the annotation line: + +```python +# Remove: +related_thing: Annotated['RelatedThingType', strawberry.lazy('.graphql.types')] | None +``` + +If the field was in an `exclude` list, remove it from the exclude list (it no longer exists to exclude). + +## 4. Update the API Serializer + +**File:** `netbox//api/serializers_/.py` + +- **Simple field**: remove the field name from `Meta.fields` (and `brief_fields` if present). +- **FK field**: remove the serializer field declaration and its name from `Meta.fields`: + +```python +# Remove: +related_thing = RelatedThingSerializer(nested=True, required=False, allow_null=True) +# And remove 'related_thing' from Meta.fields +``` + +## 5. Update Forms + +There are typically up to four forms to update. Find them under `netbox//forms/`. + +### 5a. Filter form — `forms/filtersets.py` + +- Remove the field from `fieldsets`. +- Remove the filter field declaration (e.g. `new_field = forms.CharField(...)` or the `DynamicModelMultipleChoiceField`). + +### 5b. Bulk edit form — `forms/bulk_edit.py` + +- Remove the field from `fieldsets` and `Meta.fields` (if present). +- Remove the field declaration. +- Remove from `nullable_fields` if listed there. + +### 5c. Bulk import form — `forms/bulk_import.py` + +- Remove from `Meta.fields`. +- Remove any explicit field declaration. + +### 5d. Model form — `model_forms.py` + +- Remove from `fieldsets`. +- Remove from `Meta.fields`. +- Remove any explicit field declaration (e.g. a `DynamicModelChoiceField`). + +## 6. Update the FilterSet + +**File:** `netbox//filtersets.py` + +- **Simple field**: remove from `Meta.fields`. +- **FK field**: remove both the `` and `_id` explicit filter declarations. +- **`search()` method**: if the field was included in the `Q(...)` chain, remove that clause. +- Remove any now-unused imports (e.g. the related model import if it was only used by this filter). + +## 7. Update the Table + +**File:** `netbox//tables/.py` + +- Remove the column declaration (e.g. `related_thing = tables.Column(linkify=True)`). +- Remove the field from `Meta.fields`. +- Remove from `default_columns` if listed there. + +## 8. Update the Detail View Panel + +**File:** `netbox//ui/panels.py` + +Find the panel class for the model and remove the attribute declaration: + +```python +# Remove: +new_field = attrs.TextAttr('new_field') +related_thing = attrs.RelatedObjectAttr('related_thing', linkify=True) +``` + +If the model uses a legacy HTML template (`netbox/templates//`) rather than a declarative panel, remove the corresponding `` row from that template instead. + +## 9. Update the SearchIndex + +**File:** `netbox//search.py` + +If the field was indexed for global search, remove it from the `fields` tuple: + +```python +# Remove: +('new_field', 300), +``` + +## 10. Remove the Field from the Model + +**File:** `netbox//models/.py` + +1. Delete the field declaration. +2. If the field was in `clone_fields`, remove it from that tuple. +3. If `clean()` had validation logic specific to this field, remove those clauses. If `clean()` becomes empty, remove the override entirely. +4. For FK fields: remove the `related_name` on the target model is automatic (Django handles it). If the FK was the only reason a related model was imported, remove that import too. +5. For GenericForeignKey fields: if this was the only GFK, also remove the `object_type` ContentType FK and `object_id` integer field, and remove the `models.Index(fields=('object_type', 'object_id'))` from `Meta`. + +## 11. Generate the Migration + +**Do NOT write migrations manually.** Tell the user to run: + +```bash +cd netbox/ +python manage.py makemigrations -n remove__from_ --no-header +``` + +Set `DEVELOPER = True` in `configuration.py` if the command is blocked. + +Review the generated migration — it should contain only a `RemoveField` operation (plus any index removal for GFK fields). Apply with: + +```bash +python manage.py migrate +``` + +## Summary Checklist + +| # | File(s) | Action | +|---|---|---| +| 1 | `tests/test_*.py` | Remove field from test data, filter tests, API tests, view tests | +| 2 | `docs/models//.md` | Remove field from `## Fields` section | +| 3 | `graphql/filters.py`, `types.py` | Remove filter field; remove FK annotation if explicit | +| 4 | `api/serializers_/.py` | Remove from `Meta.fields`; remove FK serializer field | +| 5a | `forms/filtersets.py` | Remove from `fieldsets`; remove filter field declaration | +| 5b | `forms/bulk_edit.py` | Remove from `fieldsets`, `Meta.fields`, `nullable_fields` | +| 5c | `forms/bulk_import.py` | Remove from `Meta.fields` and field declaration | +| 5d | `forms/model_forms.py` | Remove from `fieldsets`, `Meta.fields`, and field declaration | +| 6 | `filtersets.py` | Remove from `Meta.fields`; remove FK + FK_id pair; update `search()` | +| 7 | `tables/.py` | Remove column declaration and from `Meta.fields`, `default_columns` | +| 8 | `/ui/panels.py` | Remove attr declaration from panel class | +| 9 | `search.py` | Remove from SearchIndex `fields` tuple | +| 10 | `models/.py` | Remove field; clean up `clone_fields`, `clean()`, imports | +| 11 | (user runs) | `makemigrations -n remove__from_ --no-header` then `migrate` | + +## Common Gotchas + +- **Work outside-in** — remove tests, docs, GraphQL, and API references before touching the model, to avoid import errors during the process. +- **FK fields leave no `_id` companion in serializers** — the modern pattern uses a single `field = Serializer(nested=True)`. Grep for the field name and the serializer class name. +- **FilterSets have both `` and `_id`** — both must be removed; they are explicit declarations, not auto-generated. +- **`clone_fields`** must be updated if the field was listed there. +- **`search()` in filtersets** — if the field was in the `Q(...)` chain of the `search()` method, that clause must be removed to avoid a `FieldError` at runtime. +- **`brief_fields` in serializers** — remove explicitly if the field was listed. +- **`makemigrations` must be run**, not written manually. If blocked, set `DEVELOPER = True` in `configuration.py`. +- **No `ruff format`** on existing files — use `ruff check` only. + +## References + +- Panel attrs reference: `netbox/netbox/ui/attrs.py` +- Panel classes: `netbox//ui/panels.py` +- Base filterset classes: `netbox/netbox/filtersets.py` +- `add-model-field` skill: `.claude/skills/add-model-field/SKILL.md` (reverse of this skill) +- Contributing guide: `docs/development/extending-models.md` diff --git a/.claude/skills/remove-model/SKILL.md b/.claude/skills/remove-model/SKILL.md new file mode 100644 index 000000000..a86d6e068 --- /dev/null +++ b/.claude/skills/remove-model/SKILL.md @@ -0,0 +1,194 @@ +--- +name: remove-model +description: Step-by-step guide for removing an existing model from NetBox, covering all required touch points in safe deletion order (tests, docs, nav, search, GraphQL, API, views, URLs, forms, filterset, table, choices, model, migration). Use when the user asks to remove, delete, or deprecate a model or object type from NetBox. +--- + +# Removing a Model from NetBox + +Removing a model requires undoing ~13 components. Work in the order below — remove consumers before providers to avoid import errors during the process. Deleting a model is **irreversible once migrated**; confirm with the user before running `makemigrations`. + +## 0. Before You Start + +Identify: +- **Model name** and **app** — e.g. `MyModel` in `dcim` +- **All references** — run a broad grep before touching anything: + +```bash +grep -r 'MyModel\|mymodel\|my-model\|my_model' netbox/ --include='*.py' -l +grep -r 'MyModel\|mymodel\|my-model\|my_model' docs/ -l +grep -r 'mymodel\|my-model' netbox/netbox/navigation/ --include='*.py' +``` + +Check for: +- Other models with ForeignKey / M2M pointing to this model (they need updating or their own removal first) +- Generic relations via `FeatureQuery` or `ContentType` that reference this model +- Any plugin or external code documented as depending on this model + +**Do not proceed if other retained models have non-nullable FKs to this model** — those FK fields must be removed or made nullable first. + +## 1. Remove Tests + +Delete test methods or entire test classes that exist solely for this model. If the test file contains only this model's tests, delete the file; otherwise remove just the relevant class(es). + +Files to check: +- `netbox//tests/test_api.py` +- `netbox//tests/test_views.py` +- `netbox//tests/test_filtersets.py` +- `netbox//tests/test_models.py` +- `netbox//tests/test_forms.py` +- `netbox//tests/test_tables.py` +- Any app-specific test modules (e.g. `test_cablepaths.py`) + +## 2. Remove Documentation + +1. Delete `docs/models//.md`. +2. Remove the `mkdocs.yml` entry under the relevant `nav:` group. +3. Remove the entry from `docs/development/models.md` (the "Models Index" list). + +## 3. Remove Navigation Menu Entry + +**File:** `netbox/netbox/navigation/menu.py` + +Remove the `get_model_item('', 'mymodel', ...)` line from the relevant `MenuGroup`. + +## 4. Remove from Search Index + +**File:** `netbox//search.py` + +Delete the `@register_search` class for the model. If the file becomes empty (no other indexes), delete the file itself. + +## 5. Remove GraphQL + +Remove in this order (schema depends on types, types depend on filters): + +1. **`netbox//graphql/schema.py`** — remove the `my_model` and `my_model_list` fields from the app's `Query` type. +2. **`netbox//graphql/types.py`** — remove the `MyModelType` class and its `__all__` entry. +3. **`netbox//graphql/filters.py`** — remove the `MyModelFilter` class and its `__all__` entry. + +If any remaining type in `types.py` has a lazy annotation referencing `MyModelType`, remove that annotation too. + +## 6. Remove REST API + +1. **`netbox//api/urls.py`** — remove the `router.register('my-models', ...)` line. +2. **`netbox//api/views.py`** — remove the `MyModelViewSet` class. +3. **`netbox//api/serializers_/.py`** — remove the serializer class. If this was the only serializer in the module, delete the file and remove its `from . import *` line from `serializers_/__init__.py`. + +Also check other serializers that reference this model (e.g. `MyModelSerializer(nested=True)` on related serializers) and remove those fields too. + +## 7. Remove URL Routes + +**File:** `netbox//urls.py` + +Remove the two `path(...)` entries that call `get_model_urls('', 'mymodel', ...)`. + +## 8. Remove Views + +**File:** `netbox//views.py` + +Remove all view classes decorated with `@register_model_view(MyModel, ...)`. There are typically seven: + +- `MyModelListView` +- `MyModelView` +- `MyModelEditView` +- `MyModelDeleteView` +- `MyModelBulkImportView` +- `MyModelBulkEditView` +- `MyModelBulkDeleteView` +- `MyModelBulkRenameView` (if present) + +Also remove the panel class from `netbox//ui/panels.py` and any `layout` references using it. + +If there is a model-specific HTML template (`netbox/templates//mymodel.html` or similar), delete it. + +## 9. Remove Table + +**File:** `netbox//tables/.py` + +Remove the `MyModelTable` class. If it is the sole table in the module, delete the file and clean up the `__init__.py` re-export. + +**File:** `netbox//tables/__init__.py` + +Remove the corresponding `from . import *` or named import. + +## 10. Remove Forms + +Remove in dependency order (bulk forms depend on the model form): + +1. **`netbox//forms/bulk_import.py`** — remove `MyModelImportForm`. +2. **`netbox//forms/bulk_edit.py`** — remove `MyModelBulkEditForm`. +3. **`netbox//forms/filtersets.py`** — remove `MyModelFilterForm`. +4. **`netbox//forms/model_forms.py`** — remove `MyModelForm`. +5. **`netbox//forms/__init__.py`** — remove all re-exports of the deleted form classes. + +## 11. Remove FilterSet + +**File:** `netbox//filtersets.py` + +Remove the `MyModelFilterSet` class. Also remove any imports of `MyModel` or related models that were only used by this filterset. + +## 12. Remove Choices + +**File:** `netbox//choices.py` + +Remove any `ChoiceSet` subclasses that were defined exclusively for this model (e.g. `MyModelStatusChoices`). Leave choices that are shared with other models. + +## 13. Remove the Model + +**File:** `netbox//models/.py` (or `models.py`) + +1. Delete the `MyModel` class. +2. Remove `'MyModel'` from `__all__` in the module. +3. Remove the import line in `netbox//models/__init__.py` if this was the last model in the submodule (or remove just the `MyModel` name from a `from . import ...` line). +4. Remove any now-unused imports in the model file itself. + +## 14. Generate the Migration + +**Do NOT write migrations manually.** Tell the user to run: + +```bash +cd netbox/ +python manage.py makemigrations -n remove_mymodel --no-header +``` + +Set `DEVELOPER = True` in `configuration.py` if the command is blocked. + +Review the generated migration before applying — it should only contain a `DeleteModel` operation (plus any `RemoveField` operations for FKs on other models if Django detected them). Apply with: + +```bash +python manage.py migrate +``` + +## Common Gotchas + +- **Remove consumers before providers** — tests, docs, GraphQL schema, API viewset, URL routes, and views all reference the model; remove them before removing the model itself to avoid import errors. +- **FK cleanup** — Django will detect FKs pointing at the deleted model and auto-add `RemoveField` operations to the migration. Verify the migration is correct before running it. +- **ContentType cleanup** — after migrating, `ContentType` rows for the old model linger in the database. They are harmless but can be cleaned up with `python manage.py remove_stale_contenttypes`. +- **`__all__` entries** — grep all `__init__.py` files for the model name after removing the class; dangling re-exports cause `ImportError` at startup. +- **Serializer references** — other serializers may have a nested `MyModelSerializer(nested=True)` field. Search for the serializer class name as well as the model name. +- **`manage.py` lives in `netbox/`**, not the repo root. +- **No `ruff format`** on existing files — use `ruff check` only. + +## Summary Checklist + +| # | File(s) | Action | +|---|---|---| +| 1 | `tests/test_*.py` | Remove test classes for this model | +| 2 | `docs/models//.md`, `mkdocs.yml`, `docs/development/models.md` | Delete doc page; remove nav entries | +| 3 | `netbox/netbox/navigation/menu.py` | Remove `get_model_item(...)` line | +| 4 | `/search.py` | Remove `SearchIndex` class | +| 5 | `/graphql/schema.py`, `types.py`, `filters.py` | Remove query fields, type, filter | +| 6 | `/api/urls.py`, `views.py`, `serializers_/.py` | Remove router entry, viewset, serializer | +| 7 | `/urls.py` | Remove `get_model_urls(...)` paths | +| 8 | `/views.py`, `/ui/panels.py` | Remove all view classes and panel | +| 9 | `/tables/.py`, `tables/__init__.py` | Remove table class and re-export | +| 10 | `/forms/*.py`, `forms/__init__.py` | Remove all four form classes and re-exports | +| 11 | `/filtersets.py` | Remove `FilterSet` class | +| 12 | `/choices.py` | Remove model-specific `ChoiceSet` subclasses | +| 13 | `/models/.py`, `models/__init__.py` | Remove model class and `__all__` entry | +| 14 | (user runs) | `makemigrations -n remove_mymodel --no-header` then `migrate` | + +## References + +- Model base classes: `netbox/netbox/models/__init__.py` +- Navigation menu: `netbox/netbox/navigation/menu.py` +- `add-model` skill: `.claude/skills/add-model/SKILL.md` (reverse of this skill) From 9db8c207a2f1fb000d93cbb531c17ed85d2be7f2 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 13:39:05 -0400 Subject: [PATCH 016/131] Add Claude skills to add and removing config parameters --- .claude/skills/add-config-param/SKILL.md | 217 ++++++++++++++++++++ .claude/skills/remove-config-param/SKILL.md | 168 +++++++++++++++ 2 files changed, 385 insertions(+) create mode 100644 .claude/skills/add-config-param/SKILL.md create mode 100644 .claude/skills/remove-config-param/SKILL.md diff --git a/.claude/skills/add-config-param/SKILL.md b/.claude/skills/add-config-param/SKILL.md new file mode 100644 index 000000000..429705cb9 --- /dev/null +++ b/.claude/skills/add-config-param/SKILL.md @@ -0,0 +1,217 @@ +--- +name: add-config-param +description: Step-by-step guide for adding a new configuration parameter to NetBox, covering both static parameters (settings.py) and dynamic parameters (database-backed, editable via the admin UI). Use when the user asks to add a new configuration option, setting, or parameter to NetBox. +--- + +# Adding a Configuration Parameter to NetBox + +NetBox has two distinct kinds of configuration parameters. Choose the right one before writing any code: + +| Type | Where defined | Changed by | Takes effect | +|---|---|---|---| +| **Static** | `settings.py` via `getattr(configuration, ...)` | Editing `configuration.py` + restart | On WSGI restart | +| **Dynamic** | `config/parameters.py` `PARAMS` tuple | Admin UI or `configuration.py` | Immediately (cached in Redis) | + +**Use dynamic** when: +- Operators need to tune the value without a service restart +- The parameter controls UI behavior or defaults (banners, page sizes, default values) +- Examples: `PAGINATE_COUNT`, `MAINTENANCE_MODE`, `BANNER_TOP` + +**Use static** when: +- The value must not change at runtime (auth backends, database config, secret keys) +- The value controls infrastructure that requires a restart anyway +- Examples: `ALLOWED_HOSTS`, `REMOTE_AUTH_BACKEND`, `LOGGING` + +--- + +## Adding a Dynamic Configuration Parameter + +Dynamic parameters are defined in `netbox/netbox/config/parameters.py`, stored in the `ConfigRevision.data` JSONField, cached in Redis, and editable via Admin > System > Configuration History. + +### Step 1 — Add to `PARAMS` + +**File:** `netbox/netbox/config/parameters.py` + +Add a `ConfigParam` entry to the `PARAMS` tuple, grouped logically with related parameters: + +```python +ConfigParam( + name='MY_PARAM', + label=_('My param'), + default=, + description=_("One-sentence description of what this controls"), + field=forms.BooleanField, # or IntegerField, CharField, JSONField, SimpleArrayField + # field_kwargs only when extra widget/validation config is needed: + field_kwargs={ + 'widget': forms.Textarea(attrs={'class': 'vLargeTextField'}), + }, +), +``` + +**Common `field` choices:** + +| Field | Use for | +|---|---| +| `forms.CharField` (default) | Short strings | +| `forms.BooleanField` | On/off toggles | +| `forms.IntegerField` | Counts, sizes, timeouts | +| `forms.JSONField` | Dicts/lists with free-form structure | +| `SimpleArrayField` | Lists of strings (add `field_kwargs={'base_field': forms.CharField()}`) | + +The `default` value is returned whenever no `ConfigRevision` row exists and the parameter is not hard-coded in `configuration.py`. + +### Step 2 — Use the parameter in code + +Access via `get_config()` (request-scoped, cached) or the `ConfigItem` callable (deferred): + +```python +from netbox.config import get_config + +# One-time read: +value = get_config().MY_PARAM + +# Deferred (evaluated later): +from netbox.config import ConfigItem +MY_PARAM = ConfigItem('MY_PARAM') +``` + +`get_config()` returns the `Config` object which tries: +1. Hard-coded value in Django `settings` (set by `configuration.py`) +2. Redis-cached active `ConfigRevision` +3. `ConfigParam.default` + +### Step 3 — Document in the configuration docs + +Add a section to the appropriate file under `docs/configuration/`: + +| File | Category | +|---|---| +| `miscellaneous.md` | General / doesn't fit elsewhere | +| `default-values.md` | Default values for object fields | +| `security.md` | Auth, permissions, URL validation | +| `data-validation.md` | `CUSTOM_VALIDATORS`, `PROTECTION_RULES` | +| `graphql-api.md` | GraphQL settings | +| `error-reporting.md` | Sentry, logging | +| `remote-authentication.md` | Remote auth settings | +| `development.md` | Developer-only flags | +| `system.md` | Low-level system settings | + +Template for a dynamic parameter doc section: + +```markdown +## MY_PARAM + +!!! tip "Dynamic Configuration Parameter" + +Default: `` + +One or two sentences describing what the parameter does, what values are accepted, +and any side effects. +``` + +### Step 4 — Register in the dynamic params index + +**File:** `docs/configuration/index.md` + +Add the new parameter to the bulleted list under "Dynamic Configuration Parameters", keeping the list alphabetically ordered: + +```markdown +* [`MY_PARAM`](./miscellaneous.md#my_param) +``` + +### Step 5 — Optionally add to the example config + +If the parameter is important enough that operators should know they can hard-code it, add a commented entry to `netbox/netbox/configuration_example.py`: + +```python +# MY_PARAM = +``` + +Place it near related parameters. + +### No migration needed + +Dynamic parameters are stored in the `ConfigRevision.data` JSONField, which already exists. No database migration is required when adding a new `ConfigParam`. + +--- + +## Adding a Static Configuration Parameter + +Static parameters live in `settings.py` and are read at startup from `configuration.py`. They take effect only after the WSGI service is restarted. + +### Step 1 — Add to `settings.py` + +**File:** `netbox/netbox/settings.py` + +Add a line in the "Set static config parameters" block, alphabetically within its logical group: + +```python +MY_PARAM = getattr(configuration, 'MY_PARAM', ) +``` + +For required parameters (no default), use `getattr(configuration, 'MY_PARAM')` with no fallback and add the parameter name to the required check near the top: + +```python +for parameter in ('ALLOWED_HOSTS', 'MY_PARAM', 'SECRET_KEY', 'REDIS'): + if not hasattr(configuration, parameter): + raise ImproperlyConfigured(f"Required parameter {parameter} is missing from configuration.") +``` + +### Step 2 — Add validation (if needed) + +If the parameter has constrained values, add an `ImproperlyConfigured` check immediately after the `getattr` line: + +```python +MY_PARAM = getattr(configuration, 'MY_PARAM', 'option_a') +if MY_PARAM not in ('option_a', 'option_b'): + raise ImproperlyConfigured(f"MY_PARAM must be 'option_a' or 'option_b' (found {MY_PARAM})") +``` + +For complex validation (importable paths, valid URLs, etc.) follow the patterns of `PROXY_ROUTERS` or `RELEASE_CHECK_URL` in `settings.py`. + +### Step 3 — Add to the example config + +**File:** `netbox/netbox/configuration_example.py` + +Add a commented entry with a brief inline comment explaining the parameter: + +```python +# MY_PARAM = 'default_value' # Short description of what this does +``` + +### Step 4 — Document + +Add a section to the appropriate `docs/configuration/*.md` file: + +```markdown +## MY_PARAM + +Default: `` + +One or two sentences describing the parameter, accepted values, and any constraints. + +--- +``` + +Static parameters do **not** get the `!!! tip "Dynamic Configuration Parameter"` admonition. + +--- + +## Common Gotchas + +- **Dynamic params don't need a migration** — the value is stored in the `ConfigRevision.data` JSONField which already exists. +- **Hard-coding a dynamic param in `configuration.py` overrides the UI** — the loop at the bottom of `settings.py` (`for param in CONFIG_PARAMS: ...`) sets the Django setting, which `Config.__getattr__` checks first. Document this behaviour in the parameter's doc page. +- **`forms.BooleanField` with `required=False`**: the `ConfigFormMetaclass` always adds `required=False`, so a `BooleanField` correctly represents a three-state (True / False / unset-use-default) UI. No extra `field_kwargs` needed for booleans. +- **`SimpleArrayField` needs `base_field`**: always pass `field_kwargs={'base_field': forms.CharField()}`. +- **No `ruff format`** on existing files — use `ruff check` only. + +## References + +- Dynamic param definitions: `netbox/netbox/config/parameters.py` +- Config loading / `Config` class: `netbox/netbox/config/__init__.py` +- `ConfigRevision` model: `netbox/core/models/config.py` +- `ConfigRevisionForm` (metaclass): `netbox/core/forms/model_forms.py` +- Static config loading: `netbox/netbox/settings.py` lines 67–213 +- Example config: `netbox/netbox/configuration_example.py` +- Config tests: `netbox/netbox/tests/test_config.py` +- Documentation: `docs/configuration/` diff --git a/.claude/skills/remove-config-param/SKILL.md b/.claude/skills/remove-config-param/SKILL.md new file mode 100644 index 000000000..8822aa58e --- /dev/null +++ b/.claude/skills/remove-config-param/SKILL.md @@ -0,0 +1,168 @@ +--- +name: remove-config-param +description: Step-by-step guide for removing a configuration parameter from NetBox, covering both static parameters (settings.py) and dynamic parameters (database-backed). Use when the user asks to remove, delete, or deprecate a configuration option or setting. +--- + +# Removing a Configuration Parameter from NetBox + +Before touching any files, determine which type of parameter you are removing: + +| Type | Where defined | How to tell | +|---|---|---| +| **Static** | `settings.py` via `getattr(configuration, ...)` | Appears in `settings.py`; not in `config/parameters.py` `PARAMS` | +| **Dynamic** | `config/parameters.py` `PARAMS` tuple | Appears in `PARAMS`; editable via Admin > System > Configuration History | + +Run a broad grep before starting to find all usages: + +```bash +grep -r 'MY_PARAM' netbox/ --include='*.py' -l +grep -r 'MY_PARAM' docs/ -l +``` + +--- + +## Removing a Dynamic Configuration Parameter + +### Step 1 — Find all usages in code + +Before removing the parameter definition, identify every call site: + +```bash +grep -r 'MY_PARAM\|my_param' netbox/ --include='*.py' +``` + +For `get_config().MY_PARAM` and `ConfigItem('MY_PARAM')` patterns specifically: + +```bash +grep -r "get_config()\.MY_PARAM\|ConfigItem('MY_PARAM')" netbox/ --include='*.py' +``` + +Remove or replace every usage. The replacement depends on the reason for removal: +- **Parameter folded into another**: replace with the new parameter access +- **Hard-coded default**: replace `get_config().MY_PARAM` with the literal default value +- **Feature removed**: remove the surrounding code entirely + +### Step 2 — Remove from `PARAMS` + +**File:** `netbox/netbox/config/parameters.py` + +Delete the `ConfigParam(...)` block for the parameter from the `PARAMS` tuple. + +### Step 3 — Remove from the dynamic params index + +**File:** `docs/configuration/index.md` + +Remove the bullet-point entry for `MY_PARAM` from the "Dynamic Configuration Parameters" list. + +### Step 4 — Remove the documentation section + +**File:** `docs/configuration/.md` (whichever file the parameter was documented in) + +Delete the `## MY_PARAM` section and its content, including the trailing `---` separator. + +### Step 5 — Remove from the example config (if present) + +**File:** `netbox/netbox/configuration_example.py` + +If a commented `# MY_PARAM = ...` line was added when the parameter was introduced, remove it. + +### No migration needed + +Dynamic parameters are stored as keys in the `ConfigRevision.data` JSONField. Removing the `ConfigParam` definition from `PARAMS` means the UI no longer shows the field and the `Config` object no longer exposes the attribute — but old `ConfigRevision` rows in the database will silently retain the key in their JSON blob. This is harmless and requires no migration. + +--- + +## Removing a Static Configuration Parameter + +### Step 1 — Find all usages in code + +```bash +grep -r 'MY_PARAM' netbox/ --include='*.py' +``` + +Remove every reference. For Django settings accessed via `settings.MY_PARAM`, also search templates: + +```bash +grep -r 'MY_PARAM' netbox/templates/ +``` + +### Step 2 — Remove from `settings.py` + +**File:** `netbox/netbox/settings.py` + +1. Delete the `MY_PARAM = getattr(configuration, 'MY_PARAM', ...)` line. +2. If the parameter was required (listed in the required-parameter check near the top), remove it from that tuple: + ```python + # Before: + for parameter in ('ALLOWED_HOSTS', 'MY_PARAM', 'SECRET_KEY', 'REDIS'): + # After: + for parameter in ('ALLOWED_HOSTS', 'SECRET_KEY', 'REDIS'): + ``` +3. Remove any validation block that immediately followed the `getattr` line (e.g. `if MY_PARAM not in (...): raise ImproperlyConfigured(...)`). + +### Step 3 — Remove from the example config + +**File:** `netbox/netbox/configuration_example.py` + +Delete the commented `# MY_PARAM = ...` line. + +### Step 4 — Remove the documentation section + +**File:** `docs/configuration/.md` + +Delete the `## MY_PARAM` section and its content, including the trailing `---` separator. + +--- + +## Deprecation vs. Immediate Removal + +If the parameter is used by existing deployments, consider a two-phase removal: + +**Phase 1 (current release) — Deprecate:** +1. Keep the `getattr` / `ConfigParam` definition in place so existing configs don't break. +2. Add a deprecation warning comment in `settings.py` (see how `SENTRY_DSN` is handled with `# TODO: Remove in NetBox vX.Y`). +3. Log a `warnings.warn(...)` or add a startup notice if the parameter is still set. +4. Mark the doc section as deprecated. + +**Phase 2 (future release) — Remove:** +Follow the full removal steps above. + +--- + +## Common Gotchas + +- **Remove all call sites first** — if code still calls `get_config().MY_PARAM` or `settings.MY_PARAM` after the definition is gone, startup or runtime will raise `AttributeError`. +- **Old ConfigRevision rows keep the key** — this is safe; the `Config.__getattr__` lookup simply won't find a registered default and will raise `AttributeError` if code tries to access it. Remove all code references before removing the `ConfigParam`. +- **`configuration.py` in user deployments** — removing a static parameter may cause a `TypeError` or silent failure if users have `MY_PARAM = ...` in their local `configuration.py`. Document the removal in the release notes. +- **No `ruff format`** on existing files — use `ruff check` only. + +## Summary Checklist + +### Dynamic parameter + +| # | File(s) | Action | +|---|---|---| +| 1 | All `.py` files | Remove all `get_config().MY_PARAM` and `ConfigItem('MY_PARAM')` usages | +| 2 | `netbox/netbox/config/parameters.py` | Remove `ConfigParam(...)` block from `PARAMS` | +| 3 | `docs/configuration/index.md` | Remove bullet-point entry | +| 4 | `docs/configuration/.md` | Remove `## MY_PARAM` section | +| 5 | `netbox/netbox/configuration_example.py` | Remove commented entry (if present) | + +### Static parameter + +| # | File(s) | Action | +|---|---|---| +| 1 | All `.py` and template files | Remove all `settings.MY_PARAM` / `MY_PARAM` usages | +| 2 | `netbox/netbox/settings.py` | Remove `getattr` line; remove from required-params tuple; remove validation block | +| 3 | `netbox/netbox/configuration_example.py` | Remove commented entry | +| 4 | `docs/configuration/.md` | Remove `## MY_PARAM` section | + +## References + +- Dynamic param definitions: `netbox/netbox/config/parameters.py` +- Config loading / `Config` class: `netbox/netbox/config/__init__.py` +- `ConfigRevision` model: `netbox/core/models/config.py` +- Static config loading: `netbox/netbox/settings.py` lines 67–213 +- Example config: `netbox/netbox/configuration_example.py` +- Documentation: `docs/configuration/` +- `add-config-param` skill: `.claude/skills/add-config-param/SKILL.md` (reverse of this skill) From 670386ed72ee9dc1787ba12a5c8b539a9c1db8d0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 14:26:43 -0400 Subject: [PATCH 017/131] Address PR feedback --- .claude/skills/remove-config-param/SKILL.md | 2 +- .claude/skills/remove-model-field/SKILL.md | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.claude/skills/remove-config-param/SKILL.md b/.claude/skills/remove-config-param/SKILL.md index 8822aa58e..fecbc6494 100644 --- a/.claude/skills/remove-config-param/SKILL.md +++ b/.claude/skills/remove-config-param/SKILL.md @@ -132,7 +132,7 @@ Follow the full removal steps above. ## Common Gotchas - **Remove all call sites first** — if code still calls `get_config().MY_PARAM` or `settings.MY_PARAM` after the definition is gone, startup or runtime will raise `AttributeError`. -- **Old ConfigRevision rows keep the key** — this is safe; the `Config.__getattr__` lookup simply won't find a registered default and will raise `AttributeError` if code tries to access it. Remove all code references before removing the `ConfigParam`. +- **Old `ConfigRevision` rows retain the key in their JSON blob** — this is harmless and requires no migration. The risk is code: any remaining call to `get_config().MY_PARAM` or `settings.MY_PARAM` after the definition is gone will raise `AttributeError`. Remove all code references *before* removing the `ConfigParam` definition. - **`configuration.py` in user deployments** — removing a static parameter may cause a `TypeError` or silent failure if users have `MY_PARAM = ...` in their local `configuration.py`. Document the removal in the release notes. - **No `ruff format`** on existing files — use `ruff check` only. diff --git a/.claude/skills/remove-model-field/SKILL.md b/.claude/skills/remove-model-field/SKILL.md index 39629f674..1e23c1860 100644 --- a/.claude/skills/remove-model-field/SKILL.md +++ b/.claude/skills/remove-model-field/SKILL.md @@ -155,7 +155,11 @@ If the field was indexed for global search, remove it from the `fields` tuple: 2. If the field was in `clone_fields`, remove it from that tuple. 3. If `clean()` had validation logic specific to this field, remove those clauses. If `clean()` becomes empty, remove the override entirely. 4. For FK fields: remove the `related_name` on the target model is automatic (Django handles it). If the FK was the only reason a related model was imported, remove that import too. -5. For GenericForeignKey fields: if this was the only GFK, also remove the `object_type` ContentType FK and `object_id` integer field, and remove the `models.Index(fields=('object_type', 'object_id'))` from `Meta`. +5. Check `Meta` for references to the field: + - `ordering` — if the field appears in the ordering tuple, remove it (or replace with a remaining field if ordering would otherwise become empty). + - `constraints` — remove any `UniqueConstraint` or `CheckConstraint` whose `fields` list includes this field; if only this field remains, remove the constraint entirely; if other fields remain, remove just this field from the list. + - `indexes` — remove any `models.Index` that includes this field. +6. For GenericForeignKey fields: if this was the only GFK, also remove the `object_type` ContentType FK and `object_id` integer field, and remove the `models.Index(fields=('object_type', 'object_id'))` from `Meta`. ## 11. Generate the Migration @@ -190,7 +194,7 @@ python manage.py migrate | 7 | `tables/.py` | Remove column declaration and from `Meta.fields`, `default_columns` | | 8 | `/ui/panels.py` | Remove attr declaration from panel class | | 9 | `search.py` | Remove from SearchIndex `fields` tuple | -| 10 | `models/.py` | Remove field; clean up `clone_fields`, `clean()`, imports | +| 10 | `models/.py` | Remove field; clean up `clone_fields`, `clean()`, `Meta` ordering/constraints/indexes, imports | | 11 | (user runs) | `makemigrations -n remove__from_ --no-header` then `migrate` | ## Common Gotchas From c45482c4af246ef6d254cf30e81870ef5ef8a46b Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Thu, 7 May 2026 11:33:03 -0700 Subject: [PATCH 018/131] #21934 allow highlight override table stripping (#22018) --- netbox/project-static/dist/netbox.css | 2 +- .../styles/custom/_interfaces.scss | 30 +++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/netbox/project-static/dist/netbox.css b/netbox/project-static/dist/netbox.css index d4019c186..40c15ecb9 100644 --- a/netbox/project-static/dist/netbox.css +++ b/netbox/project-static/dist/netbox.css @@ -1 +1 @@ -@charset "UTF-8";:root,[data-bs-theme=light]{--tblr-black: #000000;--tblr-white: #ffffff;--tblr-gray: #4b5563;--tblr-gray-dark: #1f2937;--tblr-gray-100: #f3f4f6;--tblr-gray-200: #e5e7eb;--tblr-gray-300: #d1d5db;--tblr-gray-400: #9ca3af;--tblr-gray-500: #6b7280;--tblr-gray-600: #4b5563;--tblr-gray-700: #374151;--tblr-gray-800: #1f2937;--tblr-gray-900: #111827;--tblr-primary: #00857D;--tblr-secondary: #6b7280;--tblr-success: #2fb344;--tblr-info: #4299e1;--tblr-warning: #f59f00;--tblr-danger: #d63939;--tblr-light: #f9fafb;--tblr-dark: #1f2937;--tblr-muted: #6b7280;--tblr-blue: #066fd1;--tblr-azure: #4299e1;--tblr-indigo: #4263eb;--tblr-purple: #ae3ec9;--tblr-pink: #d6336c;--tblr-red: #d63939;--tblr-orange: #f76707;--tblr-yellow: #f59f00;--tblr-lime: #74b816;--tblr-green: #2fb344;--tblr-teal: #0ca678;--tblr-cyan: #17a2b8;--tblr-primary-rgb: 0, 133, 125;--tblr-secondary-rgb: 107, 114, 128;--tblr-success-rgb: 47, 179, 68;--tblr-info-rgb: 66, 153, 225;--tblr-warning-rgb: 245, 159, 0;--tblr-danger-rgb: 214, 57, 57;--tblr-light-rgb: 249, 250, 251;--tblr-dark-rgb: 31, 41, 55;--tblr-muted-rgb: 107, 114, 128;--tblr-blue-rgb: 6, 111, 209;--tblr-azure-rgb: 66, 153, 225;--tblr-indigo-rgb: 66, 99, 235;--tblr-purple-rgb: 174, 62, 201;--tblr-pink-rgb: 214, 51, 108;--tblr-red-rgb: 214, 57, 57;--tblr-orange-rgb: 247, 103, 7;--tblr-yellow-rgb: 245, 159, 0;--tblr-lime-rgb: 116, 184, 22;--tblr-green-rgb: 47, 179, 68;--tblr-teal-rgb: 12, 166, 120;--tblr-cyan-rgb: 23, 162, 184;--tblr-primary-text-emphasis: rgb(0, 53.2, 50);--tblr-secondary-text-emphasis: rgb(42.8, 45.6, 51.2);--tblr-success-text-emphasis: rgb(18.8, 71.6, 27.2);--tblr-info-text-emphasis: rgb(26.4, 61.2, 90);--tblr-warning-text-emphasis: rgb(98, 63.6, 0);--tblr-danger-text-emphasis: rgb(85.6, 22.8, 22.8);--tblr-light-text-emphasis: #374151;--tblr-dark-text-emphasis: #374151;--tblr-primary-bg-subtle: rgb(204, 230.6, 229);--tblr-secondary-bg-subtle: rgb(225.4, 226.8, 229.6);--tblr-success-bg-subtle: rgb(213.4, 239.8, 217.6);--tblr-info-bg-subtle: rgb(217.2, 234.6, 249);--tblr-warning-bg-subtle: rgb(253, 235.8, 204);--tblr-danger-bg-subtle: rgb(246.8, 215.4, 215.4);--tblr-light-bg-subtle: rgb(249, 249.5, 250.5);--tblr-dark-bg-subtle: #9ca3af;--tblr-primary-border-subtle: rgb(153, 206.2, 203);--tblr-secondary-border-subtle: rgb(195.8, 198.6, 204.2);--tblr-success-border-subtle: rgb(171.8, 224.6, 180.2);--tblr-info-border-subtle: rgb(179.4, 214.2, 243);--tblr-warning-border-subtle: rgb(251, 216.6, 153);--tblr-danger-border-subtle: rgb(238.6, 175.8, 175.8);--tblr-light-border-subtle: #e5e7eb;--tblr-dark-border-subtle: #6b7280;--tblr-white-rgb: 255, 255, 255;--tblr-black-rgb: 0, 0, 0;--tblr-font-sans-serif: "Inter", system-ui, sans-serif;--tblr-font-monospace: "Roboto Mono";--tblr-gradient: linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--tblr-body-font-family: var(--tblr-font-sans-serif);--tblr-body-font-size: .875rem;--tblr-body-font-weight: 400;--tblr-body-line-height: 1.4285714286;--tblr-body-color: #1f2937;--tblr-body-color-rgb: 31, 41, 55;--tblr-body-bg: #f9fafb;--tblr-body-bg-rgb: 249, 250, 251;--tblr-emphasis-color: #374151;--tblr-emphasis-color-rgb: 55, 65, 81;--tblr-secondary-color: rgba(31, 41, 55, .75);--tblr-secondary-color-rgb: 31, 41, 55;--tblr-secondary-bg: #e5e7eb;--tblr-secondary-bg-rgb: 229, 231, 235;--tblr-tertiary-color: rgba(31, 41, 55, .5);--tblr-tertiary-color-rgb: 31, 41, 55;--tblr-tertiary-bg: #f3f4f6;--tblr-tertiary-bg-rgb: 243, 244, 246;--tblr-heading-color: inherit;--tblr-link-color: #00857D;--tblr-link-color-rgb: 0, 133, 125;--tblr-link-decoration: none;--tblr-link-hover-color: rgb(0, 106.4, 100);--tblr-link-hover-color-rgb: 0, 106, 100;--tblr-link-hover-decoration: underline;--tblr-code-color: light-dark(var(--tblr-gray-600), var(--tblr-gray-400));--tblr-highlight-color: #1f2937;--tblr-highlight-bg: rgb(253, 235.8, 204);--tblr-border-width: 1px;--tblr-border-style: solid;--tblr-border-color: #e5e7eb;--tblr-border-color-translucent: rgba(4, 32, 69, .1);--tblr-border-radius: 6px;--tblr-border-radius-sm: 4px;--tblr-border-radius-lg: 8px;--tblr-border-radius-xl: 1rem;--tblr-border-radius-xxl: 2rem;--tblr-border-radius-2xl: var(--tblr-border-radius-xxl);--tblr-border-radius-pill: 100rem;--tblr-box-shadow: rgba(var(--tblr-body-color-rgb), .04) 0 2px 4px 0;--tblr-box-shadow-sm: 0 .125rem .25rem rgba(0, 0, 0, .075);--tblr-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, .175);--tblr-box-shadow-inset: 0 0 transparent;--tblr-focus-ring-width: .25rem;--tblr-focus-ring-opacity: .25;--tblr-focus-ring-color: rgba(var(--tblr-primary-rgb), .25);--tblr-form-valid-color: #2fb344;--tblr-form-valid-border-color: #2fb344;--tblr-form-invalid-color: #d63939;--tblr-form-invalid-border-color: #d63939}[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{color-scheme:dark;--tblr-body-color: #e5e7eb;--tblr-body-color-rgb: 229, 231, 235;--tblr-body-bg: #111827;--tblr-body-bg-rgb: 17, 24, 39;--tblr-emphasis-color: #ffffff;--tblr-emphasis-color-rgb: 255, 255, 255;--tblr-secondary-color: rgba(229, 231, 235, .75);--tblr-secondary-color-rgb: 229, 231, 235;--tblr-secondary-bg: #1f2937;--tblr-secondary-bg-rgb: 31, 41, 55;--tblr-tertiary-color: rgba(229, 231, 235, .5);--tblr-tertiary-color-rgb: 229, 231, 235;--tblr-tertiary-bg: rgb(24, 32.5, 47);--tblr-tertiary-bg-rgb: 24, 33, 47;--tblr-primary-text-emphasis: rgb(102, 181.8, 177);--tblr-secondary-text-emphasis: rgb(166.2, 170.4, 178.8);--tblr-success-text-emphasis: rgb(130.2, 209.4, 142.8);--tblr-info-text-emphasis: rgb(141.6, 193.8, 237);--tblr-warning-text-emphasis: rgb(249, 197.4, 102);--tblr-danger-text-emphasis: rgb(230.4, 136.2, 136.2);--tblr-light-text-emphasis: #f3f4f6;--tblr-dark-text-emphasis: #d1d5db;--tblr-primary-bg-subtle: rgb(0, 26.6, 25);--tblr-secondary-bg-subtle: rgb(21.4, 22.8, 25.6);--tblr-success-bg-subtle: rgb(9.4, 35.8, 13.6);--tblr-info-bg-subtle: rgb(13.2, 30.6, 45);--tblr-warning-bg-subtle: rgb(49, 31.8, 0);--tblr-danger-bg-subtle: rgb(42.8, 11.4, 11.4);--tblr-light-bg-subtle: #1f2937;--tblr-dark-bg-subtle: rgb(15.5, 20.5, 27.5);--tblr-primary-border-subtle: rgb(0, 79.8, 75);--tblr-secondary-border-subtle: rgb(64.2, 68.4, 76.8);--tblr-success-border-subtle: rgb(28.2, 107.4, 40.8);--tblr-info-border-subtle: rgb(39.6, 91.8, 135);--tblr-warning-border-subtle: rgb(147, 95.4, 0);--tblr-danger-border-subtle: rgb(128.4, 34.2, 34.2);--tblr-light-border-subtle: #374151;--tblr-dark-border-subtle: #1f2937;--tblr-heading-color: inherit;--tblr-link-color: rgb(102, 181.8, 177);--tblr-link-hover-color: rgb(132.6, 196.44, 192.6);--tblr-link-color-rgb: 102, 182, 177;--tblr-link-hover-color-rgb: 133, 196, 193;--tblr-code-color: var(--tblr-gray-300);--tblr-highlight-color: #e5e7eb;--tblr-highlight-bg: rgb(98, 63.6, 0);--tblr-border-color: rgb(45.7069767442, 60.4511627907, 81.0930232558);--tblr-border-color-translucent: rgba(72, 110, 149, .14);--tblr-form-valid-color: rgb(130.2, 209.4, 142.8);--tblr-form-valid-border-color: rgb(130.2, 209.4, 142.8);--tblr-form-invalid-color: rgb(230.4, 136.2, 136.2);--tblr-form-invalid-border-color: rgb(230.4, 136.2, 136.2)}*,*:before,*:after{box-sizing:border-box}@media(prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--tblr-body-font-family);font-size:var(--tblr-body-font-size);font-weight:var(--tblr-body-font-weight);line-height:var(--tblr-body-line-height);color:var(--tblr-body-color);text-align:var(--tblr-body-text-align);background-color:var(--tblr-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr,.hr{margin:2rem 0;color:inherit;border:0;border-top:var(--tblr-border-width) solid;opacity:.16}h6,.h6,h5,.h5,h4,.h4,h3,.field-group h2,.field-group .h2,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:var(--tblr-spacer);font-weight:var(--tblr-font-weight-bold);line-height:1.2;color:var(--tblr-heading-color)}h1,.h1{font-size:1.5rem}h2,.h2{font-size:1.25rem}h3,.field-group h2,.field-group .h2,.h3{font-size:1rem}h4,.h4{font-size:.875rem}h5,.h5{font-size:.75rem}h6,.h6{font-size:.625rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:600}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small,.small{font-size:.875em}mark,.mark{padding:.1875em;color:var(--tblr-highlight-color);background-color:var(--tblr-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:rgba(var(--tblr-link-color-rgb),var(--tblr-link-opacity, 1));text-decoration:none}a:hover{--tblr-link-color-rgb: var(--tblr-link-hover-color-rgb);text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--tblr-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.85714285em;color:var(--tblr-light)}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.85714285em;color:var(--tblr-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.25rem .5rem;font-size:var(--tblr-font-size-h5);color:var(--tblr-text-secondary-dark);background-color:var(--tblr-code-bg);border-radius:4px}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:var(--tblr-secondary-color);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;line-height:inherit;font-size:1.5rem}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button{cursor:pointer;filter:grayscale(1)}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:.875rem;font-weight:var(--tblr-font-weight-normal)}.display-1{font-weight:300;line-height:1.2;font-size:5rem}.display-2{font-weight:300;line-height:1.2;font-size:4.5rem}.display-3{font-weight:300;line-height:1.2;font-size:4rem}.display-4{font-weight:300;line-height:1.2;font-size:3.5rem}.display-5{font-weight:300;line-height:1.2;font-size:3rem}.display-6{font-weight:300;line-height:1.2;font-size:2rem}.list-unstyled,.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:.875rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#4b5563}.blockquote-footer:before{content:"\2014\a0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--tblr-body-bg);border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-box-shadow-sm);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--tblr-secondary-color)}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto}@media(min-width:576px){.container-sm,.container{max-width:540px}}@media(min-width:768px){.container-md,.container-sm,.container{max-width:720px}}@media(min-width:992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media(min-width:1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media(min-width:1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}:root{--tblr-breakpoint-xs: 0;--tblr-breakpoint-sm: 576px;--tblr-breakpoint-md: 768px;--tblr-breakpoint-lg: 992px;--tblr-breakpoint-xl: 1200px;--tblr-breakpoint-xxl: 1400px}.row{--tblr-gutter-x: var(--tblr-page-padding);--tblr-gutter-y: 0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--tblr-gutter-y));margin-right:calc(-.5 * var(--tblr-gutter-x));margin-left:calc(-.5 * var(--tblr-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-top:var(--tblr-gutter-y)}.grid{display:grid;grid-template-rows:repeat(var(--tblr-rows, 1),1fr);grid-template-columns:repeat(var(--tblr-columns, 12),1fr);gap:var(--tblr-gap, var(--tblr-page-padding))}.grid .g-col-1{grid-column:auto/span 1}.grid .g-col-2{grid-column:auto/span 2}.grid .g-col-3{grid-column:auto/span 3}.grid .g-col-4{grid-column:auto/span 4}.grid .g-col-5{grid-column:auto/span 5}.grid .g-col-6{grid-column:auto/span 6}.grid .g-col-7{grid-column:auto/span 7}.grid .g-col-8{grid-column:auto/span 8}.grid .g-col-9{grid-column:auto/span 9}.grid .g-col-10{grid-column:auto/span 10}.grid .g-col-11{grid-column:auto/span 11}.grid .g-col-12{grid-column:auto/span 12}.grid .g-start-1{grid-column-start:1}.grid .g-start-2{grid-column-start:2}.grid .g-start-3{grid-column-start:3}.grid .g-start-4{grid-column-start:4}.grid .g-start-5{grid-column-start:5}.grid .g-start-6{grid-column-start:6}.grid .g-start-7{grid-column-start:7}.grid .g-start-8{grid-column-start:8}.grid .g-start-9{grid-column-start:9}.grid .g-start-10{grid-column-start:10}.grid .g-start-11{grid-column-start:11}@media(min-width:576px){.grid .g-col-sm-1{grid-column:auto/span 1}.grid .g-col-sm-2{grid-column:auto/span 2}.grid .g-col-sm-3{grid-column:auto/span 3}.grid .g-col-sm-4{grid-column:auto/span 4}.grid .g-col-sm-5{grid-column:auto/span 5}.grid .g-col-sm-6{grid-column:auto/span 6}.grid .g-col-sm-7{grid-column:auto/span 7}.grid .g-col-sm-8{grid-column:auto/span 8}.grid .g-col-sm-9{grid-column:auto/span 9}.grid .g-col-sm-10{grid-column:auto/span 10}.grid .g-col-sm-11{grid-column:auto/span 11}.grid .g-col-sm-12{grid-column:auto/span 12}.grid .g-start-sm-1{grid-column-start:1}.grid .g-start-sm-2{grid-column-start:2}.grid .g-start-sm-3{grid-column-start:3}.grid .g-start-sm-4{grid-column-start:4}.grid .g-start-sm-5{grid-column-start:5}.grid .g-start-sm-6{grid-column-start:6}.grid .g-start-sm-7{grid-column-start:7}.grid .g-start-sm-8{grid-column-start:8}.grid .g-start-sm-9{grid-column-start:9}.grid .g-start-sm-10{grid-column-start:10}.grid .g-start-sm-11{grid-column-start:11}}@media(min-width:768px){.grid .g-col-md-1{grid-column:auto/span 1}.grid .g-col-md-2{grid-column:auto/span 2}.grid .g-col-md-3{grid-column:auto/span 3}.grid .g-col-md-4{grid-column:auto/span 4}.grid .g-col-md-5{grid-column:auto/span 5}.grid .g-col-md-6{grid-column:auto/span 6}.grid .g-col-md-7{grid-column:auto/span 7}.grid .g-col-md-8{grid-column:auto/span 8}.grid .g-col-md-9{grid-column:auto/span 9}.grid .g-col-md-10{grid-column:auto/span 10}.grid .g-col-md-11{grid-column:auto/span 11}.grid .g-col-md-12{grid-column:auto/span 12}.grid .g-start-md-1{grid-column-start:1}.grid .g-start-md-2{grid-column-start:2}.grid .g-start-md-3{grid-column-start:3}.grid .g-start-md-4{grid-column-start:4}.grid .g-start-md-5{grid-column-start:5}.grid .g-start-md-6{grid-column-start:6}.grid .g-start-md-7{grid-column-start:7}.grid .g-start-md-8{grid-column-start:8}.grid .g-start-md-9{grid-column-start:9}.grid .g-start-md-10{grid-column-start:10}.grid .g-start-md-11{grid-column-start:11}}@media(min-width:992px){.grid .g-col-lg-1{grid-column:auto/span 1}.grid .g-col-lg-2{grid-column:auto/span 2}.grid .g-col-lg-3{grid-column:auto/span 3}.grid .g-col-lg-4{grid-column:auto/span 4}.grid .g-col-lg-5{grid-column:auto/span 5}.grid .g-col-lg-6{grid-column:auto/span 6}.grid .g-col-lg-7{grid-column:auto/span 7}.grid .g-col-lg-8{grid-column:auto/span 8}.grid .g-col-lg-9{grid-column:auto/span 9}.grid .g-col-lg-10{grid-column:auto/span 10}.grid .g-col-lg-11{grid-column:auto/span 11}.grid .g-col-lg-12{grid-column:auto/span 12}.grid .g-start-lg-1{grid-column-start:1}.grid .g-start-lg-2{grid-column-start:2}.grid .g-start-lg-3{grid-column-start:3}.grid .g-start-lg-4{grid-column-start:4}.grid .g-start-lg-5{grid-column-start:5}.grid .g-start-lg-6{grid-column-start:6}.grid .g-start-lg-7{grid-column-start:7}.grid .g-start-lg-8{grid-column-start:8}.grid .g-start-lg-9{grid-column-start:9}.grid .g-start-lg-10{grid-column-start:10}.grid .g-start-lg-11{grid-column-start:11}}@media(min-width:1200px){.grid .g-col-xl-1{grid-column:auto/span 1}.grid .g-col-xl-2{grid-column:auto/span 2}.grid .g-col-xl-3{grid-column:auto/span 3}.grid .g-col-xl-4{grid-column:auto/span 4}.grid .g-col-xl-5{grid-column:auto/span 5}.grid .g-col-xl-6{grid-column:auto/span 6}.grid .g-col-xl-7{grid-column:auto/span 7}.grid .g-col-xl-8{grid-column:auto/span 8}.grid .g-col-xl-9{grid-column:auto/span 9}.grid .g-col-xl-10{grid-column:auto/span 10}.grid .g-col-xl-11{grid-column:auto/span 11}.grid .g-col-xl-12{grid-column:auto/span 12}.grid .g-start-xl-1{grid-column-start:1}.grid .g-start-xl-2{grid-column-start:2}.grid .g-start-xl-3{grid-column-start:3}.grid .g-start-xl-4{grid-column-start:4}.grid .g-start-xl-5{grid-column-start:5}.grid .g-start-xl-6{grid-column-start:6}.grid .g-start-xl-7{grid-column-start:7}.grid .g-start-xl-8{grid-column-start:8}.grid .g-start-xl-9{grid-column-start:9}.grid .g-start-xl-10{grid-column-start:10}.grid .g-start-xl-11{grid-column-start:11}}@media(min-width:1400px){.grid .g-col-xxl-1{grid-column:auto/span 1}.grid .g-col-xxl-2{grid-column:auto/span 2}.grid .g-col-xxl-3{grid-column:auto/span 3}.grid .g-col-xxl-4{grid-column:auto/span 4}.grid .g-col-xxl-5{grid-column:auto/span 5}.grid .g-col-xxl-6{grid-column:auto/span 6}.grid .g-col-xxl-7{grid-column:auto/span 7}.grid .g-col-xxl-8{grid-column:auto/span 8}.grid .g-col-xxl-9{grid-column:auto/span 9}.grid .g-col-xxl-10{grid-column:auto/span 10}.grid .g-col-xxl-11{grid-column:auto/span 11}.grid .g-col-xxl-12{grid-column:auto/span 12}.grid .g-start-xxl-1{grid-column-start:1}.grid .g-start-xxl-2{grid-column-start:2}.grid .g-start-xxl-3{grid-column-start:3}.grid .g-start-xxl-4{grid-column-start:4}.grid .g-start-xxl-5{grid-column-start:5}.grid .g-start-xxl-6{grid-column-start:6}.grid .g-start-xxl-7{grid-column-start:7}.grid .g-start-xxl-8{grid-column-start:8}.grid .g-start-xxl-9{grid-column-start:9}.grid .g-start-xxl-10{grid-column-start:10}.grid .g-start-xxl-11{grid-column-start:11}}.col{flex:1 0 0}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.66666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--tblr-gutter-x: 0}.g-0,.gy-0{--tblr-gutter-y: 0}.g-1,.gx-1{--tblr-gutter-x: .25rem}.g-1,.gy-1{--tblr-gutter-y: .25rem}.g-2,.gx-2{--tblr-gutter-x: .5rem}.g-2,.gy-2{--tblr-gutter-y: .5rem}.g-3,.gx-3{--tblr-gutter-x: 1rem}.g-3,.gy-3{--tblr-gutter-y: 1rem}.g-4,.gx-4{--tblr-gutter-x: 1.5rem}.g-4,.gy-4{--tblr-gutter-y: 1.5rem}.g-5,.gx-5{--tblr-gutter-x: 2rem}.g-5,.gy-5{--tblr-gutter-y: 2rem}.g-6,.gx-6{--tblr-gutter-x: 2.5rem}.g-6,.gy-6{--tblr-gutter-y: 2.5rem}@media(min-width:576px){.col-sm{flex:1 0 0}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.66666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--tblr-gutter-x: 0}.g-sm-0,.gy-sm-0{--tblr-gutter-y: 0}.g-sm-1,.gx-sm-1{--tblr-gutter-x: .25rem}.g-sm-1,.gy-sm-1{--tblr-gutter-y: .25rem}.g-sm-2,.gx-sm-2{--tblr-gutter-x: .5rem}.g-sm-2,.gy-sm-2{--tblr-gutter-y: .5rem}.g-sm-3,.gx-sm-3{--tblr-gutter-x: 1rem}.g-sm-3,.gy-sm-3{--tblr-gutter-y: 1rem}.g-sm-4,.gx-sm-4{--tblr-gutter-x: 1.5rem}.g-sm-4,.gy-sm-4{--tblr-gutter-y: 1.5rem}.g-sm-5,.gx-sm-5{--tblr-gutter-x: 2rem}.g-sm-5,.gy-sm-5{--tblr-gutter-y: 2rem}.g-sm-6,.gx-sm-6{--tblr-gutter-x: 2.5rem}.g-sm-6,.gy-sm-6{--tblr-gutter-y: 2.5rem}}@media(min-width:768px){.col-md{flex:1 0 0}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.66666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--tblr-gutter-x: 0}.g-md-0,.gy-md-0{--tblr-gutter-y: 0}.g-md-1,.gx-md-1{--tblr-gutter-x: .25rem}.g-md-1,.gy-md-1{--tblr-gutter-y: .25rem}.g-md-2,.gx-md-2{--tblr-gutter-x: .5rem}.g-md-2,.gy-md-2{--tblr-gutter-y: .5rem}.g-md-3,.gx-md-3{--tblr-gutter-x: 1rem}.g-md-3,.gy-md-3{--tblr-gutter-y: 1rem}.g-md-4,.gx-md-4{--tblr-gutter-x: 1.5rem}.g-md-4,.gy-md-4{--tblr-gutter-y: 1.5rem}.g-md-5,.gx-md-5{--tblr-gutter-x: 2rem}.g-md-5,.gy-md-5{--tblr-gutter-y: 2rem}.g-md-6,.gx-md-6{--tblr-gutter-x: 2.5rem}.g-md-6,.gy-md-6{--tblr-gutter-y: 2.5rem}}@media(min-width:992px){.col-lg{flex:1 0 0}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.66666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--tblr-gutter-x: 0}.g-lg-0,.gy-lg-0{--tblr-gutter-y: 0}.g-lg-1,.gx-lg-1{--tblr-gutter-x: .25rem}.g-lg-1,.gy-lg-1{--tblr-gutter-y: .25rem}.g-lg-2,.gx-lg-2{--tblr-gutter-x: .5rem}.g-lg-2,.gy-lg-2{--tblr-gutter-y: .5rem}.g-lg-3,.gx-lg-3{--tblr-gutter-x: 1rem}.g-lg-3,.gy-lg-3{--tblr-gutter-y: 1rem}.g-lg-4,.gx-lg-4{--tblr-gutter-x: 1.5rem}.g-lg-4,.gy-lg-4{--tblr-gutter-y: 1.5rem}.g-lg-5,.gx-lg-5{--tblr-gutter-x: 2rem}.g-lg-5,.gy-lg-5{--tblr-gutter-y: 2rem}.g-lg-6,.gx-lg-6{--tblr-gutter-x: 2.5rem}.g-lg-6,.gy-lg-6{--tblr-gutter-y: 2.5rem}}@media(min-width:1200px){.col-xl{flex:1 0 0}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.66666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--tblr-gutter-x: 0}.g-xl-0,.gy-xl-0{--tblr-gutter-y: 0}.g-xl-1,.gx-xl-1{--tblr-gutter-x: .25rem}.g-xl-1,.gy-xl-1{--tblr-gutter-y: .25rem}.g-xl-2,.gx-xl-2{--tblr-gutter-x: .5rem}.g-xl-2,.gy-xl-2{--tblr-gutter-y: .5rem}.g-xl-3,.gx-xl-3{--tblr-gutter-x: 1rem}.g-xl-3,.gy-xl-3{--tblr-gutter-y: 1rem}.g-xl-4,.gx-xl-4{--tblr-gutter-x: 1.5rem}.g-xl-4,.gy-xl-4{--tblr-gutter-y: 1.5rem}.g-xl-5,.gx-xl-5{--tblr-gutter-x: 2rem}.g-xl-5,.gy-xl-5{--tblr-gutter-y: 2rem}.g-xl-6,.gx-xl-6{--tblr-gutter-x: 2.5rem}.g-xl-6,.gy-xl-6{--tblr-gutter-y: 2.5rem}}@media(min-width:1400px){.col-xxl{flex:1 0 0}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.66666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--tblr-gutter-x: 0}.g-xxl-0,.gy-xxl-0{--tblr-gutter-y: 0}.g-xxl-1,.gx-xxl-1{--tblr-gutter-x: .25rem}.g-xxl-1,.gy-xxl-1{--tblr-gutter-y: .25rem}.g-xxl-2,.gx-xxl-2{--tblr-gutter-x: .5rem}.g-xxl-2,.gy-xxl-2{--tblr-gutter-y: .5rem}.g-xxl-3,.gx-xxl-3{--tblr-gutter-x: 1rem}.g-xxl-3,.gy-xxl-3{--tblr-gutter-y: 1rem}.g-xxl-4,.gx-xxl-4{--tblr-gutter-x: 1.5rem}.g-xxl-4,.gy-xxl-4{--tblr-gutter-y: 1.5rem}.g-xxl-5,.gx-xxl-5{--tblr-gutter-x: 2rem}.g-xxl-5,.gy-xxl-5{--tblr-gutter-y: 2rem}.g-xxl-6,.gx-xxl-6{--tblr-gutter-x: 2.5rem}.g-xxl-6,.gy-xxl-6{--tblr-gutter-y: 2.5rem}}.table,.markdown>table{--tblr-table-color-type: initial;--tblr-table-bg-type: initial;--tblr-table-color-state: initial;--tblr-table-bg-state: initial;--tblr-table-color: inherit;--tblr-table-bg: transparent;--tblr-table-border-color: var(--tblr-border-color-translucent);--tblr-table-accent-bg: transparent;--tblr-table-striped-color: inherit;--tblr-table-striped-bg: var(--tblr-bg-surface-tertiary);--tblr-table-active-color: inherit;--tblr-table-active-bg: var(--tblr-active-bg);--tblr-table-hover-color: inherit;--tblr-table-hover-bg: rgba(var(--tblr-emphasis-color-rgb), .075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--tblr-table-border-color)}.table>:not(caption)>*>*,.markdown>table>:not(caption)>*>*{padding:.5rem;color:var(--tblr-table-color-state, var(--tblr-table-color-type, var(--tblr-table-color)));background-color:var(--tblr-table-bg);border-bottom-width:var(--tblr-border-width);box-shadow:inset 0 0 0 9999px var(--tblr-table-bg-state, var(--tblr-table-bg-type, var(--tblr-table-accent-bg)))}.table>tbody,.markdown>table>tbody{vertical-align:inherit}.table>thead,.markdown>table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(var(--tblr-border-width) * 2) solid var(--tblr-border-color-translucent)}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*,.markdown>table>:not(caption)>*>*{padding:.25rem}.table-bordered>:not(caption)>*,.markdown>table>:not(caption)>*{border-width:var(--tblr-border-width) 0}.table-bordered>:not(caption)>*>*,.markdown>table>:not(caption)>*>*{border-width:0 var(--tblr-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(2n)>*{--tblr-table-color-type: var(--tblr-table-striped-color);--tblr-table-bg-type: var(--tblr-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--tblr-table-color-type: var(--tblr-table-striped-color);--tblr-table-bg-type: var(--tblr-table-striped-bg)}.table-active{--tblr-table-color-state: var(--tblr-table-active-color);--tblr-table-bg-state: var(--tblr-table-active-bg)}.table-hover>tbody>tr:hover>*{--tblr-table-color-state: var(--tblr-table-hover-color);--tblr-table-bg-state: var(--tblr-table-hover-bg)}.table-primary{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(204, 230.6, 229);--tblr-table-border-color: rgb(169.4, 192.68, 194.2);--tblr-table-striped-bg: rgb(195.35, 221.12, 220.3);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(186.7, 211.64, 211.6);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(191.025, 216.38, 215.95);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-secondary{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(225.4, 226.8, 229.6);--tblr-table-border-color: rgb(186.52, 189.64, 194.68);--tblr-table-striped-bg: rgb(215.68, 217.51, 220.87);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(205.96, 208.22, 212.14);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(210.82, 212.865, 216.505);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-success{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(213.4, 239.8, 217.6);--tblr-table-border-color: rgb(176.92, 200.04, 185.08);--tblr-table-striped-bg: rgb(204.28, 229.86, 209.47);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(195.16, 219.92, 201.34);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(199.72, 224.89, 205.405);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-info{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(217.2, 234.6, 249);--tblr-table-border-color: rgb(179.96, 195.88, 210.2);--tblr-table-striped-bg: rgb(207.89, 224.92, 239.3);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(198.58, 215.24, 229.6);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(203.235, 220.08, 234.45);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-warning{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(253, 235.8, 204);--tblr-table-border-color: rgb(208.6, 196.84, 174.2);--tblr-table-striped-bg: rgb(241.9, 226.06, 196.55);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(230.8, 216.32, 189.1);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(236.35, 221.19, 192.825);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-danger{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(246.8, 215.4, 215.4);--tblr-table-border-color: rgb(203.64, 180.52, 183.32);--tblr-table-striped-bg: rgb(236.01, 206.68, 207.38);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(225.22, 197.96, 199.36);--tblr-table-active-color: #f9fafb;--tblr-table-hover-bg: rgb(230.615, 202.32, 203.37);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-light{--tblr-table-color: #1f2937;--tblr-table-bg: #f9fafb;--tblr-table-border-color: rgb(205.4, 208.2, 211.8);--tblr-table-striped-bg: rgb(238.1, 239.55, 241.2);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(227.2, 229.1, 231.4);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(232.65, 234.325, 236.3);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-dark{--tblr-table-color: #f9fafb;--tblr-table-bg: #1f2937;--tblr-table-border-color: rgb(74.6, 82.8, 94.2);--tblr-table-striped-bg: rgb(41.9, 51.45, 64.8);--tblr-table-striped-color: #f9fafb;--tblr-table-active-bg: rgb(52.8, 61.9, 74.6);--tblr-table-active-color: #f9fafb;--tblr-table-hover-bg: rgb(47.35, 56.675, 69.7);--tblr-table-hover-color: #f9fafb;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem;font-size:.875rem;font-weight:var(--tblr-font-weight-medium)}.col-form-label{padding-top:calc(.5625rem + var(--tblr-border-width));padding-bottom:calc(.5625rem + var(--tblr-border-width));margin-bottom:0;font-size:inherit;font-weight:var(--tblr-font-weight-medium);line-height:1.25rem}.col-form-label-lg{padding-top:calc(.6875rem + var(--tblr-border-width));padding-bottom:calc(.6875rem + var(--tblr-border-width));font-size:1rem}.col-form-label-sm{padding-top:calc(.3125rem + var(--tblr-border-width));padding-bottom:calc(.3125rem + var(--tblr-border-width));font-size:.75rem}.form-text{margin-top:.25rem;font-size:.875em;color:var(--tblr-secondary-color)}.form-control{display:block;width:100%;padding:.5625rem 1rem;font-family:var(--tblr-body-font-family);font-size:.875rem;font-weight:400;line-height:1.25rem;color:var(--tblr-body-color);appearance:none;background-color:var(--tblr-bg-forms);background-clip:padding-box;border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-shadow-input);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--tblr-body-color);background-color:var(--tblr-bg-forms);border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.25rem;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--tblr-tertiary);opacity:1}.form-control:disabled{background-color:var(--tblr-bg-surface-secondary);opacity:1}.form-control::file-selector-button{padding:.5625rem 1rem;margin:-.5625rem -1rem;margin-inline-end:1rem;color:var(--tblr-body-color);background-color:var(--tblr-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--tblr-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--tblr-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.5625rem 0;margin-bottom:0;line-height:1.25rem;color:var(--tblr-body-color);background-color:transparent;border:solid transparent;border-width:var(--tblr-border-width) 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2));padding:.3125rem .5rem;font-size:.75rem;border-radius:var(--tblr-border-radius-sm)}.form-control-sm::file-selector-button{padding:.3125rem .5rem;margin:-.3125rem -.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2));padding:.6875rem 1.5rem;font-size:1rem;border-radius:var(--tblr-border-radius-lg)}.form-control-lg::file-selector-button{padding:.6875rem 1.5rem;margin:-.6875rem -1.5rem;margin-inline-end:1.5rem}textarea.form-control{min-height:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2));padding:.5625rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:var(--tblr-border-radius)}.form-control-color::-webkit-color-swatch{border:0!important;border-radius:var(--tblr-border-radius)}.form-control-color.form-control-sm{height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2))}.form-select{--tblr-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.5625rem 3rem .5625rem 1rem;font-family:var(--tblr-body-font-family);font-size:.875rem;font-weight:400;line-height:1.25rem;color:var(--tblr-body-color);appearance:none;background-color:var(--tblr-bg-forms);background-image:var(--tblr-form-select-bg-img),var(--tblr-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right 1rem center;background-size:16px 12px;border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-shadow-input);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:1rem;background-image:none}.form-select:disabled{background-color:var(--tblr-bg-surface-secondary)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--tblr-body-color)}.form-select-sm{padding-top:.3125rem;padding-bottom:.3125rem;padding-left:.5rem;font-size:.75rem;border-radius:var(--tblr-border-radius-sm)}.form-select-lg{padding-top:.6875rem;padding-bottom:.6875rem;padding-left:1.5rem;font-size:1rem;border-radius:var(--tblr-border-radius-lg)}[data-bs-theme=dark] .form-select,body[data-bs-theme=dark] [data-bs-theme=light] .form-select{--tblr-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23e5e7eb' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check{display:block;min-height:1.25rem;padding-left:2rem;margin-bottom:.75rem}.form-check .form-check-input{float:left;margin-left:-2rem}.form-check-reverse{padding-right:2rem;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-2rem;margin-left:0}.form-check-input{--tblr-form-check-bg: var(--tblr-bg-forms);flex-shrink:0;width:1.25rem;height:1.25rem;margin-top:.0892857143rem;vertical-align:top;appearance:none;background-color:var(--tblr-form-check-bg);background-image:var(--tblr-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:var(--tblr-border-radius)}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#80c2be;outline:0;box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-check-input:checked{background-color:var(--tblr-primary);border-color:var(--tblr-border-color-translucent)}.form-check-input:checked[type=checkbox]{--tblr-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--tblr-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3ccircle r='3' fill='%23ffffff' cx='8' cy='8' /%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:var(--tblr-primary);border-color:var(--tblr-primary);--tblr-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input:disabled~.form-check-label{cursor:default;opacity:.7}.form-switch{padding-left:2.5rem}.form-switch .form-check-input{--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23e5e7eb'/%3e%3c/svg%3e");width:2rem;margin-left:-2.5rem;background-image:var(--tblr-form-switch-bg);background-position:left center;border-radius:2rem;transition:background-position .15s ease-in-out}.form-switch .form-check-input:focus{--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 194, 190%29'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5rem;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5rem;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.4}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.25rem;padding:0;appearance:none;background-color:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #f9fafb,0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #f9fafb,0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.375rem;appearance:none;background-color:var(--tblr-primary);border:2px var(--tblr-border-style) #ffffff;border-radius:1rem;box-shadow:0 .1rem .25rem #0000001a;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b3dad8}.form-range::-webkit-slider-runnable-track{width:100%;height:.25rem;color:transparent;cursor:pointer;background-color:var(--tblr-border-color);border-color:transparent;border-radius:1rem;box-shadow:var(--tblr-box-shadow-inset)}.form-range::-moz-range-thumb{width:1rem;height:1rem;appearance:none;background-color:var(--tblr-primary);border:2px var(--tblr-border-style) #ffffff;border-radius:1rem;box-shadow:0 .1rem .25rem #0000001a;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#b3dad8}.form-range::-moz-range-track{width:100%;height:.25rem;color:transparent;cursor:pointer;background-color:var(--tblr-border-color);border-color:transparent;border-radius:1rem;box-shadow:var(--tblr-box-shadow-inset)}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--tblr-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--tblr-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--tblr-border-width) * 2));min-height:calc(3.5rem + calc(var(--tblr-border-width) * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;max-width:100%;height:100%;padding:1rem;overflow:hidden;color:rgba(var(--tblr-body-color-rgb),.65);text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:var(--tblr-border-width) solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem}.form-floating>.form-control::placeholder,.form-floating>.form-control-plaintext::placeholder{color:transparent}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown),.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill,.form-floating>.form-control-plaintext:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem;padding-left:1rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-control-plaintext~label,.form-floating>.form-select~label{transform:scale(.85) translateY(-.5rem) translate(.15rem)}.form-floating>.form-control:-webkit-autofill~label{transform:scale(.85) translateY(-.5rem) translate(.15rem)}.form-floating>textarea:focus~label:after,.form-floating>textarea:not(:placeholder-shown)~label:after{position:absolute;inset:1rem .5rem;z-index:-1;height:1.5em;content:"";background-color:var(--tblr-bg-forms);border-radius:var(--tblr-border-radius)}.form-floating>textarea:disabled~label:after{background-color:var(--tblr-bg-surface-secondary)}.form-floating>.form-control-plaintext~label{border-width:var(--tblr-border-width) 0}.form-floating>:disabled~label,.form-floating>.form-control:disabled~label{color:#4b5563}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-floating{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus,.input-group>.form-floating:focus-within{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.5625rem 1rem;font-size:.875rem;font-weight:400;line-height:1.25rem;color:var(--tblr-gray-500);text-align:center;white-space:nowrap;background-color:var(--tblr-bg-surface-secondary);border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.6875rem 1.5rem;font-size:1rem;border-radius:var(--tblr-border-radius-lg)}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.3125rem .5rem;font-size:.75rem;border-radius:var(--tblr-border-radius-sm)}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:4rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(-1 * var(--tblr-border-width));border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--tblr-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:var(--tblr-spacer-1) var(--tblr-spacer-3);margin-top:.1rem;font-size:.765625rem;color:#fff;background-color:var(--tblr-success);border-radius:var(--tblr-border-radius)}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:var(--tblr-form-valid-border-color);padding-right:2.375rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:var(--tblr-form-valid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-success-rgb),.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:2.375rem;background-position:top 1.53125rem right 1.53125rem}.was-validated .form-select:valid,.form-select.is-valid{border-color:var(--tblr-form-valid-border-color)}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{--tblr-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");padding-right:5.5rem;background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:var(--tblr-form-valid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-success-rgb),.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:5.375rem}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:var(--tblr-form-valid-border-color)}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:var(--tblr-form-valid-color)}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(var(--tblr-success-rgb),.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:var(--tblr-form-valid-color)}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):valid,.input-group>.form-control:not(:focus).is-valid,.was-validated .input-group>.form-select:not(:focus):valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.input-group>.form-floating:not(:focus-within).is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--tblr-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:var(--tblr-spacer-1) var(--tblr-spacer-3);margin-top:.1rem;font-size:.765625rem;color:#fff;background-color:var(--tblr-danger);border-radius:var(--tblr-border-radius)}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,select.tomselected.is-invalid+div.ts-wrapper~.invalid-feedback,.is-invalid~.invalid-tooltip,select.tomselected.is-invalid+div.ts-wrapper~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid,select.tomselected.is-invalid+div.form-control.ts-wrapper{border-color:var(--tblr-form-invalid-border-color);padding-right:2.375rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus,select.tomselected.is-invalid+div.form-control.ts-wrapper:focus{border-color:var(--tblr-form-invalid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-danger-rgb),.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:2.375rem;background-position:top 1.53125rem right 1.53125rem}.was-validated .form-select:invalid,.form-select.is-invalid,select.tomselected.is-invalid+div.form-select.ts-wrapper{border-color:var(--tblr-form-invalid-border-color)}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),select.tomselected.is-invalid+div.form-select.ts-wrapper:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],select.tomselected.is-invalid+div.form-select.ts-wrapper:not([multiple])[size="1"]{--tblr-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");padding-right:5.5rem;background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus,select.tomselected.is-invalid+div.form-select.ts-wrapper:focus{border-color:var(--tblr-form-invalid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-danger-rgb),.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid,select.tomselected.is-invalid+div.form-control-color.ts-wrapper{width:5.375rem}.was-validated .form-check-input:invalid,.form-check-input.is-invalid,select.tomselected.is-invalid+div.form-check-input.ts-wrapper{border-color:var(--tblr-form-invalid-border-color)}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked,select.tomselected.is-invalid+div.form-check-input.ts-wrapper:checked{background-color:var(--tblr-form-invalid-color)}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus,select.tomselected.is-invalid+div.form-check-input.ts-wrapper:focus{box-shadow:0 0 0 .25rem rgba(var(--tblr-danger-rgb),.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label,select.tomselected.is-invalid+div.form-check-input.ts-wrapper~.form-check-label{color:var(--tblr-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):invalid,.input-group>.form-control:not(:focus).is-invalid,.input-group>select.tomselected.is-invalid+div.form-control.ts-wrapper:not(:focus),.was-validated .input-group>.form-select:not(:focus):invalid,.input-group>.form-select:not(:focus).is-invalid,.input-group>select.tomselected.is-invalid+div.form-select.ts-wrapper:not(:focus),.was-validated .input-group>.form-floating:not(:focus-within):invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>select.tomselected.is-invalid+div.form-floating.ts-wrapper:not(:focus-within){z-index:4}.btn{--tblr-btn-padding-x: .5rem;--tblr-btn-padding-y: .25rem;--tblr-btn-font-family: var(--tblr-body-font-family);--tblr-btn-font-size: .875rem;--tblr-btn-font-weight: var(--tblr-font-weight-medium);--tblr-btn-line-height: 1.25rem;--tblr-btn-color: var(--tblr-body-color);--tblr-btn-bg: transparent;--tblr-btn-border-width: var(--tblr-border-width);--tblr-btn-border-color: transparent;--tblr-btn-border-radius: var(--tblr-border-radius);--tblr-btn-hover-border-color: transparent;--tblr-btn-box-shadow: var(--tblr-shadow-input);--tblr-btn-disabled-opacity: .4;--tblr-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--tblr-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--tblr-btn-padding-y) var(--tblr-btn-padding-x);font-family:var(--tblr-btn-font-family);font-size:var(--tblr-btn-font-size);font-weight:var(--tblr-btn-font-weight);line-height:var(--tblr-btn-line-height);color:var(--tblr-btn-color);text-align:center;vertical-align:middle;cursor:pointer;user-select:none;border:var(--tblr-btn-border-width) solid var(--tblr-btn-border-color);border-radius:var(--tblr-btn-border-radius);background-color:var(--tblr-btn-bg);box-shadow:var(--tblr-btn-box-shadow);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--tblr-btn-hover-color);text-decoration:none;background-color:var(--tblr-btn-hover-bg);border-color:var(--tblr-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--tblr-btn-color);background-color:var(--tblr-btn-bg);border-color:var(--tblr-btn-border-color)}.btn:focus-visible{color:var(--tblr-btn-hover-color);background-color:var(--tblr-btn-hover-bg);border-color:var(--tblr-btn-hover-border-color);outline:0;box-shadow:var(--tblr-btn-box-shadow),var(--tblr-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--tblr-btn-hover-border-color);outline:0;box-shadow:var(--tblr-btn-box-shadow),var(--tblr-btn-focus-box-shadow)}.btn-check:checked+.btn,:not(.btn-check)+.btn:active,.btn:first-child:active,.btn.active,.btn.show{color:var(--tblr-btn-active-color);background-color:var(--tblr-btn-active-bg);border-color:var(--tblr-btn-active-border-color);box-shadow:var(--tblr-btn-active-shadow)}.btn-check:checked+.btn:focus-visible,:not(.btn-check)+.btn:active:focus-visible,.btn:first-child:active:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible{box-shadow:var(--tblr-btn-active-shadow),var(--tblr-btn-focus-box-shadow)}.btn-check:checked:focus-visible+.btn{box-shadow:var(--tblr-btn-active-shadow),var(--tblr-btn-focus-box-shadow)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{color:var(--tblr-btn-disabled-color);pointer-events:none;background-color:var(--tblr-btn-disabled-bg);border-color:var(--tblr-btn-disabled-border-color);opacity:var(--tblr-btn-disabled-opacity);box-shadow:none}.btn-link{--tblr-btn-font-weight: 400;--tblr-btn-color: var(--tblr-link-color);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-link-hover-color);--tblr-btn-hover-border-color: transparent;--tblr-btn-active-color: var(--tblr-link-hover-color);--tblr-btn-active-border-color: transparent;--tblr-btn-disabled-color: #4b5563;--tblr-btn-disabled-border-color: transparent;--tblr-btn-box-shadow: 0 0 0 #000;--tblr-btn-focus-shadow-rgb: 37, 151, 144;text-decoration:none}.btn-link:hover,.btn-link:focus-visible{text-decoration:underline}.btn-link:focus-visible{color:var(--tblr-btn-color)}.btn-link:hover{color:var(--tblr-btn-hover-color)}.btn-lg,.btn-group-lg>.btn{--tblr-btn-padding-y: .6875rem;--tblr-btn-padding-x: 1.5rem;--tblr-btn-font-size: 1rem;--tblr-btn-border-radius: var(--tblr-border-radius-lg)}.btn-sm,.btn-group-sm>.btn{--tblr-btn-padding-y: .3125rem;--tblr-btn-padding-x: .5rem;--tblr-btn-font-size: .75rem;--tblr-btn-border-radius: var(--tblr-border-radius-sm)}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media(prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart,.dropup-center,.dropdown-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(-45deg)}.dropdown-menu{--tblr-dropdown-zindex: 1000;--tblr-dropdown-min-width: 11rem;--tblr-dropdown-padding-x: 0;--tblr-dropdown-padding-y: .25rem;--tblr-dropdown-spacer: 1px;--tblr-dropdown-font-size: .875rem;--tblr-dropdown-color: var(--tblr-body-color);--tblr-dropdown-bg: var(--tblr-bg-surface);--tblr-dropdown-border-color: var(--tblr-border-color-translucent);--tblr-dropdown-border-radius: var(--tblr-border-radius);--tblr-dropdown-border-width: var(--tblr-border-width);--tblr-dropdown-inner-border-radius: calc(var(--tblr-border-radius) - var(--tblr-border-width));--tblr-dropdown-divider-bg: var(--tblr-border-color-translucent);--tblr-dropdown-divider-margin-y: var(--tblr-spacer-2);--tblr-dropdown-box-shadow: var(--tblr-shadow-dropdown);--tblr-dropdown-link-color: inherit;--tblr-dropdown-link-hover-color: inherit;--tblr-dropdown-link-hover-bg: rgba(var(--tblr-secondary-rgb), .08);--tblr-dropdown-link-active-color: var(--tblr-primary);--tblr-dropdown-link-active-bg: var(--tblr-active-bg);--tblr-dropdown-link-disabled-color: var(--tblr-tertiary-color);--tblr-dropdown-item-padding-x: .75rem;--tblr-dropdown-item-padding-y: .5rem;--tblr-dropdown-header-color: #4b5563;--tblr-dropdown-header-padding-x: .75rem;--tblr-dropdown-header-padding-y: .25rem;position:absolute;z-index:var(--tblr-dropdown-zindex);display:none;min-width:var(--tblr-dropdown-min-width);padding:var(--tblr-dropdown-padding-y) var(--tblr-dropdown-padding-x);margin:0;font-size:var(--tblr-dropdown-font-size);color:var(--tblr-dropdown-color);text-align:left;list-style:none;background-color:var(--tblr-dropdown-bg);background-clip:padding-box;border:var(--tblr-dropdown-border-width) solid var(--tblr-dropdown-border-color);border-radius:var(--tblr-dropdown-border-radius);box-shadow:var(--tblr-dropdown-box-shadow)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--tblr-dropdown-spacer)}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width:576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width:768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width:992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width:1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width:1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--tblr-dropdown-spacer)}.dropup .dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(135deg)}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--tblr-dropdown-spacer)}.dropend .dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(-135deg)}.dropend .dropdown-toggle:after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--tblr-dropdown-spacer)}.dropstart .dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(45deg)}.dropstart .dropdown-toggle:before{vertical-align:0}.dropdown-divider{height:0;margin:var(--tblr-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--tblr-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--tblr-dropdown-item-padding-y) var(--tblr-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--tblr-dropdown-link-color);text-align:inherit;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--tblr-dropdown-item-border-radius, 0)}.dropdown-item:hover,.dropdown-item:focus{color:var(--tblr-dropdown-link-hover-color);text-decoration:none;background-color:var(--tblr-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--tblr-dropdown-link-active-color);text-decoration:none;background-color:var(--tblr-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--tblr-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--tblr-dropdown-header-padding-y) var(--tblr-dropdown-header-padding-x);margin-bottom:0;font-size:.765625rem;color:var(--tblr-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--tblr-dropdown-item-padding-y) var(--tblr-dropdown-item-padding-x);color:var(--tblr-dropdown-link-color)}.dropdown-menu-dark{--tblr-dropdown-color: #d1d5db;--tblr-dropdown-bg: #1f2937;--tblr-dropdown-border-color: var(--tblr-border-color-translucent);--tblr-dropdown-box-shadow: ;--tblr-dropdown-link-color: #d1d5db;--tblr-dropdown-link-hover-color: #ffffff;--tblr-dropdown-divider-bg: var(--tblr-border-color-translucent);--tblr-dropdown-link-hover-bg: rgba(255, 255, 255, .15);--tblr-dropdown-link-active-color: var(--tblr-primary);--tblr-dropdown-link-active-bg: var(--tblr-active-bg);--tblr-dropdown-link-disabled-color: #6b7280;--tblr-dropdown-header-color: #6b7280}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:var(--tblr-border-radius)}.btn-group>:not(.btn-check:first-child)+.btn,.btn-group>.btn-group:not(:first-child){margin-left:calc(-1 * var(--tblr-border-width))}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after,.dropend .dropdown-toggle-split:after{margin-left:0}.dropstart .dropdown-toggle-split:before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:1.125rem;padding-left:1.125rem}.btn-group.show .dropdown-toggle{box-shadow:inset 0 3px 5px #00000020}.btn-group.show .dropdown-toggle.btn-link{box-shadow:none}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:calc(-1 * var(--tblr-border-width))}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:nth-child(n+3),.btn-group-vertical>:not(.btn-check)+.btn,.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--tblr-nav-link-padding-x: .75rem;--tblr-nav-link-padding-y: .5rem;--tblr-nav-link-font-weight: ;--tblr-nav-link-color: var(--tblr-gray-500);--tblr-nav-link-hover-color: var(--tblr-link-hover-color);--tblr-nav-link-disabled-color: var(--tblr-disabled-color);display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--tblr-nav-link-padding-y) var(--tblr-nav-link-padding-x);font-size:var(--tblr-nav-link-font-size);font-weight:var(--tblr-nav-link-font-weight);color:var(--tblr-nav-link-color);background:none;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}.nav-link:hover,.nav-link:focus{color:var(--tblr-nav-link-hover-color);text-decoration:none}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.nav-link.disabled,.nav-link:disabled{color:var(--tblr-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--tblr-nav-tabs-border-width: var(--tblr-border-width);--tblr-nav-tabs-border-color: var(--tblr-border-color);--tblr-nav-tabs-border-radius: var(--tblr-border-radius);--tblr-nav-tabs-link-hover-border-color: var(--tblr-border-color) var(--tblr-border-color) var(--tblr-border-color);--tblr-nav-tabs-link-active-color: var(--tblr-body-color);--tblr-nav-tabs-link-active-bg: var(--tblr-body-bg);--tblr-nav-tabs-link-active-border-color: var(--tblr-border-color) var(--tblr-border-color) var(--tblr-border-color);border-bottom:var(--tblr-nav-tabs-border-width) solid var(--tblr-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--tblr-nav-tabs-border-width));border:var(--tblr-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--tblr-nav-tabs-border-radius);border-top-right-radius:var(--tblr-nav-tabs-border-radius)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{isolation:isolate;border-color:var(--tblr-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:var(--tblr-nav-tabs-link-active-color);background-color:var(--tblr-nav-tabs-link-active-bg);border-color:var(--tblr-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--tblr-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--tblr-nav-pills-border-radius: var(--tblr-border-radius);--tblr-nav-pills-link-active-color: var(--tblr-primary);--tblr-nav-pills-link-active-bg: rgba(var(--tblr-secondary-rgb), .15)}.nav-pills .nav-link{border-radius:var(--tblr-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--tblr-nav-pills-link-active-color);background-color:var(--tblr-nav-pills-link-active-bg)}.nav-underline{--tblr-nav-underline-gap: 1rem;--tblr-nav-underline-border-width: .125rem;--tblr-nav-underline-link-active-color: var(--tblr-emphasis-color);gap:var(--tblr-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--tblr-nav-underline-border-width) solid transparent}.nav-underline .nav-link:hover,.nav-underline .nav-link:focus{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:600;color:var(--tblr-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-grow:1;flex-basis:0;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--tblr-navbar-padding-x: 0;--tblr-navbar-padding-y: .25rem;--tblr-navbar-color: var(--tblr-secondary);--tblr-navbar-hover-color: var(--tblr-body-color);--tblr-navbar-disabled-color: var(--tblr-disabled-color);--tblr-navbar-active-color: var(--tblr-body-color);--tblr-navbar-brand-padding-y: .5rem;--tblr-navbar-brand-margin-end: 1rem;--tblr-navbar-brand-font-size: 1.25rem;--tblr-navbar-brand-color: var(--tblr-body-color);--tblr-navbar-brand-hover-color: var(--tblr-body-color);--tblr-navbar-nav-link-padding-x: .75rem;--tblr-navbar-toggler-padding-y: 0;--tblr-navbar-toggler-padding-x: 0;--tblr-navbar-toggler-font-size: 1rem;--tblr-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2831, 41, 55, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--tblr-navbar-toggler-border-color: rgba(var(--tblr-emphasis-color-rgb), .15);--tblr-navbar-toggler-border-radius: var(--tblr-border-radius);--tblr-navbar-toggler-focus-width: 0;--tblr-navbar-toggler-transition: box-shadow .15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--tblr-navbar-padding-y) var(--tblr-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-sm,.navbar>.container-md,.navbar>.container-lg,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--tblr-navbar-brand-padding-y);padding-bottom:var(--tblr-navbar-brand-padding-y);margin-right:var(--tblr-navbar-brand-margin-end);font-size:var(--tblr-navbar-brand-font-size);color:var(--tblr-navbar-brand-color);white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{color:var(--tblr-navbar-brand-hover-color);text-decoration:none}.navbar-nav{--tblr-nav-link-padding-x: 0;--tblr-nav-link-padding-y: .5rem;--tblr-nav-link-font-weight: ;--tblr-nav-link-color: var(--tblr-navbar-color);--tblr-nav-link-hover-color: var(--tblr-navbar-hover-color);--tblr-nav-link-disabled-color: var(--tblr-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--tblr-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--tblr-navbar-color)}.navbar-text a,.navbar-text a:hover,.navbar-text a:focus{color:var(--tblr-navbar-active-color)}.navbar-collapse{flex-grow:1;flex-basis:100%;align-items:center}.navbar-toggler{padding:var(--tblr-navbar-toggler-padding-y) var(--tblr-navbar-toggler-padding-x);font-size:var(--tblr-navbar-toggler-font-size);line-height:1;color:var(--tblr-navbar-color);background-color:transparent;border:var(--tblr-border-width) solid var(--tblr-navbar-toggler-border-color);border-radius:var(--tblr-navbar-toggler-border-radius);transition:var(--tblr-navbar-toggler-transition)}@media(prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--tblr-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--tblr-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--tblr-scroll-height, 75vh);overflow-y:auto}@media(min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark],body[data-bs-theme=dark] .navbar[data-bs-theme=light]{--tblr-navbar-color: rgba(255, 255, 255, .7);--tblr-navbar-hover-color: rgba(255, 255, 255, .75);--tblr-navbar-disabled-color: var(--tblr-disabled-color);--tblr-navbar-active-color: #ffffff;--tblr-navbar-brand-color: #ffffff;--tblr-navbar-brand-hover-color: #ffffff;--tblr-navbar-toggler-border-color: rgba(255, 255, 255, .1);--tblr-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.7%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon,body[data-bs-theme=dark] [data-bs-theme=light] .navbar-toggler-icon{--tblr-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.7%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--tblr-card-spacer-y: 1rem;--tblr-card-spacer-x: 1.25rem;--tblr-card-title-spacer-y: 1.25rem;--tblr-card-title-color: ;--tblr-card-subtitle-color: ;--tblr-card-border-width: var(--tblr-border-width);--tblr-card-border-color: var(--tblr-border-color-translucent);--tblr-card-border-radius: var(--tblr-border-radius-lg);--tblr-card-box-shadow: var(--tblr-shadow-card);--tblr-card-inner-border-radius: calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));--tblr-card-cap-padding-y: 1rem;--tblr-card-cap-padding-x: 1.25rem;--tblr-card-cap-bg: var(--tblr-bg-surface-tertiary);--tblr-card-cap-color: inherit;--tblr-card-height: ;--tblr-card-color: inherit;--tblr-card-bg: var(--tblr-bg-surface);--tblr-card-img-overlay-padding: 1rem;--tblr-card-group-margin: 1.5rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--tblr-card-height);color:var(--tblr-body-color);word-wrap:break-word;background-color:var(--tblr-card-bg);background-clip:border-box;border:var(--tblr-card-border-width) solid var(--tblr-card-border-color);border-radius:var(--tblr-card-border-radius);box-shadow:var(--tblr-card-box-shadow)}.card>hr,.card>.hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--tblr-card-inner-border-radius);border-top-right-radius:var(--tblr-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--tblr-card-inner-border-radius);border-bottom-left-radius:var(--tblr-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--tblr-card-spacer-y) var(--tblr-card-spacer-x);color:var(--tblr-card-color)}.card-title{margin-bottom:var(--tblr-card-title-spacer-y);color:var(--tblr-card-title-color)}.card-subtitle{margin-top:calc(-.5 * var(--tblr-card-title-spacer-y));margin-bottom:0;color:var(--tblr-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:var(--tblr-card-spacer-x)}.card-header{padding:var(--tblr-card-cap-padding-y) var(--tblr-card-cap-padding-x);margin-bottom:0;color:var(--tblr-card-cap-color);background-color:var(--tblr-card-cap-bg);border-bottom:var(--tblr-card-border-width) solid var(--tblr-card-border-color)}.card-header:first-child{border-radius:var(--tblr-card-inner-border-radius) var(--tblr-card-inner-border-radius) 0 0}.card-footer{padding:var(--tblr-card-cap-padding-y) var(--tblr-card-cap-padding-x);color:var(--tblr-card-cap-color);background-color:var(--tblr-card-cap-bg);border-top:var(--tblr-card-border-width) solid var(--tblr-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--tblr-card-inner-border-radius) var(--tblr-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--tblr-card-cap-padding-x));margin-bottom:calc(-1 * var(--tblr-card-cap-padding-y));margin-left:calc(-.5 * var(--tblr-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--tblr-card-bg);border-bottom-color:var(--tblr-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--tblr-card-cap-padding-x));margin-left:calc(-.5 * var(--tblr-card-cap-padding-x))}.card-img-overlay{position:absolute;inset:0;padding:var(--tblr-card-img-overlay-padding);border-radius:var(--tblr-card-inner-border-radius)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--tblr-card-inner-border-radius);border-top-right-radius:var(--tblr-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--tblr-card-inner-border-radius);border-bottom-left-radius:var(--tblr-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--tblr-card-group-margin)}@media(min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child)>.card-img-top,.card-group>.card:not(:last-child)>.card-header{border-top-right-radius:0}.card-group>.card:not(:last-child)>.card-img-bottom,.card-group>.card:not(:last-child)>.card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child)>.card-img-top,.card-group>.card:not(:first-child)>.card-header{border-top-left-radius:0}.card-group>.card:not(:first-child)>.card-img-bottom,.card-group>.card:not(:first-child)>.card-footer{border-bottom-left-radius:0}}.pagination{--tblr-pagination-padding-x: .25rem;--tblr-pagination-padding-y: calc(.25rem + 1px) ;--tblr-pagination-font-size: .875rem;--tblr-pagination-color: var(--tblr-body-color);--tblr-pagination-bg: transparent;--tblr-pagination-border-width: 1px;--tblr-pagination-border-color: transparent;--tblr-pagination-border-radius: var(--tblr-border-radius);--tblr-pagination-hover-color: var(--tblr-link-hover-color);--tblr-pagination-hover-bg: var(--tblr-active-bg);--tblr-pagination-hover-border-color: var(--tblr-pagination-border-color);--tblr-pagination-focus-color: var(--tblr-link-hover-color);--tblr-pagination-focus-bg: var(--tblr-secondary-bg);--tblr-pagination-focus-box-shadow: 0 0 0 .25rem rgba(var(--tblr-primary-rgb), .25);--tblr-pagination-active-color: #ffffff;--tblr-pagination-active-bg: var(--tblr-primary);--tblr-pagination-active-border-color: var(--tblr-primary);--tblr-pagination-disabled-color: var(--tblr-disabled-color);--tblr-pagination-disabled-bg: transparent;--tblr-pagination-disabled-border-color: var(--tblr-pagination-border-color);display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--tblr-pagination-padding-y) var(--tblr-pagination-padding-x);font-size:var(--tblr-pagination-font-size);color:var(--tblr-pagination-color);background-color:var(--tblr-pagination-bg);border:var(--tblr-pagination-border-width) solid var(--tblr-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--tblr-pagination-hover-color);text-decoration:none;background-color:var(--tblr-pagination-hover-bg);border-color:var(--tblr-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--tblr-pagination-focus-color);background-color:var(--tblr-pagination-focus-bg);outline:0;box-shadow:var(--tblr-pagination-focus-box-shadow)}.page-link.active,.active>.page-link{z-index:3;color:var(--tblr-pagination-active-color);background-color:var(--tblr-pagination-active-bg);border-color:var(--tblr-pagination-active-border-color)}.page-link.disabled,.disabled>.page-link{color:var(--tblr-pagination-disabled-color);pointer-events:none;background-color:var(--tblr-pagination-disabled-bg);border-color:var(--tblr-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item:first-child .page-link{border-top-left-radius:var(--tblr-pagination-border-radius);border-bottom-left-radius:var(--tblr-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--tblr-pagination-border-radius);border-bottom-right-radius:var(--tblr-pagination-border-radius)}.pagination-lg{--tblr-pagination-padding-x: 1.5rem;--tblr-pagination-padding-y: .75rem;--tblr-pagination-font-size: 1.09375rem;--tblr-pagination-border-radius: var(--tblr-border-radius-lg)}.pagination-sm{--tblr-pagination-padding-x: .5rem;--tblr-pagination-padding-y: .25rem;--tblr-pagination-font-size: .765625rem;--tblr-pagination-border-radius: var(--tblr-border-radius-sm)}@keyframes progress-bar-stripes{0%{background-position-x:var(--tblr-progress-height)}}.progress,.progress-stacked{--tblr-progress-height: .5rem;--tblr-progress-font-size: .65625rem;--tblr-progress-bg: var(--tblr-border-color);--tblr-progress-border-radius: var(--tblr-border-radius);--tblr-progress-box-shadow: var(--tblr-box-shadow-inset);--tblr-progress-bar-color: #ffffff;--tblr-progress-bar-bg: var(--tblr-primary);--tblr-progress-bar-transition: width .6s ease;display:flex;height:var(--tblr-progress-height);overflow:hidden;font-size:var(--tblr-progress-font-size);background-color:var(--tblr-progress-bg);border-radius:var(--tblr-progress-border-radius);box-shadow:var(--tblr-progress-box-shadow)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--tblr-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--tblr-progress-bar-bg);transition:var(--tblr-progress-bar-transition)}@media(prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--tblr-progress-height) var(--tblr-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--tblr-list-group-color: var(--tblr-body-color);--tblr-list-group-bg: inherit;--tblr-list-group-border-color: var(--tblr-border-color);--tblr-list-group-border-width: var(--tblr-border-width);--tblr-list-group-border-radius: var(--tblr-border-radius);--tblr-list-group-item-padding-x: 1.25rem;--tblr-list-group-item-padding-y: 1rem;--tblr-list-group-action-color: inherit;--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: rgba(var(--tblr-secondary-rgb), .08);--tblr-list-group-action-active-color: var(--tblr-body-color);--tblr-list-group-action-active-bg: var(--tblr-secondary-bg);--tblr-list-group-disabled-color: var(--tblr-secondary-color);--tblr-list-group-disabled-bg: inherit;--tblr-list-group-active-color: inherit;--tblr-list-group-active-bg: var(--tblr-active-bg);--tblr-list-group-active-border-color: var(--tblr-border-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--tblr-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item:before{content:counters(section,".") ". ";counter-increment:section}.list-group-item{position:relative;display:block;padding:var(--tblr-list-group-item-padding-y) var(--tblr-list-group-item-padding-x);color:var(--tblr-list-group-color);background-color:var(--tblr-list-group-bg);border:var(--tblr-list-group-border-width) solid var(--tblr-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--tblr-list-group-disabled-color);pointer-events:none;background-color:var(--tblr-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--tblr-list-group-active-color);background-color:var(--tblr-list-group-active-bg);border-color:var(--tblr-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--tblr-list-group-border-width));border-top-width:var(--tblr-list-group-border-width)}.list-group-item-action{width:100%;color:var(--tblr-list-group-action-color);text-align:inherit}.list-group-item-action:not(.active):hover,.list-group-item-action:not(.active):focus{z-index:1;color:var(--tblr-list-group-action-hover-color);text-decoration:none;background-color:var(--tblr-list-group-action-hover-bg)}.list-group-item-action:not(.active):active{color:var(--tblr-list-group-action-active-color);background-color:var(--tblr-list-group-action-active-bg)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}@media(min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--tblr-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{--tblr-list-group-color: var(--tblr-primary-text-emphasis);--tblr-list-group-bg: var(--tblr-primary-bg-subtle);--tblr-list-group-border-color: var(--tblr-primary-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-primary-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-primary-border-subtle);--tblr-list-group-active-color: var(--tblr-primary-bg-subtle);--tblr-list-group-active-bg: var(--tblr-primary-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-primary-text-emphasis)}.list-group-item-secondary{--tblr-list-group-color: var(--tblr-secondary-text-emphasis);--tblr-list-group-bg: var(--tblr-secondary-bg-subtle);--tblr-list-group-border-color: var(--tblr-secondary-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-secondary-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-secondary-border-subtle);--tblr-list-group-active-color: var(--tblr-secondary-bg-subtle);--tblr-list-group-active-bg: var(--tblr-secondary-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-secondary-text-emphasis)}.list-group-item-success{--tblr-list-group-color: var(--tblr-success-text-emphasis);--tblr-list-group-bg: var(--tblr-success-bg-subtle);--tblr-list-group-border-color: var(--tblr-success-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-success-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-success-border-subtle);--tblr-list-group-active-color: var(--tblr-success-bg-subtle);--tblr-list-group-active-bg: var(--tblr-success-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-success-text-emphasis)}.list-group-item-info{--tblr-list-group-color: var(--tblr-info-text-emphasis);--tblr-list-group-bg: var(--tblr-info-bg-subtle);--tblr-list-group-border-color: var(--tblr-info-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-info-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-info-border-subtle);--tblr-list-group-active-color: var(--tblr-info-bg-subtle);--tblr-list-group-active-bg: var(--tblr-info-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-info-text-emphasis)}.list-group-item-warning{--tblr-list-group-color: var(--tblr-warning-text-emphasis);--tblr-list-group-bg: var(--tblr-warning-bg-subtle);--tblr-list-group-border-color: var(--tblr-warning-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-warning-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-warning-border-subtle);--tblr-list-group-active-color: var(--tblr-warning-bg-subtle);--tblr-list-group-active-bg: var(--tblr-warning-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-warning-text-emphasis)}.list-group-item-danger{--tblr-list-group-color: var(--tblr-danger-text-emphasis);--tblr-list-group-bg: var(--tblr-danger-bg-subtle);--tblr-list-group-border-color: var(--tblr-danger-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-danger-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-danger-border-subtle);--tblr-list-group-active-color: var(--tblr-danger-bg-subtle);--tblr-list-group-active-bg: var(--tblr-danger-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-danger-text-emphasis)}.list-group-item-light{--tblr-list-group-color: var(--tblr-light-text-emphasis);--tblr-list-group-bg: var(--tblr-light-bg-subtle);--tblr-list-group-border-color: var(--tblr-light-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-light-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-light-border-subtle);--tblr-list-group-active-color: var(--tblr-light-bg-subtle);--tblr-list-group-active-bg: var(--tblr-light-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-light-text-emphasis)}.list-group-item-dark{--tblr-list-group-color: var(--tblr-dark-text-emphasis);--tblr-list-group-bg: var(--tblr-dark-bg-subtle);--tblr-list-group-border-color: var(--tblr-dark-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-dark-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-dark-border-subtle);--tblr-list-group-active-color: var(--tblr-dark-bg-subtle);--tblr-list-group-active-bg: var(--tblr-dark-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-dark-text-emphasis)}.list-group-item-muted{--tblr-list-group-color: var(--tblr-muted-text-emphasis);--tblr-list-group-bg: var(--tblr-muted-bg-subtle);--tblr-list-group-border-color: var(--tblr-muted-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-muted-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-muted-border-subtle);--tblr-list-group-active-color: var(--tblr-muted-bg-subtle);--tblr-list-group-active-bg: var(--tblr-muted-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-muted-text-emphasis)}.list-group-item-blue{--tblr-list-group-color: var(--tblr-blue-text-emphasis);--tblr-list-group-bg: var(--tblr-blue-bg-subtle);--tblr-list-group-border-color: var(--tblr-blue-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-blue-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-blue-border-subtle);--tblr-list-group-active-color: var(--tblr-blue-bg-subtle);--tblr-list-group-active-bg: var(--tblr-blue-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-blue-text-emphasis)}.list-group-item-azure{--tblr-list-group-color: var(--tblr-azure-text-emphasis);--tblr-list-group-bg: var(--tblr-azure-bg-subtle);--tblr-list-group-border-color: var(--tblr-azure-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-azure-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-azure-border-subtle);--tblr-list-group-active-color: var(--tblr-azure-bg-subtle);--tblr-list-group-active-bg: var(--tblr-azure-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-azure-text-emphasis)}.list-group-item-indigo{--tblr-list-group-color: var(--tblr-indigo-text-emphasis);--tblr-list-group-bg: var(--tblr-indigo-bg-subtle);--tblr-list-group-border-color: var(--tblr-indigo-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-indigo-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-indigo-border-subtle);--tblr-list-group-active-color: var(--tblr-indigo-bg-subtle);--tblr-list-group-active-bg: var(--tblr-indigo-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-indigo-text-emphasis)}.list-group-item-purple{--tblr-list-group-color: var(--tblr-purple-text-emphasis);--tblr-list-group-bg: var(--tblr-purple-bg-subtle);--tblr-list-group-border-color: var(--tblr-purple-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-purple-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-purple-border-subtle);--tblr-list-group-active-color: var(--tblr-purple-bg-subtle);--tblr-list-group-active-bg: var(--tblr-purple-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-purple-text-emphasis)}.list-group-item-pink{--tblr-list-group-color: var(--tblr-pink-text-emphasis);--tblr-list-group-bg: var(--tblr-pink-bg-subtle);--tblr-list-group-border-color: var(--tblr-pink-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-pink-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-pink-border-subtle);--tblr-list-group-active-color: var(--tblr-pink-bg-subtle);--tblr-list-group-active-bg: var(--tblr-pink-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-pink-text-emphasis)}.list-group-item-red{--tblr-list-group-color: var(--tblr-red-text-emphasis);--tblr-list-group-bg: var(--tblr-red-bg-subtle);--tblr-list-group-border-color: var(--tblr-red-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-red-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-red-border-subtle);--tblr-list-group-active-color: var(--tblr-red-bg-subtle);--tblr-list-group-active-bg: var(--tblr-red-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-red-text-emphasis)}.list-group-item-orange{--tblr-list-group-color: var(--tblr-orange-text-emphasis);--tblr-list-group-bg: var(--tblr-orange-bg-subtle);--tblr-list-group-border-color: var(--tblr-orange-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-orange-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-orange-border-subtle);--tblr-list-group-active-color: var(--tblr-orange-bg-subtle);--tblr-list-group-active-bg: var(--tblr-orange-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-orange-text-emphasis)}.list-group-item-yellow{--tblr-list-group-color: var(--tblr-yellow-text-emphasis);--tblr-list-group-bg: var(--tblr-yellow-bg-subtle);--tblr-list-group-border-color: var(--tblr-yellow-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-yellow-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-yellow-border-subtle);--tblr-list-group-active-color: var(--tblr-yellow-bg-subtle);--tblr-list-group-active-bg: var(--tblr-yellow-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-yellow-text-emphasis)}.list-group-item-lime{--tblr-list-group-color: var(--tblr-lime-text-emphasis);--tblr-list-group-bg: var(--tblr-lime-bg-subtle);--tblr-list-group-border-color: var(--tblr-lime-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-lime-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-lime-border-subtle);--tblr-list-group-active-color: var(--tblr-lime-bg-subtle);--tblr-list-group-active-bg: var(--tblr-lime-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-lime-text-emphasis)}.list-group-item-green{--tblr-list-group-color: var(--tblr-green-text-emphasis);--tblr-list-group-bg: var(--tblr-green-bg-subtle);--tblr-list-group-border-color: var(--tblr-green-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-green-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-green-border-subtle);--tblr-list-group-active-color: var(--tblr-green-bg-subtle);--tblr-list-group-active-bg: var(--tblr-green-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-green-text-emphasis)}.list-group-item-teal{--tblr-list-group-color: var(--tblr-teal-text-emphasis);--tblr-list-group-bg: var(--tblr-teal-bg-subtle);--tblr-list-group-border-color: var(--tblr-teal-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-teal-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-teal-border-subtle);--tblr-list-group-active-color: var(--tblr-teal-bg-subtle);--tblr-list-group-active-bg: var(--tblr-teal-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-teal-text-emphasis)}.list-group-item-cyan{--tblr-list-group-color: var(--tblr-cyan-text-emphasis);--tblr-list-group-bg: var(--tblr-cyan-bg-subtle);--tblr-list-group-border-color: var(--tblr-cyan-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-cyan-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-cyan-border-subtle);--tblr-list-group-active-color: var(--tblr-cyan-bg-subtle);--tblr-list-group-active-bg: var(--tblr-cyan-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-cyan-text-emphasis)}.toast{--tblr-toast-zindex: 1090;--tblr-toast-padding-x: .75rem;--tblr-toast-padding-y: .5rem;--tblr-toast-spacing: calc(var(--tblr-page-padding) * 2);--tblr-toast-max-width: 350px;--tblr-toast-font-size: .875rem;--tblr-toast-color: ;--tblr-toast-bg: var(--tblr-bg-surface);--tblr-toast-border-width: var(--tblr-border-width);--tblr-toast-border-color: var(--tblr-border-color);--tblr-toast-border-radius: var(--tblr-border-radius);--tblr-toast-box-shadow: var(--tblr-box-shadow);--tblr-toast-header-color: var(--tblr-gray-500);--tblr-toast-header-bg: rgba(var(--tblr-body-bg-rgb), .85);--tblr-toast-header-border-color: var(--tblr-border-color);width:var(--tblr-toast-max-width);max-width:100%;font-size:var(--tblr-toast-font-size);color:var(--tblr-toast-color);pointer-events:auto;background-color:var(--tblr-toast-bg);background-clip:padding-box;border:var(--tblr-toast-border-width) solid var(--tblr-toast-border-color);box-shadow:var(--tblr-toast-box-shadow);border-radius:var(--tblr-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--tblr-toast-zindex: 1090;position:absolute;z-index:var(--tblr-toast-zindex);width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--tblr-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--tblr-toast-padding-y) var(--tblr-toast-padding-x);color:var(--tblr-toast-header-color);background-color:var(--tblr-toast-header-bg);background-clip:padding-box;border-bottom:var(--tblr-toast-border-width) solid var(--tblr-toast-header-border-color);border-top-left-radius:calc(var(--tblr-toast-border-radius) - var(--tblr-toast-border-width));border-top-right-radius:calc(var(--tblr-toast-border-radius) - var(--tblr-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--tblr-toast-padding-x));margin-left:var(--tblr-toast-padding-x)}.toast-body{padding:var(--tblr-toast-padding-x);word-wrap:break-word}.modal{--tblr-modal-zindex: 1055;--tblr-modal-width: 540px;--tblr-modal-padding: 1.5rem;--tblr-modal-margin: .5rem;--tblr-modal-color: var(--tblr-body-color);--tblr-modal-bg: var(--tblr-bg-surface);--tblr-modal-border-color: transparent;--tblr-modal-border-width: var(--tblr-border-width);--tblr-modal-border-radius: var(--tblr-border-radius-lg);--tblr-modal-box-shadow: var(--tblr-box-shadow-sm);--tblr-modal-inner-border-radius: calc(var(--tblr-modal-border-radius) - 1px);--tblr-modal-header-padding-x: 1.5rem;--tblr-modal-header-padding-y: 1.5rem;--tblr-modal-header-padding: 1.5rem;--tblr-modal-header-border-color: var(--tblr-border-color);--tblr-modal-header-border-width: var(--tblr-border-width);--tblr-modal-title-line-height: 1.4285714286;--tblr-modal-footer-gap: .75rem;--tblr-modal-footer-bg: var(--tblr-bg-surface-tertiary);--tblr-modal-footer-border-color: var(--tblr-border-color);--tblr-modal-footer-border-width: var(--tblr-border-width);position:fixed;top:0;left:0;z-index:var(--tblr-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--tblr-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transform:translateY(-1rem);transition:transform .3s ease-out}@media(prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--tblr-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--tblr-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--tblr-modal-color);pointer-events:auto;background-color:var(--tblr-modal-bg);background-clip:padding-box;border:var(--tblr-modal-border-width) solid var(--tblr-modal-border-color);border-radius:var(--tblr-modal-border-radius);box-shadow:var(--tblr-modal-box-shadow);outline:0}.modal-backdrop{--tblr-backdrop-zindex: 1050;--tblr-backdrop-bg: var(--tblr-gray-800);--tblr-backdrop-opacity: .24;position:fixed;top:0;left:0;z-index:var(--tblr-backdrop-zindex);width:100vw;height:100vh;background-color:var(--tblr-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--tblr-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;padding:var(--tblr-modal-header-padding);border-bottom:var(--tblr-modal-header-border-width) solid var(--tblr-modal-header-border-color);border-top-left-radius:var(--tblr-modal-inner-border-radius);border-top-right-radius:var(--tblr-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--tblr-modal-header-padding-y) * .5) calc(var(--tblr-modal-header-padding-x) * .5);margin-top:calc(-.5 * var(--tblr-modal-header-padding-y));margin-right:calc(-.5 * var(--tblr-modal-header-padding-x));margin-bottom:calc(-.5 * var(--tblr-modal-header-padding-y));margin-left:auto}.modal-title{margin-bottom:0;line-height:var(--tblr-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--tblr-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--tblr-modal-padding) - var(--tblr-modal-footer-gap) * .5);background-color:var(--tblr-modal-footer-bg);border-top:var(--tblr-modal-footer-border-width) solid var(--tblr-modal-footer-border-color);border-bottom-right-radius:var(--tblr-modal-inner-border-radius);border-bottom-left-radius:var(--tblr-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--tblr-modal-footer-gap) * .5)}@media(min-width:576px){.modal{--tblr-modal-margin: 1.75rem;--tblr-modal-box-shadow: var(--tblr-box-shadow)}.modal-dialog{max-width:var(--tblr-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--tblr-modal-width: 380px}}@media(min-width:992px){.modal-lg,.modal-xl{--tblr-modal-width: 720px}}@media(min-width:1200px){.modal-xl{--tblr-modal-width: 1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header,.modal-fullscreen-sm-down .modal-footer{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header,.modal-fullscreen-md-down .modal-footer{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header,.modal-fullscreen-lg-down .modal-footer{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header,.modal-fullscreen-xl-down .modal-footer{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header,.modal-fullscreen-xxl-down .modal-footer{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--tblr-tooltip-zindex: 1080;--tblr-tooltip-max-width: 200px;--tblr-tooltip-padding-x: var(--tblr-spacer-3);--tblr-tooltip-padding-y: var(--tblr-spacer-1);--tblr-tooltip-margin: ;--tblr-tooltip-font-size: .765625rem;--tblr-tooltip-color: var(--tblr-text-inverted);--tblr-tooltip-bg: var(--tblr-bg-surface-inverted);--tblr-tooltip-border-radius: var(--tblr-border-radius);--tblr-tooltip-opacity: .9;--tblr-tooltip-arrow-width: .8rem;--tblr-tooltip-arrow-height: .4rem;z-index:var(--tblr-tooltip-zindex);display:block;margin:var(--tblr-tooltip-margin);font-family:var(--tblr-font-sans-serif);font-style:normal;font-weight:400;line-height:1.4285714286;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--tblr-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--tblr-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--tblr-tooltip-arrow-width);height:var(--tblr-tooltip-arrow-height)}.tooltip .tooltip-arrow:before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:calc(-1 * var(--tblr-tooltip-arrow-height))}.bs-tooltip-top .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow:before{top:-1px;border-width:var(--tblr-tooltip-arrow-height) calc(var(--tblr-tooltip-arrow-width) * .5) 0;border-top-color:var(--tblr-tooltip-bg)}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:calc(-1 * var(--tblr-tooltip-arrow-height));width:var(--tblr-tooltip-arrow-height);height:var(--tblr-tooltip-arrow-width)}.bs-tooltip-end .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow:before{right:-1px;border-width:calc(var(--tblr-tooltip-arrow-width) * .5) var(--tblr-tooltip-arrow-height) calc(var(--tblr-tooltip-arrow-width) * .5) 0;border-right-color:var(--tblr-tooltip-bg)}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:calc(-1 * var(--tblr-tooltip-arrow-height))}.bs-tooltip-bottom .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow:before{bottom:-1px;border-width:0 calc(var(--tblr-tooltip-arrow-width) * .5) var(--tblr-tooltip-arrow-height);border-bottom-color:var(--tblr-tooltip-bg)}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:calc(-1 * var(--tblr-tooltip-arrow-height));width:var(--tblr-tooltip-arrow-height);height:var(--tblr-tooltip-arrow-width)}.bs-tooltip-start .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow:before{left:-1px;border-width:calc(var(--tblr-tooltip-arrow-width) * .5) 0 calc(var(--tblr-tooltip-arrow-width) * .5) var(--tblr-tooltip-arrow-height);border-left-color:var(--tblr-tooltip-bg)}.tooltip-inner{max-width:var(--tblr-tooltip-max-width);padding:var(--tblr-tooltip-padding-y) var(--tblr-tooltip-padding-x);color:var(--tblr-tooltip-color);text-align:center;background-color:var(--tblr-tooltip-bg);border-radius:var(--tblr-tooltip-border-radius)}.popover{--tblr-popover-zindex: 1070;--tblr-popover-max-width: 276px;--tblr-popover-font-size: .765625rem;--tblr-popover-bg: var(--tblr-bg-surface);--tblr-popover-border-width: var(--tblr-border-width);--tblr-popover-border-color: var(--tblr-border-color);--tblr-popover-border-radius: var(--tblr-border-radius-lg);--tblr-popover-inner-border-radius: calc(var(--tblr-border-radius-lg) - var(--tblr-border-width));--tblr-popover-box-shadow: var(--tblr-shadow-lg);--tblr-popover-header-padding-x: 1rem;--tblr-popover-header-padding-y: .5rem;--tblr-popover-header-font-size: .875rem;--tblr-popover-header-color: inherit;--tblr-popover-header-bg: transparent;--tblr-popover-body-padding-x: .5rem;--tblr-popover-body-padding-y: .5rem;--tblr-popover-body-color: inherit;--tblr-popover-arrow-width: 1rem;--tblr-popover-arrow-height: .5rem;--tblr-popover-arrow-border: var(--tblr-popover-border-color);z-index:var(--tblr-popover-zindex);display:block;max-width:var(--tblr-popover-max-width);font-family:var(--tblr-font-sans-serif);font-style:normal;font-weight:400;line-height:1.4285714286;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--tblr-popover-font-size);word-wrap:break-word;background-color:var(--tblr-popover-bg);background-clip:padding-box;border:var(--tblr-popover-border-width) solid var(--tblr-popover-border-color);border-radius:var(--tblr-popover-border-radius);box-shadow:var(--tblr-popover-box-shadow)}.popover .popover-arrow{display:block;width:var(--tblr-popover-arrow-width);height:var(--tblr-popover-arrow-height)}.popover .popover-arrow:before,.popover .popover-arrow:after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width))}.bs-popover-top>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before,.bs-popover-top>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after{border-width:var(--tblr-popover-arrow-height) calc(var(--tblr-popover-arrow-width) * .5) 0}.bs-popover-top>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before{bottom:0;border-top-color:var(--tblr-popover-arrow-border)}.bs-popover-top>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after{bottom:var(--tblr-popover-border-width);border-top-color:var(--tblr-popover-bg)}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width));width:var(--tblr-popover-arrow-height);height:var(--tblr-popover-arrow-width)}.bs-popover-end>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before,.bs-popover-end>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after{border-width:calc(var(--tblr-popover-arrow-width) * .5) var(--tblr-popover-arrow-height) calc(var(--tblr-popover-arrow-width) * .5) 0}.bs-popover-end>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before{left:0;border-right-color:var(--tblr-popover-arrow-border)}.bs-popover-end>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after{left:var(--tblr-popover-border-width);border-right-color:var(--tblr-popover-bg)}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width))}.bs-popover-bottom>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before,.bs-popover-bottom>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after{border-width:0 calc(var(--tblr-popover-arrow-width) * .5) var(--tblr-popover-arrow-height)}.bs-popover-bottom>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before{top:0;border-bottom-color:var(--tblr-popover-arrow-border)}.bs-popover-bottom>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after{top:var(--tblr-popover-border-width);border-bottom-color:var(--tblr-popover-bg)}.bs-popover-bottom .popover-header:before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header:before{position:absolute;top:0;left:50%;display:block;width:var(--tblr-popover-arrow-width);margin-left:calc(-.5 * var(--tblr-popover-arrow-width));content:"";border-bottom:var(--tblr-popover-border-width) solid var(--tblr-popover-header-bg)}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width));width:var(--tblr-popover-arrow-height);height:var(--tblr-popover-arrow-width)}.bs-popover-start>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before,.bs-popover-start>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after{border-width:calc(var(--tblr-popover-arrow-width) * .5) 0 calc(var(--tblr-popover-arrow-width) * .5) var(--tblr-popover-arrow-height)}.bs-popover-start>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before{right:0;border-left-color:var(--tblr-popover-arrow-border)}.bs-popover-start>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after{right:var(--tblr-popover-border-width);border-left-color:var(--tblr-popover-bg)}.popover-header{padding:var(--tblr-popover-header-padding-y) var(--tblr-popover-header-padding-x);margin-bottom:0;font-size:var(--tblr-popover-header-font-size);color:var(--tblr-popover-header-color);background-color:var(--tblr-popover-header-bg);border-bottom:var(--tblr-popover-border-width) solid var(--tblr-popover-border-color);border-top-left-radius:var(--tblr-popover-inner-border-radius);border-top-right-radius:var(--tblr-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--tblr-popover-body-padding-y) var(--tblr-popover-body-padding-x);color:var(--tblr-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner:after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translate(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translate(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;filter:var(--tblr-carousel-control-icon-filter);border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion:reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:1.5rem;height:1.5rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='15 18 9 12 15 6'%3e%3c/polyline%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='9 18 15 12 9 6'%3e%3c/polyline%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:var(--tblr-carousel-indicator-active-bg);background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:var(--tblr-carousel-caption-color);text-align:center}.carousel-dark{--tblr-carousel-indicator-active-bg: #000000;--tblr-carousel-caption-color: #000000;--tblr-carousel-control-icon-filter: invert(1) grayscale(100)}:root,[data-bs-theme=light]{--tblr-carousel-indicator-active-bg: #ffffff;--tblr-carousel-caption-color: #ffffff;--tblr-carousel-control-icon-filter: }[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{--tblr-carousel-indicator-active-bg: #000000;--tblr-carousel-caption-color: #000000;--tblr-carousel-control-icon-filter: invert(1) grayscale(100)}.spinner-grow,.spinner-border{display:inline-block;flex-shrink:0;width:var(--tblr-spinner-width);height:var(--tblr-spinner-height);vertical-align:var(--tblr-spinner-vertical-align);border-radius:50%;animation:var(--tblr-spinner-animation-speed) linear infinite var(--tblr-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--tblr-spinner-width: 1.5rem;--tblr-spinner-height: 1.5rem;--tblr-spinner-vertical-align: -.125em;--tblr-spinner-border-width: 2px;--tblr-spinner-animation-speed: .75s;--tblr-spinner-animation-name: spinner-border;border:var(--tblr-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--tblr-spinner-width: 1rem;--tblr-spinner-height: 1rem;--tblr-spinner-border-width: 1px}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--tblr-spinner-width: 1.5rem;--tblr-spinner-height: 1.5rem;--tblr-spinner-vertical-align: -.125em;--tblr-spinner-animation-speed: .75s;--tblr-spinner-animation-name: spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--tblr-spinner-width: 1rem;--tblr-spinner-height: 1rem}@media(prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--tblr-spinner-animation-speed: 1.5s}}.offcanvas,.offcanvas-xxl,.offcanvas-xl,.offcanvas-lg,.offcanvas-md,.offcanvas-sm{--tblr-offcanvas-zindex: 1045;--tblr-offcanvas-width: 400px;--tblr-offcanvas-height: 30vh;--tblr-offcanvas-padding-x: 1.5rem;--tblr-offcanvas-padding-y: 1.5rem;--tblr-offcanvas-color: var(--tblr-body-color);--tblr-offcanvas-bg: var(--tblr-bg-surface);--tblr-offcanvas-border-width: var(--tblr-border-width);--tblr-offcanvas-border-color: var(--tblr-border-color);--tblr-offcanvas-box-shadow: var(--tblr-box-shadow-sm);--tblr-offcanvas-transition: transform .3s ease-in-out;--tblr-offcanvas-title-line-height: 1.4285714286}@media(max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:575.98px)and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media(max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.showing,.offcanvas-sm.show:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show{visibility:visible}}@media(min-width:576px){.offcanvas-sm{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:767.98px)and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media(max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.showing,.offcanvas-md.show:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show{visibility:visible}}@media(min-width:768px){.offcanvas-md{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:991.98px)and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media(max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.showing,.offcanvas-lg.show:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show{visibility:visible}}@media(min-width:992px){.offcanvas-lg{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:1199.98px)and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media(max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.showing,.offcanvas-xl.show:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show{visibility:visible}}@media(min-width:1200px){.offcanvas-xl{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:1399.98px)and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media(max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.showing,.offcanvas-xxl.show:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show{visibility:visible}}@media(min-width:1400px){.offcanvas-xxl{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}@media(prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas.showing,.offcanvas.show:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:var(--tblr-gray-800)}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.24}.offcanvas-header{display:flex;align-items:center;padding:var(--tblr-offcanvas-padding-y) var(--tblr-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--tblr-offcanvas-padding-y) * .5) calc(var(--tblr-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--tblr-offcanvas-padding-y));margin-right:calc(-.5 * var(--tblr-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--tblr-offcanvas-padding-y));margin-left:auto}.offcanvas-title{margin-bottom:0;line-height:var(--tblr-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;padding:var(--tblr-offcanvas-padding-y) var(--tblr-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.2}.placeholder.btn:before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.1}}.placeholder-wave{mask-image:linear-gradient(130deg,#000 55%,#000000e6,#000 95%);mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{to{mask-position:-200% 0%}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.object-fit-contain{object-fit:contain!important}.object-fit-cover{object-fit:cover!important}.object-fit-fill{object-fit:fill!important}.object-fit-scale{object-fit:scale-down!important}.object-fit-none{object-fit:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:var(--tblr-box-shadow)!important}.shadow-sm{box-shadow:var(--tblr-box-shadow-sm)!important}.shadow-lg{box-shadow:var(--tblr-box-shadow-lg)!important}.shadow-none{box-shadow:none!important}.focus-ring-primary{--tblr-focus-ring-color: rgba(var(--tblr-primary-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-secondary{--tblr-focus-ring-color: rgba(var(--tblr-secondary-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-success{--tblr-focus-ring-color: rgba(var(--tblr-success-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-info{--tblr-focus-ring-color: rgba(var(--tblr-info-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-warning{--tblr-focus-ring-color: rgba(var(--tblr-warning-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-danger{--tblr-focus-ring-color: rgba(var(--tblr-danger-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-light{--tblr-focus-ring-color: rgba(var(--tblr-light-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-dark{--tblr-focus-ring-color: rgba(var(--tblr-dark-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-muted{--tblr-focus-ring-color: rgba(var(--tblr-muted-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-blue{--tblr-focus-ring-color: rgba(var(--tblr-blue-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-azure{--tblr-focus-ring-color: rgba(var(--tblr-azure-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-indigo{--tblr-focus-ring-color: rgba(var(--tblr-indigo-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-purple{--tblr-focus-ring-color: rgba(var(--tblr-purple-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-pink{--tblr-focus-ring-color: rgba(var(--tblr-pink-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-red{--tblr-focus-ring-color: rgba(var(--tblr-red-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-orange{--tblr-focus-ring-color: rgba(var(--tblr-orange-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-yellow{--tblr-focus-ring-color: rgba(var(--tblr-yellow-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-lime{--tblr-focus-ring-color: rgba(var(--tblr-lime-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-green{--tblr-focus-ring-color: rgba(var(--tblr-green-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-teal{--tblr-focus-ring-color: rgba(var(--tblr-teal-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-cyan{--tblr-focus-ring-color: rgba(var(--tblr-cyan-rgb), var(--tblr-focus-ring-opacity))}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translate(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-wide{border:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-0{border:0!important}.border-top{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-top-wide{border-top:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-end-wide{border-right:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-bottom-wide{border-bottom:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-start-wide{border-left:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-start-0{border-left:0!important}.border-red{--tblr-border-opacity: 1;border-color:rgba(var(--tblr-red-rgb),var(--tblr-border-opacity))!important}.border-green{--tblr-border-opacity: 1;border-color:rgba(var(--tblr-green-rgb),var(--tblr-border-opacity))!important}.border-primary-subtle{border-color:var(--tblr-primary-border-subtle)!important}.border-secondary-subtle{border-color:var(--tblr-secondary-border-subtle)!important}.border-success-subtle{border-color:var(--tblr-success-border-subtle)!important}.border-info-subtle{border-color:var(--tblr-info-border-subtle)!important}.border-warning-subtle{border-color:var(--tblr-warning-border-subtle)!important}.border-danger-subtle{border-color:var(--tblr-danger-border-subtle)!important}.border-light-subtle{border-color:var(--tblr-light-border-subtle)!important}.border-dark-subtle{border-color:var(--tblr-dark-border-subtle)!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.border-opacity-10{--tblr-border-opacity: .1}.border-opacity-25{--tblr-border-opacity: .25}.border-opacity-50{--tblr-border-opacity: .5}.border-opacity-75{--tblr-border-opacity: .75}.border-opacity-100{--tblr-border-opacity: 1}.w-25{width:25%!important}.w-33{width:33.33333%!important}.w-50{width:50%!important}.w-66{width:66.66666%!important}.w-75{width:75%!important}.w-100{width:100%!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-33{height:33.33333%!important}.h-50{height:50%!important}.h-66{height:66.66666%!important}.h-75{height:75%!important}.h-100{height:100%!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:2rem!important}.m-6{margin:2.5rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:2rem!important;margin-left:2rem!important}.mx-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:2rem!important}.mt-6{margin-top:2.5rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:2rem!important}.me-6{margin-right:2.5rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:2rem!important}.mb-6{margin-bottom:2.5rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:2rem!important}.ms-6{margin-left:2.5rem!important}.ms-auto{margin-left:auto!important}.m-n1{margin:-.25rem!important}.m-n2{margin:-.5rem!important}.m-n3{margin:-1rem!important}.m-n4{margin:-1.5rem!important}.m-n5{margin:-2rem!important}.m-n6{margin:-2.5rem!important}.mx-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-n1{margin-top:-.25rem!important}.mt-n2{margin-top:-.5rem!important}.mt-n3{margin-top:-1rem!important}.mt-n4{margin-top:-1.5rem!important}.mt-n5{margin-top:-2rem!important}.mt-n6{margin-top:-2.5rem!important}.me-n1{margin-right:-.25rem!important}.me-n2{margin-right:-.5rem!important}.me-n3{margin-right:-1rem!important}.me-n4{margin-right:-1.5rem!important}.me-n5{margin-right:-2rem!important}.me-n6{margin-right:-2.5rem!important}.mb-n1{margin-bottom:-.25rem!important}.mb-n2{margin-bottom:-.5rem!important}.mb-n3{margin-bottom:-1rem!important}.mb-n4{margin-bottom:-1.5rem!important}.mb-n5{margin-bottom:-2rem!important}.mb-n6{margin-bottom:-2.5rem!important}.ms-n1{margin-left:-.25rem!important}.ms-n2{margin-left:-.5rem!important}.ms-n3{margin-left:-1rem!important}.ms-n4{margin-left:-1.5rem!important}.ms-n5{margin-left:-2rem!important}.ms-n6{margin-left:-2.5rem!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:2rem!important}.p-6{padding:2.5rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:2rem!important;padding-left:2rem!important}.px-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:2rem!important}.pt-6{padding-top:2.5rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:2rem!important}.pe-6{padding-right:2.5rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:2rem!important}.pb-6{padding-bottom:2.5rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:2rem!important}.ps-6{padding-left:2.5rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:2rem!important}.gap-6{gap:2.5rem!important}.row-gap-0{row-gap:0!important}.row-gap-1{row-gap:.25rem!important}.row-gap-2{row-gap:.5rem!important}.row-gap-3{row-gap:1rem!important}.row-gap-4{row-gap:1.5rem!important}.row-gap-5{row-gap:2rem!important}.row-gap-6{row-gap:2.5rem!important}.column-gap-0{column-gap:0!important}.column-gap-1{column-gap:.25rem!important}.column-gap-2{column-gap:.5rem!important}.column-gap-3{column-gap:1rem!important}.column-gap-4{column-gap:1.5rem!important}.column-gap-5{column-gap:2rem!important}.column-gap-6{column-gap:2.5rem!important}.font-monospace{font-family:var(--tblr-font-monospace)!important}.fs-1{font-size:1.5rem!important}.fs-2{font-size:1.25rem!important}.fs-3{font-size:1rem!important}.fs-4{font-size:.875rem!important}.fs-5{font-size:.75rem!important}.fs-6{font-size:.625rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-lighter{font-weight:lighter!important}.fw-light{font-weight:300!important}.fw-normal{font-weight:400!important}.fw-medium{font-weight:500!important}.fw-semibold,.fw-bold{font-weight:600!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.1428571429!important}.lh-base{line-height:1.4285714286!important}.lh-lg{line-height:1.7142857143!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--tblr-text-opacity: 1;color:rgba(var(--tblr-primary-rgb),var(--tblr-text-opacity))!important}.text-secondary{--tblr-text-opacity: 1;color:rgba(var(--tblr-secondary-rgb),var(--tblr-text-opacity))!important}.text-success{--tblr-text-opacity: 1;color:rgba(var(--tblr-success-rgb),var(--tblr-text-opacity))!important}.text-info{--tblr-text-opacity: 1;color:rgba(var(--tblr-info-rgb),var(--tblr-text-opacity))!important}.text-warning{--tblr-text-opacity: 1;color:rgba(var(--tblr-warning-rgb),var(--tblr-text-opacity))!important}.text-danger{--tblr-text-opacity: 1;color:rgba(var(--tblr-danger-rgb),var(--tblr-text-opacity))!important}.text-light{--tblr-text-opacity: 1;color:rgba(var(--tblr-light-rgb),var(--tblr-text-opacity))!important}.text-dark{--tblr-text-opacity: 1;color:rgba(var(--tblr-dark-rgb),var(--tblr-text-opacity))!important}.text-muted{--tblr-text-opacity: 1;color:var(--tblr-secondary-color)!important}.text-blue{--tblr-text-opacity: 1;color:rgba(var(--tblr-blue-rgb),var(--tblr-text-opacity))!important}.text-azure{--tblr-text-opacity: 1;color:rgba(var(--tblr-azure-rgb),var(--tblr-text-opacity))!important}.text-indigo{--tblr-text-opacity: 1;color:rgba(var(--tblr-indigo-rgb),var(--tblr-text-opacity))!important}.text-purple{--tblr-text-opacity: 1;color:rgba(var(--tblr-purple-rgb),var(--tblr-text-opacity))!important}.text-pink{--tblr-text-opacity: 1;color:rgba(var(--tblr-pink-rgb),var(--tblr-text-opacity))!important}.text-red{--tblr-text-opacity: 1;color:rgba(var(--tblr-red-rgb),var(--tblr-text-opacity))!important}.text-orange{--tblr-text-opacity: 1;color:rgba(var(--tblr-orange-rgb),var(--tblr-text-opacity))!important}.text-yellow{--tblr-text-opacity: 1;color:rgba(var(--tblr-yellow-rgb),var(--tblr-text-opacity))!important}.text-lime{--tblr-text-opacity: 1;color:rgba(var(--tblr-lime-rgb),var(--tblr-text-opacity))!important}.text-green{--tblr-text-opacity: 1;color:rgba(var(--tblr-green-rgb),var(--tblr-text-opacity))!important}.text-teal{--tblr-text-opacity: 1;color:rgba(var(--tblr-teal-rgb),var(--tblr-text-opacity))!important}.text-cyan{--tblr-text-opacity: 1;color:rgba(var(--tblr-cyan-rgb),var(--tblr-text-opacity))!important}.text-black{--tblr-text-opacity: 1;color:rgba(var(--tblr-black-rgb),var(--tblr-text-opacity))!important}.text-white{--tblr-text-opacity: 1;color:rgba(var(--tblr-white-rgb),var(--tblr-text-opacity))!important}.text-body{--tblr-text-opacity: 1;color:rgba(var(--tblr-body-color-rgb),var(--tblr-text-opacity))!important}.text-black-50{--tblr-text-opacity: 1;color:#00000080!important}.text-white-50{--tblr-text-opacity: 1;color:#ffffff80!important}.text-body-secondary{--tblr-text-opacity: 1;color:var(--tblr-secondary-color)!important}.text-body-tertiary{--tblr-text-opacity: 1;color:var(--tblr-tertiary-color)!important}.text-body-emphasis{--tblr-text-opacity: 1;color:var(--tblr-emphasis-color)!important}.text-reset{--tblr-text-opacity: 1;color:inherit!important}.text-opacity-25{--tblr-text-opacity: .25}.text-opacity-50{--tblr-text-opacity: .5}.text-opacity-75{--tblr-text-opacity: .75}.text-opacity-100{--tblr-text-opacity: 1}.text-primary-emphasis{color:var(--tblr-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--tblr-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--tblr-success-text-emphasis)!important}.text-info-emphasis{color:var(--tblr-info-text-emphasis)!important}.text-warning-emphasis{color:var(--tblr-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--tblr-danger-text-emphasis)!important}.text-light-emphasis{color:var(--tblr-light-text-emphasis)!important}.text-dark-emphasis{color:var(--tblr-dark-text-emphasis)!important}.link-opacity-10,.link-opacity-10-hover:hover{--tblr-link-opacity: .1}.link-opacity-25,.link-opacity-25-hover:hover{--tblr-link-opacity: .25}.link-opacity-50,.link-opacity-50-hover:hover{--tblr-link-opacity: .5}.link-opacity-75,.link-opacity-75-hover:hover{--tblr-link-opacity: .75}.link-opacity-100,.link-opacity-100-hover:hover{--tblr-link-opacity: 1}.link-offset-1,.link-offset-1-hover:hover{text-underline-offset:.125em!important}.link-offset-2,.link-offset-2-hover:hover{text-underline-offset:.25em!important}.link-offset-3,.link-offset-3-hover:hover{text-underline-offset:.375em!important}.link-underline-primary{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-primary-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-secondary{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-secondary-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-success{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-success-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-info{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-info-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-warning{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-warning-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-danger{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-danger-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-light{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-light-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-dark{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-dark-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-muted{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-muted-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-blue{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-blue-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-azure{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-azure-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-indigo{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-indigo-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-purple{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-purple-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-pink{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-pink-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-red{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-red-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-orange{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-orange-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-yellow{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-yellow-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-lime{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-lime-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-green{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-green-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-teal{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-teal-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-cyan{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-cyan-rgb),var(--tblr-link-underline-opacity))!important}.link-underline{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-link-color-rgb),var(--tblr-link-underline-opacity, 1))!important}.link-underline-opacity-0,.link-underline-opacity-0-hover:hover{--tblr-link-underline-opacity: 0}.link-underline-opacity-10,.link-underline-opacity-10-hover:hover{--tblr-link-underline-opacity: .1}.link-underline-opacity-25,.link-underline-opacity-25-hover:hover{--tblr-link-underline-opacity: .25}.link-underline-opacity-50,.link-underline-opacity-50-hover:hover{--tblr-link-underline-opacity: .5}.link-underline-opacity-75,.link-underline-opacity-75-hover:hover{--tblr-link-underline-opacity: .75}.link-underline-opacity-100,.link-underline-opacity-100-hover:hover{--tblr-link-underline-opacity: 1}.bg-primary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-primary-rgb),var(--tblr-bg-opacity))!important}.bg-secondary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-secondary-rgb),var(--tblr-bg-opacity))!important}.bg-success{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-success-rgb),var(--tblr-bg-opacity))!important}.bg-info{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-info-rgb),var(--tblr-bg-opacity))!important}.bg-warning{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-warning-rgb),var(--tblr-bg-opacity))!important}.bg-danger{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-danger-rgb),var(--tblr-bg-opacity))!important}.bg-light{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-light-rgb),var(--tblr-bg-opacity))!important}.bg-dark{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-dark-rgb),var(--tblr-bg-opacity))!important}.bg-muted{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-muted-rgb),var(--tblr-bg-opacity))!important}.bg-blue{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-blue-rgb),var(--tblr-bg-opacity))!important}.bg-azure{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-azure-rgb),var(--tblr-bg-opacity))!important}.bg-indigo{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-indigo-rgb),var(--tblr-bg-opacity))!important}.bg-purple{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-purple-rgb),var(--tblr-bg-opacity))!important}.bg-pink{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-pink-rgb),var(--tblr-bg-opacity))!important}.bg-red{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-red-rgb),var(--tblr-bg-opacity))!important}.bg-orange{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-orange-rgb),var(--tblr-bg-opacity))!important}.bg-yellow{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-yellow-rgb),var(--tblr-bg-opacity))!important}.bg-lime{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-lime-rgb),var(--tblr-bg-opacity))!important}.bg-green{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-green-rgb),var(--tblr-bg-opacity))!important}.bg-teal{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-teal-rgb),var(--tblr-bg-opacity))!important}.bg-cyan{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-cyan-rgb),var(--tblr-bg-opacity))!important}.bg-black{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-black-rgb),var(--tblr-bg-opacity))!important}.bg-white{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-white-rgb),var(--tblr-bg-opacity))!important}.bg-body{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-body-bg-rgb),var(--tblr-bg-opacity))!important}.bg-transparent{--tblr-bg-opacity: 1;background-color:transparent!important}.bg-body-secondary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-secondary-bg-rgb),var(--tblr-bg-opacity))!important}.bg-body-tertiary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-tertiary-bg-rgb),var(--tblr-bg-opacity))!important}.bg-opacity-10{--tblr-bg-opacity: .1}.bg-opacity-25{--tblr-bg-opacity: .25}.bg-opacity-50{--tblr-bg-opacity: .5}.bg-opacity-75{--tblr-bg-opacity: .75}.bg-opacity-100{--tblr-bg-opacity: 1}.bg-primary-subtle{background-color:var(--tblr-primary-bg-subtle)!important}.bg-secondary-subtle{background-color:var(--tblr-secondary-bg-subtle)!important}.bg-success-subtle{background-color:var(--tblr-success-bg-subtle)!important}.bg-info-subtle{background-color:var(--tblr-info-bg-subtle)!important}.bg-warning-subtle{background-color:var(--tblr-warning-bg-subtle)!important}.bg-danger-subtle{background-color:var(--tblr-danger-bg-subtle)!important}.bg-light-subtle{background-color:var(--tblr-light-bg-subtle)!important}.bg-dark-subtle{background-color:var(--tblr-dark-bg-subtle)!important}.bg-gradient{background-image:var(--tblr-gradient)!important}.user-select-all{user-select:all!important}.user-select-auto{user-select:auto!important}.user-select-none{user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--tblr-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--tblr-border-radius-sm)!important}.rounded-2{border-radius:var(--tblr-border-radius)!important}.rounded-3{border-radius:var(--tblr-border-radius-lg)!important}.rounded-4{border-radius:var(--tblr-border-radius-xl)!important}.rounded-5{border-radius:var(--tblr-border-radius-xxl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--tblr-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--tblr-border-radius)!important;border-top-right-radius:var(--tblr-border-radius)!important}.rounded-top-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-top-1{border-top-left-radius:var(--tblr-border-radius-sm)!important;border-top-right-radius:var(--tblr-border-radius-sm)!important}.rounded-top-2{border-top-left-radius:var(--tblr-border-radius)!important;border-top-right-radius:var(--tblr-border-radius)!important}.rounded-top-3{border-top-left-radius:var(--tblr-border-radius-lg)!important;border-top-right-radius:var(--tblr-border-radius-lg)!important}.rounded-top-4{border-top-left-radius:var(--tblr-border-radius-xl)!important;border-top-right-radius:var(--tblr-border-radius-xl)!important}.rounded-top-5{border-top-left-radius:var(--tblr-border-radius-xxl)!important;border-top-right-radius:var(--tblr-border-radius-xxl)!important}.rounded-top-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-top-pill{border-top-left-radius:var(--tblr-border-radius-pill)!important;border-top-right-radius:var(--tblr-border-radius-pill)!important}.rounded-end{border-top-right-radius:var(--tblr-border-radius)!important;border-bottom-right-radius:var(--tblr-border-radius)!important}.rounded-end-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-end-1{border-top-right-radius:var(--tblr-border-radius-sm)!important;border-bottom-right-radius:var(--tblr-border-radius-sm)!important}.rounded-end-2{border-top-right-radius:var(--tblr-border-radius)!important;border-bottom-right-radius:var(--tblr-border-radius)!important}.rounded-end-3{border-top-right-radius:var(--tblr-border-radius-lg)!important;border-bottom-right-radius:var(--tblr-border-radius-lg)!important}.rounded-end-4{border-top-right-radius:var(--tblr-border-radius-xl)!important;border-bottom-right-radius:var(--tblr-border-radius-xl)!important}.rounded-end-5{border-top-right-radius:var(--tblr-border-radius-xxl)!important;border-bottom-right-radius:var(--tblr-border-radius-xxl)!important}.rounded-end-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-end-pill{border-top-right-radius:var(--tblr-border-radius-pill)!important;border-bottom-right-radius:var(--tblr-border-radius-pill)!important}.rounded-bottom{border-bottom-right-radius:var(--tblr-border-radius)!important;border-bottom-left-radius:var(--tblr-border-radius)!important}.rounded-bottom-0{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-bottom-1{border-bottom-right-radius:var(--tblr-border-radius-sm)!important;border-bottom-left-radius:var(--tblr-border-radius-sm)!important}.rounded-bottom-2{border-bottom-right-radius:var(--tblr-border-radius)!important;border-bottom-left-radius:var(--tblr-border-radius)!important}.rounded-bottom-3{border-bottom-right-radius:var(--tblr-border-radius-lg)!important;border-bottom-left-radius:var(--tblr-border-radius-lg)!important}.rounded-bottom-4{border-bottom-right-radius:var(--tblr-border-radius-xl)!important;border-bottom-left-radius:var(--tblr-border-radius-xl)!important}.rounded-bottom-5{border-bottom-right-radius:var(--tblr-border-radius-xxl)!important;border-bottom-left-radius:var(--tblr-border-radius-xxl)!important}.rounded-bottom-circle{border-bottom-right-radius:50%!important;border-bottom-left-radius:50%!important}.rounded-bottom-pill{border-bottom-right-radius:var(--tblr-border-radius-pill)!important;border-bottom-left-radius:var(--tblr-border-radius-pill)!important}.rounded-start{border-bottom-left-radius:var(--tblr-border-radius)!important;border-top-left-radius:var(--tblr-border-radius)!important}.rounded-start-0{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.rounded-start-1{border-bottom-left-radius:var(--tblr-border-radius-sm)!important;border-top-left-radius:var(--tblr-border-radius-sm)!important}.rounded-start-2{border-bottom-left-radius:var(--tblr-border-radius)!important;border-top-left-radius:var(--tblr-border-radius)!important}.rounded-start-3{border-bottom-left-radius:var(--tblr-border-radius-lg)!important;border-top-left-radius:var(--tblr-border-radius-lg)!important}.rounded-start-4{border-bottom-left-radius:var(--tblr-border-radius-xl)!important;border-top-left-radius:var(--tblr-border-radius-xl)!important}.rounded-start-5{border-bottom-left-radius:var(--tblr-border-radius-xxl)!important;border-top-left-radius:var(--tblr-border-radius-xxl)!important}.rounded-start-circle{border-bottom-left-radius:50%!important;border-top-left-radius:50%!important}.rounded-start-pill{border-bottom-left-radius:var(--tblr-border-radius-pill)!important;border-top-left-radius:var(--tblr-border-radius-pill)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-n1{z-index:-1!important}.z-0{z-index:0!important}.z-1{z-index:1!important}.z-2{z-index:2!important}.z-3{z-index:3!important}.object-contain{object-fit:contain!important}.object-cover{object-fit:cover!important}.object-fill{object-fit:fill!important}.object-scale-down{object-fit:scale-down!important}.object-none{object-fit:none!important}.cursor-auto{cursor:auto!important}.cursor-pointer{cursor:pointer!important}.cursor-move{cursor:move!important}.cursor-not-allowed{cursor:not-allowed!important}.cursor-zoom-in{cursor:zoom-in!important}.cursor-zoom-out{cursor:zoom-out!important}.cursor-default{cursor:default!important}.cursor-none{cursor:none!important}.cursor-help{cursor:help!important}.cursor-progress{cursor:progress!important}.cursor-wait{cursor:wait!important}.cursor-text{cursor:text!important}.cursor-v-text{cursor:vertical-text!important}.cursor-grab{cursor:grab!important}.cursor-grabbing{cursor:grabbing!important}.cursor-crosshair{cursor:crosshair!important}.border-x{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-right:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-x-wide{border-left:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-right:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-x-0{border-left:0!important;border-right:0!important}.border-y{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-y-wide{border-top:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-bottom:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-y-0{border-top:0!important;border-bottom:0!important}.columns-2{columns:2!important}.columns-3{columns:3!important}.columns-4{columns:4!important}.bg-pattern-transparent{background:url('data:image/svg+xml;charset=UTF-8,') repeat center/16px 16px!important}.bg-gradient{background:linear-gradient(var(--tblr-gradient-direction, to right),var(--tblr-gradient-stops, var(--tblr-gradient-from, transparent), var(--tblr-gradient-to, transparent))) no-repeat!important}.bg-gradient-to-t{--tblr-gradient-direction: to top !important}.bg-gradient-to-te{--tblr-gradient-direction: to top right !important}.bg-gradient-to-e{--tblr-gradient-direction: to right !important}.bg-gradient-to-be{--tblr-gradient-direction: to bottom right !important}.bg-gradient-to-b{--tblr-gradient-direction: to bottom !important}.bg-gradient-to-bs{--tblr-gradient-direction: to bottom left !important}.bg-gradient-to-s{--tblr-gradient-direction: to left !important}.bg-gradient-to-ts{--tblr-gradient-direction: to top left !important}.table-auto{table-layout:auto!important}.table-fixed{table-layout:fixed!important}@media(min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.object-fit-sm-contain{object-fit:contain!important}.object-fit-sm-cover{object-fit:cover!important}.object-fit-sm-fill{object-fit:fill!important}.object-fit-sm-scale{object-fit:scale-down!important}.object-fit-sm-none{object-fit:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-inline-grid{display:inline-grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:2rem!important}.m-sm-6{margin:2.5rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:2rem!important;margin-left:2rem!important}.mx-sm-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-sm-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:2rem!important}.mt-sm-6{margin-top:2.5rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:2rem!important}.me-sm-6{margin-right:2.5rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:2rem!important}.mb-sm-6{margin-bottom:2.5rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:2rem!important}.ms-sm-6{margin-left:2.5rem!important}.ms-sm-auto{margin-left:auto!important}.m-sm-n1{margin:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.m-sm-n3{margin:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.m-sm-n5{margin:-2rem!important}.m-sm-n6{margin:-2.5rem!important}.mx-sm-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-sm-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-sm-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-sm-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-sm-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-sm-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-sm-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-sm-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-sm-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-sm-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-sm-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-sm-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-sm-n1{margin-top:-.25rem!important}.mt-sm-n2{margin-top:-.5rem!important}.mt-sm-n3{margin-top:-1rem!important}.mt-sm-n4{margin-top:-1.5rem!important}.mt-sm-n5{margin-top:-2rem!important}.mt-sm-n6{margin-top:-2.5rem!important}.me-sm-n1{margin-right:-.25rem!important}.me-sm-n2{margin-right:-.5rem!important}.me-sm-n3{margin-right:-1rem!important}.me-sm-n4{margin-right:-1.5rem!important}.me-sm-n5{margin-right:-2rem!important}.me-sm-n6{margin-right:-2.5rem!important}.mb-sm-n1{margin-bottom:-.25rem!important}.mb-sm-n2{margin-bottom:-.5rem!important}.mb-sm-n3{margin-bottom:-1rem!important}.mb-sm-n4{margin-bottom:-1.5rem!important}.mb-sm-n5{margin-bottom:-2rem!important}.mb-sm-n6{margin-bottom:-2.5rem!important}.ms-sm-n1{margin-left:-.25rem!important}.ms-sm-n2{margin-left:-.5rem!important}.ms-sm-n3{margin-left:-1rem!important}.ms-sm-n4{margin-left:-1.5rem!important}.ms-sm-n5{margin-left:-2rem!important}.ms-sm-n6{margin-left:-2.5rem!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:2rem!important}.p-sm-6{padding:2.5rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:2rem!important;padding-left:2rem!important}.px-sm-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-sm-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:2rem!important}.pt-sm-6{padding-top:2.5rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:2rem!important}.pe-sm-6{padding-right:2.5rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:2rem!important}.pb-sm-6{padding-bottom:2.5rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:2rem!important}.ps-sm-6{padding-left:2.5rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:2rem!important}.gap-sm-6{gap:2.5rem!important}.row-gap-sm-0{row-gap:0!important}.row-gap-sm-1{row-gap:.25rem!important}.row-gap-sm-2{row-gap:.5rem!important}.row-gap-sm-3{row-gap:1rem!important}.row-gap-sm-4{row-gap:1.5rem!important}.row-gap-sm-5{row-gap:2rem!important}.row-gap-sm-6{row-gap:2.5rem!important}.column-gap-sm-0{column-gap:0!important}.column-gap-sm-1{column-gap:.25rem!important}.column-gap-sm-2{column-gap:.5rem!important}.column-gap-sm-3{column-gap:1rem!important}.column-gap-sm-4{column-gap:1.5rem!important}.column-gap-sm-5{column-gap:2rem!important}.column-gap-sm-6{column-gap:2.5rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}.columns-sm-2{columns:2!important}.columns-sm-3{columns:3!important}.columns-sm-4{columns:4!important}}@media(min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.object-fit-md-contain{object-fit:contain!important}.object-fit-md-cover{object-fit:cover!important}.object-fit-md-fill{object-fit:fill!important}.object-fit-md-scale{object-fit:scale-down!important}.object-fit-md-none{object-fit:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-inline-grid{display:inline-grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:2rem!important}.m-md-6{margin:2.5rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:2rem!important;margin-left:2rem!important}.mx-md-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-md-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:2rem!important}.mt-md-6{margin-top:2.5rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:2rem!important}.me-md-6{margin-right:2.5rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:2rem!important}.mb-md-6{margin-bottom:2.5rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:2rem!important}.ms-md-6{margin-left:2.5rem!important}.ms-md-auto{margin-left:auto!important}.m-md-n1{margin:-.25rem!important}.m-md-n2{margin:-.5rem!important}.m-md-n3{margin:-1rem!important}.m-md-n4{margin:-1.5rem!important}.m-md-n5{margin:-2rem!important}.m-md-n6{margin:-2.5rem!important}.mx-md-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-md-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-md-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-md-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-md-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-md-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-md-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-md-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-md-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-md-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-md-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-md-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-md-n1{margin-top:-.25rem!important}.mt-md-n2{margin-top:-.5rem!important}.mt-md-n3{margin-top:-1rem!important}.mt-md-n4{margin-top:-1.5rem!important}.mt-md-n5{margin-top:-2rem!important}.mt-md-n6{margin-top:-2.5rem!important}.me-md-n1{margin-right:-.25rem!important}.me-md-n2{margin-right:-.5rem!important}.me-md-n3{margin-right:-1rem!important}.me-md-n4{margin-right:-1.5rem!important}.me-md-n5{margin-right:-2rem!important}.me-md-n6{margin-right:-2.5rem!important}.mb-md-n1{margin-bottom:-.25rem!important}.mb-md-n2{margin-bottom:-.5rem!important}.mb-md-n3{margin-bottom:-1rem!important}.mb-md-n4{margin-bottom:-1.5rem!important}.mb-md-n5{margin-bottom:-2rem!important}.mb-md-n6{margin-bottom:-2.5rem!important}.ms-md-n1{margin-left:-.25rem!important}.ms-md-n2{margin-left:-.5rem!important}.ms-md-n3{margin-left:-1rem!important}.ms-md-n4{margin-left:-1.5rem!important}.ms-md-n5{margin-left:-2rem!important}.ms-md-n6{margin-left:-2.5rem!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:2rem!important}.p-md-6{padding:2.5rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:2rem!important;padding-left:2rem!important}.px-md-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-md-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:2rem!important}.pt-md-6{padding-top:2.5rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:2rem!important}.pe-md-6{padding-right:2.5rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:2rem!important}.pb-md-6{padding-bottom:2.5rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:2rem!important}.ps-md-6{padding-left:2.5rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:2rem!important}.gap-md-6{gap:2.5rem!important}.row-gap-md-0{row-gap:0!important}.row-gap-md-1{row-gap:.25rem!important}.row-gap-md-2{row-gap:.5rem!important}.row-gap-md-3{row-gap:1rem!important}.row-gap-md-4{row-gap:1.5rem!important}.row-gap-md-5{row-gap:2rem!important}.row-gap-md-6{row-gap:2.5rem!important}.column-gap-md-0{column-gap:0!important}.column-gap-md-1{column-gap:.25rem!important}.column-gap-md-2{column-gap:.5rem!important}.column-gap-md-3{column-gap:1rem!important}.column-gap-md-4{column-gap:1.5rem!important}.column-gap-md-5{column-gap:2rem!important}.column-gap-md-6{column-gap:2.5rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}.columns-md-2{columns:2!important}.columns-md-3{columns:3!important}.columns-md-4{columns:4!important}}@media(min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.object-fit-lg-contain{object-fit:contain!important}.object-fit-lg-cover{object-fit:cover!important}.object-fit-lg-fill{object-fit:fill!important}.object-fit-lg-scale{object-fit:scale-down!important}.object-fit-lg-none{object-fit:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-inline-grid{display:inline-grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:2rem!important}.m-lg-6{margin:2.5rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:2rem!important;margin-left:2rem!important}.mx-lg-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-lg-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:2rem!important}.mt-lg-6{margin-top:2.5rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:2rem!important}.me-lg-6{margin-right:2.5rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:2rem!important}.mb-lg-6{margin-bottom:2.5rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:2rem!important}.ms-lg-6{margin-left:2.5rem!important}.ms-lg-auto{margin-left:auto!important}.m-lg-n1{margin:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.m-lg-n3{margin:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.m-lg-n5{margin:-2rem!important}.m-lg-n6{margin:-2.5rem!important}.mx-lg-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-lg-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-lg-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-lg-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-lg-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-lg-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-lg-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-lg-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-lg-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-lg-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-lg-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-lg-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-lg-n1{margin-top:-.25rem!important}.mt-lg-n2{margin-top:-.5rem!important}.mt-lg-n3{margin-top:-1rem!important}.mt-lg-n4{margin-top:-1.5rem!important}.mt-lg-n5{margin-top:-2rem!important}.mt-lg-n6{margin-top:-2.5rem!important}.me-lg-n1{margin-right:-.25rem!important}.me-lg-n2{margin-right:-.5rem!important}.me-lg-n3{margin-right:-1rem!important}.me-lg-n4{margin-right:-1.5rem!important}.me-lg-n5{margin-right:-2rem!important}.me-lg-n6{margin-right:-2.5rem!important}.mb-lg-n1{margin-bottom:-.25rem!important}.mb-lg-n2{margin-bottom:-.5rem!important}.mb-lg-n3{margin-bottom:-1rem!important}.mb-lg-n4{margin-bottom:-1.5rem!important}.mb-lg-n5{margin-bottom:-2rem!important}.mb-lg-n6{margin-bottom:-2.5rem!important}.ms-lg-n1{margin-left:-.25rem!important}.ms-lg-n2{margin-left:-.5rem!important}.ms-lg-n3{margin-left:-1rem!important}.ms-lg-n4{margin-left:-1.5rem!important}.ms-lg-n5{margin-left:-2rem!important}.ms-lg-n6{margin-left:-2.5rem!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:2rem!important}.p-lg-6{padding:2.5rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:2rem!important;padding-left:2rem!important}.px-lg-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-lg-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:2rem!important}.pt-lg-6{padding-top:2.5rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:2rem!important}.pe-lg-6{padding-right:2.5rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:2rem!important}.pb-lg-6{padding-bottom:2.5rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:2rem!important}.ps-lg-6{padding-left:2.5rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:2rem!important}.gap-lg-6{gap:2.5rem!important}.row-gap-lg-0{row-gap:0!important}.row-gap-lg-1{row-gap:.25rem!important}.row-gap-lg-2{row-gap:.5rem!important}.row-gap-lg-3{row-gap:1rem!important}.row-gap-lg-4{row-gap:1.5rem!important}.row-gap-lg-5{row-gap:2rem!important}.row-gap-lg-6{row-gap:2.5rem!important}.column-gap-lg-0{column-gap:0!important}.column-gap-lg-1{column-gap:.25rem!important}.column-gap-lg-2{column-gap:.5rem!important}.column-gap-lg-3{column-gap:1rem!important}.column-gap-lg-4{column-gap:1.5rem!important}.column-gap-lg-5{column-gap:2rem!important}.column-gap-lg-6{column-gap:2.5rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}.columns-lg-2{columns:2!important}.columns-lg-3{columns:3!important}.columns-lg-4{columns:4!important}}@media(min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.object-fit-xl-contain{object-fit:contain!important}.object-fit-xl-cover{object-fit:cover!important}.object-fit-xl-fill{object-fit:fill!important}.object-fit-xl-scale{object-fit:scale-down!important}.object-fit-xl-none{object-fit:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-inline-grid{display:inline-grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:2rem!important}.m-xl-6{margin:2.5rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:2rem!important;margin-left:2rem!important}.mx-xl-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-xl-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:2rem!important}.mt-xl-6{margin-top:2.5rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:2rem!important}.me-xl-6{margin-right:2.5rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:2rem!important}.mb-xl-6{margin-bottom:2.5rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:2rem!important}.ms-xl-6{margin-left:2.5rem!important}.ms-xl-auto{margin-left:auto!important}.m-xl-n1{margin:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.m-xl-n3{margin:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.m-xl-n5{margin:-2rem!important}.m-xl-n6{margin:-2.5rem!important}.mx-xl-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-xl-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-xl-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-xl-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-xl-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-xl-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-xl-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-xl-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-xl-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-xl-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-xl-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-xl-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-xl-n1{margin-top:-.25rem!important}.mt-xl-n2{margin-top:-.5rem!important}.mt-xl-n3{margin-top:-1rem!important}.mt-xl-n4{margin-top:-1.5rem!important}.mt-xl-n5{margin-top:-2rem!important}.mt-xl-n6{margin-top:-2.5rem!important}.me-xl-n1{margin-right:-.25rem!important}.me-xl-n2{margin-right:-.5rem!important}.me-xl-n3{margin-right:-1rem!important}.me-xl-n4{margin-right:-1.5rem!important}.me-xl-n5{margin-right:-2rem!important}.me-xl-n6{margin-right:-2.5rem!important}.mb-xl-n1{margin-bottom:-.25rem!important}.mb-xl-n2{margin-bottom:-.5rem!important}.mb-xl-n3{margin-bottom:-1rem!important}.mb-xl-n4{margin-bottom:-1.5rem!important}.mb-xl-n5{margin-bottom:-2rem!important}.mb-xl-n6{margin-bottom:-2.5rem!important}.ms-xl-n1{margin-left:-.25rem!important}.ms-xl-n2{margin-left:-.5rem!important}.ms-xl-n3{margin-left:-1rem!important}.ms-xl-n4{margin-left:-1.5rem!important}.ms-xl-n5{margin-left:-2rem!important}.ms-xl-n6{margin-left:-2.5rem!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:2rem!important}.p-xl-6{padding:2.5rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:2rem!important;padding-left:2rem!important}.px-xl-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-xl-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:2rem!important}.pt-xl-6{padding-top:2.5rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:2rem!important}.pe-xl-6{padding-right:2.5rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:2rem!important}.pb-xl-6{padding-bottom:2.5rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:2rem!important}.ps-xl-6{padding-left:2.5rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:2rem!important}.gap-xl-6{gap:2.5rem!important}.row-gap-xl-0{row-gap:0!important}.row-gap-xl-1{row-gap:.25rem!important}.row-gap-xl-2{row-gap:.5rem!important}.row-gap-xl-3{row-gap:1rem!important}.row-gap-xl-4{row-gap:1.5rem!important}.row-gap-xl-5{row-gap:2rem!important}.row-gap-xl-6{row-gap:2.5rem!important}.column-gap-xl-0{column-gap:0!important}.column-gap-xl-1{column-gap:.25rem!important}.column-gap-xl-2{column-gap:.5rem!important}.column-gap-xl-3{column-gap:1rem!important}.column-gap-xl-4{column-gap:1.5rem!important}.column-gap-xl-5{column-gap:2rem!important}.column-gap-xl-6{column-gap:2.5rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}.columns-xl-2{columns:2!important}.columns-xl-3{columns:3!important}.columns-xl-4{columns:4!important}}@media(min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.object-fit-xxl-contain{object-fit:contain!important}.object-fit-xxl-cover{object-fit:cover!important}.object-fit-xxl-fill{object-fit:fill!important}.object-fit-xxl-scale{object-fit:scale-down!important}.object-fit-xxl-none{object-fit:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-inline-grid{display:inline-grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:2rem!important}.m-xxl-6{margin:2.5rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:2rem!important;margin-left:2rem!important}.mx-xxl-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-xxl-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:2rem!important}.mt-xxl-6{margin-top:2.5rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:2rem!important}.me-xxl-6{margin-right:2.5rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:2rem!important}.mb-xxl-6{margin-bottom:2.5rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:2rem!important}.ms-xxl-6{margin-left:2.5rem!important}.ms-xxl-auto{margin-left:auto!important}.m-xxl-n1{margin:-.25rem!important}.m-xxl-n2{margin:-.5rem!important}.m-xxl-n3{margin:-1rem!important}.m-xxl-n4{margin:-1.5rem!important}.m-xxl-n5{margin:-2rem!important}.m-xxl-n6{margin:-2.5rem!important}.mx-xxl-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-xxl-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-xxl-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-xxl-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-xxl-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-xxl-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-xxl-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-xxl-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-xxl-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-xxl-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-xxl-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-xxl-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-xxl-n1{margin-top:-.25rem!important}.mt-xxl-n2{margin-top:-.5rem!important}.mt-xxl-n3{margin-top:-1rem!important}.mt-xxl-n4{margin-top:-1.5rem!important}.mt-xxl-n5{margin-top:-2rem!important}.mt-xxl-n6{margin-top:-2.5rem!important}.me-xxl-n1{margin-right:-.25rem!important}.me-xxl-n2{margin-right:-.5rem!important}.me-xxl-n3{margin-right:-1rem!important}.me-xxl-n4{margin-right:-1.5rem!important}.me-xxl-n5{margin-right:-2rem!important}.me-xxl-n6{margin-right:-2.5rem!important}.mb-xxl-n1{margin-bottom:-.25rem!important}.mb-xxl-n2{margin-bottom:-.5rem!important}.mb-xxl-n3{margin-bottom:-1rem!important}.mb-xxl-n4{margin-bottom:-1.5rem!important}.mb-xxl-n5{margin-bottom:-2rem!important}.mb-xxl-n6{margin-bottom:-2.5rem!important}.ms-xxl-n1{margin-left:-.25rem!important}.ms-xxl-n2{margin-left:-.5rem!important}.ms-xxl-n3{margin-left:-1rem!important}.ms-xxl-n4{margin-left:-1.5rem!important}.ms-xxl-n5{margin-left:-2rem!important}.ms-xxl-n6{margin-left:-2.5rem!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:2rem!important}.p-xxl-6{padding:2.5rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:2rem!important;padding-left:2rem!important}.px-xxl-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-xxl-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:2rem!important}.pt-xxl-6{padding-top:2.5rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:2rem!important}.pe-xxl-6{padding-right:2.5rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:2rem!important}.pb-xxl-6{padding-bottom:2.5rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:2rem!important}.ps-xxl-6{padding-left:2.5rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:2rem!important}.gap-xxl-6{gap:2.5rem!important}.row-gap-xxl-0{row-gap:0!important}.row-gap-xxl-1{row-gap:.25rem!important}.row-gap-xxl-2{row-gap:.5rem!important}.row-gap-xxl-3{row-gap:1rem!important}.row-gap-xxl-4{row-gap:1.5rem!important}.row-gap-xxl-5{row-gap:2rem!important}.row-gap-xxl-6{row-gap:2.5rem!important}.column-gap-xxl-0{column-gap:0!important}.column-gap-xxl-1{column-gap:.25rem!important}.column-gap-xxl-2{column-gap:.5rem!important}.column-gap-xxl-3{column-gap:1rem!important}.column-gap-xxl-4{column-gap:1.5rem!important}.column-gap-xxl-5{column-gap:2rem!important}.column-gap-xxl-6{column-gap:2.5rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}.columns-xxl-2{columns:2!important}.columns-xxl-3{columns:3!important}.columns-xxl-4{columns:4!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-inline-grid{display:inline-grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}}:root,:host{--tblr-font-monospace: Roboto Mono;--tblr-font-sans-serif: Inter, system-ui, sans-serif;--tblr-font-serif: Georgia, Times New Roman, times, serif;--tblr-font-comic: Comic Sans MS, Comic Sans, Chalkboard SE, Comic Neue, sans-serif, cursive;--tblr-gray-50: #f9fafb;--tblr-gray-100: #f3f4f6;--tblr-gray-200: #e5e7eb;--tblr-gray-300: #d1d5db;--tblr-gray-400: #9ca3af;--tblr-gray-500: #6b7280;--tblr-gray-600: #4b5563;--tblr-gray-700: #374151;--tblr-gray-800: #1f2937;--tblr-gray-900: #111827;--tblr-gray-950: #030712;--tblr-white: #ffffff;--tblr-black: #000000;--tblr-brand: #00857D;--tblr-primary: #00857D;--tblr-primary-rgb: 0, 133, 125;--tblr-primary-fg: var(--tblr-light);--tblr-primary-darken: rgb(0, 119.7, 112.5);--tblr-primary-darken: color-mix(in oklab, var(--tblr-primary), transparent 20%);--tblr-primary-lt: rgb(229.5, 242.8, 242);--tblr-primary-lt: color-mix(in oklab, var(--tblr-primary) 10%, transparent);--tblr-primary-200: color-mix(in oklab, var(--tblr-primary) 20%, transparent);--tblr-primary-lt-rgb: 230, 243, 242;--tblr-secondary: #6b7280;--tblr-secondary-rgb: 107, 114, 128;--tblr-secondary-fg: var(--tblr-light);--tblr-secondary-darken: rgb(96.3, 102.6, 115.2);--tblr-secondary-darken: color-mix(in oklab, var(--tblr-secondary), transparent 20%);--tblr-secondary-lt: rgb(240.2, 240.9, 242.3);--tblr-secondary-lt: color-mix(in oklab, var(--tblr-secondary) 10%, transparent);--tblr-secondary-200: color-mix(in oklab, var(--tblr-secondary) 20%, transparent);--tblr-secondary-lt-rgb: 240, 241, 242;--tblr-success: #2fb344;--tblr-success-rgb: 47, 179, 68;--tblr-success-fg: var(--tblr-light);--tblr-success-darken: rgb(42.3, 161.1, 61.2);--tblr-success-darken: color-mix(in oklab, var(--tblr-success), transparent 20%);--tblr-success-lt: rgb(234.2, 247.4, 236.3);--tblr-success-lt: color-mix(in oklab, var(--tblr-success) 10%, transparent);--tblr-success-200: color-mix(in oklab, var(--tblr-success) 20%, transparent);--tblr-success-lt-rgb: 234, 247, 236;--tblr-info: #4299e1;--tblr-info-rgb: 66, 153, 225;--tblr-info-fg: var(--tblr-light);--tblr-info-darken: rgb(59.4, 137.7, 202.5);--tblr-info-darken: color-mix(in oklab, var(--tblr-info), transparent 20%);--tblr-info-lt: rgb(236.1, 244.8, 252);--tblr-info-lt: color-mix(in oklab, var(--tblr-info) 10%, transparent);--tblr-info-200: color-mix(in oklab, var(--tblr-info) 20%, transparent);--tblr-info-lt-rgb: 236, 245, 252;--tblr-warning: #f59f00;--tblr-warning-rgb: 245, 159, 0;--tblr-warning-fg: var(--tblr-light);--tblr-warning-darken: rgb(220.5, 143.1, 0);--tblr-warning-darken: color-mix(in oklab, var(--tblr-warning), transparent 20%);--tblr-warning-lt: rgb(254, 245.4, 229.5);--tblr-warning-lt: color-mix(in oklab, var(--tblr-warning) 10%, transparent);--tblr-warning-200: color-mix(in oklab, var(--tblr-warning) 20%, transparent);--tblr-warning-lt-rgb: 254, 245, 230;--tblr-danger: #d63939;--tblr-danger-rgb: 214, 57, 57;--tblr-danger-fg: var(--tblr-light);--tblr-danger-darken: rgb(192.6, 51.3, 51.3);--tblr-danger-darken: color-mix(in oklab, var(--tblr-danger), transparent 20%);--tblr-danger-lt: rgb(250.9, 235.2, 235.2);--tblr-danger-lt: color-mix(in oklab, var(--tblr-danger) 10%, transparent);--tblr-danger-200: color-mix(in oklab, var(--tblr-danger) 20%, transparent);--tblr-danger-lt-rgb: 251, 235, 235;--tblr-light: #f9fafb;--tblr-light-rgb: 249, 250, 251;--tblr-light-fg: var(--tblr-dark);--tblr-light-darken: rgb(224.1, 225, 225.9);--tblr-light-darken: color-mix(in oklab, var(--tblr-light), transparent 20%);--tblr-light-lt: rgb(254.4, 254.5, 254.6);--tblr-light-lt: color-mix(in oklab, var(--tblr-light) 10%, transparent);--tblr-light-200: color-mix(in oklab, var(--tblr-light) 20%, transparent);--tblr-light-lt-rgb: 254, 255, 255;--tblr-dark: #1f2937;--tblr-dark-rgb: 31, 41, 55;--tblr-dark-fg: var(--tblr-light);--tblr-dark-darken: rgb(27.9, 36.9, 49.5);--tblr-dark-darken: color-mix(in oklab, var(--tblr-dark), transparent 20%);--tblr-dark-lt: rgb(232.6, 233.6, 235);--tblr-dark-lt: color-mix(in oklab, var(--tblr-dark) 10%, transparent);--tblr-dark-200: color-mix(in oklab, var(--tblr-dark) 20%, transparent);--tblr-dark-lt-rgb: 233, 234, 235;--tblr-muted: #6b7280;--tblr-muted-rgb: 107, 114, 128;--tblr-muted-fg: var(--tblr-light);--tblr-muted-darken: rgb(96.3, 102.6, 115.2);--tblr-muted-darken: color-mix(in oklab, var(--tblr-muted), transparent 20%);--tblr-muted-lt: rgb(240.2, 240.9, 242.3);--tblr-muted-lt: color-mix(in oklab, var(--tblr-muted) 10%, transparent);--tblr-muted-200: color-mix(in oklab, var(--tblr-muted) 20%, transparent);--tblr-muted-lt-rgb: 240, 241, 242;--tblr-blue: #066fd1;--tblr-blue-rgb: 6, 111, 209;--tblr-blue-fg: var(--tblr-light);--tblr-blue-darken: rgb(5.4, 99.9, 188.1);--tblr-blue-darken: color-mix(in oklab, var(--tblr-blue), transparent 20%);--tblr-blue-lt: rgb(230.1, 240.6, 250.4);--tblr-blue-lt: color-mix(in oklab, var(--tblr-blue) 10%, transparent);--tblr-blue-200: color-mix(in oklab, var(--tblr-blue) 20%, transparent);--tblr-blue-lt-rgb: 230, 241, 250;--tblr-azure: #4299e1;--tblr-azure-rgb: 66, 153, 225;--tblr-azure-fg: var(--tblr-light);--tblr-azure-darken: rgb(59.4, 137.7, 202.5);--tblr-azure-darken: color-mix(in oklab, var(--tblr-azure), transparent 20%);--tblr-azure-lt: rgb(236.1, 244.8, 252);--tblr-azure-lt: color-mix(in oklab, var(--tblr-azure) 10%, transparent);--tblr-azure-200: color-mix(in oklab, var(--tblr-azure) 20%, transparent);--tblr-azure-lt-rgb: 236, 245, 252;--tblr-indigo: #4263eb;--tblr-indigo-rgb: 66, 99, 235;--tblr-indigo-fg: var(--tblr-light);--tblr-indigo-darken: rgb(59.4, 89.1, 211.5);--tblr-indigo-darken: color-mix(in oklab, var(--tblr-indigo), transparent 20%);--tblr-indigo-lt: rgb(236.1, 239.4, 253);--tblr-indigo-lt: color-mix(in oklab, var(--tblr-indigo) 10%, transparent);--tblr-indigo-200: color-mix(in oklab, var(--tblr-indigo) 20%, transparent);--tblr-indigo-lt-rgb: 236, 239, 253;--tblr-purple: #ae3ec9;--tblr-purple-rgb: 174, 62, 201;--tblr-purple-fg: var(--tblr-light);--tblr-purple-darken: rgb(156.6, 55.8, 180.9);--tblr-purple-darken: color-mix(in oklab, var(--tblr-purple), transparent 20%);--tblr-purple-lt: rgb(246.9, 235.7, 249.6);--tblr-purple-lt: color-mix(in oklab, var(--tblr-purple) 10%, transparent);--tblr-purple-200: color-mix(in oklab, var(--tblr-purple) 20%, transparent);--tblr-purple-lt-rgb: 247, 236, 250;--tblr-pink: #d6336c;--tblr-pink-rgb: 214, 51, 108;--tblr-pink-fg: var(--tblr-light);--tblr-pink-darken: rgb(192.6, 45.9, 97.2);--tblr-pink-darken: color-mix(in oklab, var(--tblr-pink), transparent 20%);--tblr-pink-lt: rgb(250.9, 234.6, 240.3);--tblr-pink-lt: color-mix(in oklab, var(--tblr-pink) 10%, transparent);--tblr-pink-200: color-mix(in oklab, var(--tblr-pink) 20%, transparent);--tblr-pink-lt-rgb: 251, 235, 240;--tblr-red: #d63939;--tblr-red-rgb: 214, 57, 57;--tblr-red-fg: var(--tblr-light);--tblr-red-darken: rgb(192.6, 51.3, 51.3);--tblr-red-darken: color-mix(in oklab, var(--tblr-red), transparent 20%);--tblr-red-lt: rgb(250.9, 235.2, 235.2);--tblr-red-lt: color-mix(in oklab, var(--tblr-red) 10%, transparent);--tblr-red-200: color-mix(in oklab, var(--tblr-red) 20%, transparent);--tblr-red-lt-rgb: 251, 235, 235;--tblr-orange: #f76707;--tblr-orange-rgb: 247, 103, 7;--tblr-orange-fg: var(--tblr-light);--tblr-orange-darken: rgb(222.3, 92.7, 6.3);--tblr-orange-darken: color-mix(in oklab, var(--tblr-orange), transparent 20%);--tblr-orange-lt: rgb(254.2, 239.8, 230.2);--tblr-orange-lt: color-mix(in oklab, var(--tblr-orange) 10%, transparent);--tblr-orange-200: color-mix(in oklab, var(--tblr-orange) 20%, transparent);--tblr-orange-lt-rgb: 254, 240, 230;--tblr-yellow: #f59f00;--tblr-yellow-rgb: 245, 159, 0;--tblr-yellow-fg: var(--tblr-light);--tblr-yellow-darken: rgb(220.5, 143.1, 0);--tblr-yellow-darken: color-mix(in oklab, var(--tblr-yellow), transparent 20%);--tblr-yellow-lt: rgb(254, 245.4, 229.5);--tblr-yellow-lt: color-mix(in oklab, var(--tblr-yellow) 10%, transparent);--tblr-yellow-200: color-mix(in oklab, var(--tblr-yellow) 20%, transparent);--tblr-yellow-lt-rgb: 254, 245, 230;--tblr-lime: #74b816;--tblr-lime-rgb: 116, 184, 22;--tblr-lime-fg: var(--tblr-light);--tblr-lime-darken: rgb(104.4, 165.6, 19.8);--tblr-lime-darken: color-mix(in oklab, var(--tblr-lime), transparent 20%);--tblr-lime-lt: rgb(241.1, 247.9, 231.7);--tblr-lime-lt: color-mix(in oklab, var(--tblr-lime) 10%, transparent);--tblr-lime-200: color-mix(in oklab, var(--tblr-lime) 20%, transparent);--tblr-lime-lt-rgb: 241, 248, 232;--tblr-green: #2fb344;--tblr-green-rgb: 47, 179, 68;--tblr-green-fg: var(--tblr-light);--tblr-green-darken: rgb(42.3, 161.1, 61.2);--tblr-green-darken: color-mix(in oklab, var(--tblr-green), transparent 20%);--tblr-green-lt: rgb(234.2, 247.4, 236.3);--tblr-green-lt: color-mix(in oklab, var(--tblr-green) 10%, transparent);--tblr-green-200: color-mix(in oklab, var(--tblr-green) 20%, transparent);--tblr-green-lt-rgb: 234, 247, 236;--tblr-teal: #0ca678;--tblr-teal-rgb: 12, 166, 120;--tblr-teal-fg: var(--tblr-light);--tblr-teal-darken: rgb(10.8, 149.4, 108);--tblr-teal-darken: color-mix(in oklab, var(--tblr-teal), transparent 20%);--tblr-teal-lt: rgb(230.7, 246.1, 241.5);--tblr-teal-lt: color-mix(in oklab, var(--tblr-teal) 10%, transparent);--tblr-teal-200: color-mix(in oklab, var(--tblr-teal) 20%, transparent);--tblr-teal-lt-rgb: 231, 246, 242;--tblr-cyan: #17a2b8;--tblr-cyan-rgb: 23, 162, 184;--tblr-cyan-fg: var(--tblr-light);--tblr-cyan-darken: rgb(20.7, 145.8, 165.6);--tblr-cyan-darken: color-mix(in oklab, var(--tblr-cyan), transparent 20%);--tblr-cyan-lt: rgb(231.8, 245.7, 247.9);--tblr-cyan-lt: color-mix(in oklab, var(--tblr-cyan) 10%, transparent);--tblr-cyan-200: color-mix(in oklab, var(--tblr-cyan) 20%, transparent);--tblr-cyan-lt-rgb: 232, 246, 248;--tblr-x: #000000;--tblr-x-rgb: 0, 0, 0;--tblr-x-fg: var(--tblr-light);--tblr-x-darken: black;--tblr-x-darken: color-mix(in oklab, var(--tblr-x), transparent 20%);--tblr-x-lt: rgb(229.5, 229.5, 229.5);--tblr-x-lt: color-mix(in oklab, var(--tblr-x) 10%, transparent);--tblr-x-200: color-mix(in oklab, var(--tblr-x) 20%, transparent);--tblr-x-lt-rgb: 230, 230, 230;--tblr-facebook: #1877f2;--tblr-facebook-rgb: 24, 119, 242;--tblr-facebook-fg: var(--tblr-light);--tblr-facebook-darken: rgb(21.6, 107.1, 217.8);--tblr-facebook-darken: color-mix(in oklab, var(--tblr-facebook), transparent 20%);--tblr-facebook-lt: rgb(231.9, 241.4, 253.7);--tblr-facebook-lt: color-mix(in oklab, var(--tblr-facebook) 10%, transparent);--tblr-facebook-200: color-mix(in oklab, var(--tblr-facebook) 20%, transparent);--tblr-facebook-lt-rgb: 232, 241, 254;--tblr-twitter: #1da1f2;--tblr-twitter-rgb: 29, 161, 242;--tblr-twitter-fg: var(--tblr-light);--tblr-twitter-darken: rgb(26.1, 144.9, 217.8);--tblr-twitter-darken: color-mix(in oklab, var(--tblr-twitter), transparent 20%);--tblr-twitter-lt: rgb(232.4, 245.6, 253.7);--tblr-twitter-lt: color-mix(in oklab, var(--tblr-twitter) 10%, transparent);--tblr-twitter-200: color-mix(in oklab, var(--tblr-twitter) 20%, transparent);--tblr-twitter-lt-rgb: 232, 246, 254;--tblr-linkedin: #0a66c2;--tblr-linkedin-rgb: 10, 102, 194;--tblr-linkedin-fg: var(--tblr-light);--tblr-linkedin-darken: rgb(9, 91.8, 174.6);--tblr-linkedin-darken: color-mix(in oklab, var(--tblr-linkedin), transparent 20%);--tblr-linkedin-lt: rgb(230.5, 239.7, 248.9);--tblr-linkedin-lt: color-mix(in oklab, var(--tblr-linkedin) 10%, transparent);--tblr-linkedin-200: color-mix(in oklab, var(--tblr-linkedin) 20%, transparent);--tblr-linkedin-lt-rgb: 231, 240, 249;--tblr-google: #dc4e41;--tblr-google-rgb: 220, 78, 65;--tblr-google-fg: var(--tblr-light);--tblr-google-darken: rgb(198, 70.2, 58.5);--tblr-google-darken: color-mix(in oklab, var(--tblr-google), transparent 20%);--tblr-google-lt: rgb(251.5, 237.3, 236);--tblr-google-lt: color-mix(in oklab, var(--tblr-google) 10%, transparent);--tblr-google-200: color-mix(in oklab, var(--tblr-google) 20%, transparent);--tblr-google-lt-rgb: 252, 237, 236;--tblr-youtube: #ff0000;--tblr-youtube-rgb: 255, 0, 0;--tblr-youtube-fg: var(--tblr-light);--tblr-youtube-darken: rgb(229.5, 0, 0);--tblr-youtube-darken: color-mix(in oklab, var(--tblr-youtube), transparent 20%);--tblr-youtube-lt: rgb(255, 229.5, 229.5);--tblr-youtube-lt: color-mix(in oklab, var(--tblr-youtube) 10%, transparent);--tblr-youtube-200: color-mix(in oklab, var(--tblr-youtube) 20%, transparent);--tblr-youtube-lt-rgb: 255, 230, 230;--tblr-vimeo: #1ab7ea;--tblr-vimeo-rgb: 26, 183, 234;--tblr-vimeo-fg: var(--tblr-light);--tblr-vimeo-darken: rgb(23.4, 164.7, 210.6);--tblr-vimeo-darken: color-mix(in oklab, var(--tblr-vimeo), transparent 20%);--tblr-vimeo-lt: rgb(232.1, 247.8, 252.9);--tblr-vimeo-lt: color-mix(in oklab, var(--tblr-vimeo) 10%, transparent);--tblr-vimeo-200: color-mix(in oklab, var(--tblr-vimeo) 20%, transparent);--tblr-vimeo-lt-rgb: 232, 248, 253;--tblr-dribbble: #ea4c89;--tblr-dribbble-rgb: 234, 76, 137;--tblr-dribbble-fg: var(--tblr-light);--tblr-dribbble-darken: rgb(210.6, 68.4, 123.3);--tblr-dribbble-darken: color-mix(in oklab, var(--tblr-dribbble), transparent 20%);--tblr-dribbble-lt: rgb(252.9, 237.1, 243.2);--tblr-dribbble-lt: color-mix(in oklab, var(--tblr-dribbble) 10%, transparent);--tblr-dribbble-200: color-mix(in oklab, var(--tblr-dribbble) 20%, transparent);--tblr-dribbble-lt-rgb: 253, 237, 243;--tblr-github: #181717;--tblr-github-rgb: 24, 23, 23;--tblr-github-fg: var(--tblr-light);--tblr-github-darken: rgb(21.6, 20.7, 20.7);--tblr-github-darken: color-mix(in oklab, var(--tblr-github), transparent 20%);--tblr-github-lt: rgb(231.9, 231.8, 231.8);--tblr-github-lt: color-mix(in oklab, var(--tblr-github) 10%, transparent);--tblr-github-200: color-mix(in oklab, var(--tblr-github) 20%, transparent);--tblr-github-lt-rgb: 232, 232, 232;--tblr-instagram: #e4405f;--tblr-instagram-rgb: 228, 64, 95;--tblr-instagram-fg: var(--tblr-light);--tblr-instagram-darken: rgb(205.2, 57.6, 85.5);--tblr-instagram-darken: color-mix(in oklab, var(--tblr-instagram), transparent 20%);--tblr-instagram-lt: rgb(252.3, 235.9, 239);--tblr-instagram-lt: color-mix(in oklab, var(--tblr-instagram) 10%, transparent);--tblr-instagram-200: color-mix(in oklab, var(--tblr-instagram) 20%, transparent);--tblr-instagram-lt-rgb: 252, 236, 239;--tblr-pinterest: #bd081c;--tblr-pinterest-rgb: 189, 8, 28;--tblr-pinterest-fg: var(--tblr-light);--tblr-pinterest-darken: rgb(170.1, 7.2, 25.2);--tblr-pinterest-darken: color-mix(in oklab, var(--tblr-pinterest), transparent 20%);--tblr-pinterest-lt: rgb(248.4, 230.3, 232.3);--tblr-pinterest-lt: color-mix(in oklab, var(--tblr-pinterest) 10%, transparent);--tblr-pinterest-200: color-mix(in oklab, var(--tblr-pinterest) 20%, transparent);--tblr-pinterest-lt-rgb: 248, 230, 232;--tblr-vk: #6383a8;--tblr-vk-rgb: 99, 131, 168;--tblr-vk-fg: var(--tblr-light);--tblr-vk-darken: rgb(89.1, 117.9, 151.2);--tblr-vk-darken: color-mix(in oklab, var(--tblr-vk), transparent 20%);--tblr-vk-lt: rgb(239.4, 242.6, 246.3);--tblr-vk-lt: color-mix(in oklab, var(--tblr-vk) 10%, transparent);--tblr-vk-200: color-mix(in oklab, var(--tblr-vk) 20%, transparent);--tblr-vk-lt-rgb: 239, 243, 246;--tblr-rss: #ffa500;--tblr-rss-rgb: 255, 165, 0;--tblr-rss-fg: var(--tblr-light);--tblr-rss-darken: rgb(229.5, 148.5, 0);--tblr-rss-darken: color-mix(in oklab, var(--tblr-rss), transparent 20%);--tblr-rss-lt: rgb(255, 246, 229.5);--tblr-rss-lt: color-mix(in oklab, var(--tblr-rss) 10%, transparent);--tblr-rss-200: color-mix(in oklab, var(--tblr-rss) 20%, transparent);--tblr-rss-lt-rgb: 255, 246, 230;--tblr-flickr: #0063dc;--tblr-flickr-rgb: 0, 99, 220;--tblr-flickr-fg: var(--tblr-light);--tblr-flickr-darken: rgb(0, 89.1, 198);--tblr-flickr-darken: color-mix(in oklab, var(--tblr-flickr), transparent 20%);--tblr-flickr-lt: rgb(229.5, 239.4, 251.5);--tblr-flickr-lt: color-mix(in oklab, var(--tblr-flickr) 10%, transparent);--tblr-flickr-200: color-mix(in oklab, var(--tblr-flickr) 20%, transparent);--tblr-flickr-lt-rgb: 230, 239, 252;--tblr-bitbucket: #0052cc;--tblr-bitbucket-rgb: 0, 82, 204;--tblr-bitbucket-fg: var(--tblr-light);--tblr-bitbucket-darken: rgb(0, 73.8, 183.6);--tblr-bitbucket-darken: color-mix(in oklab, var(--tblr-bitbucket), transparent 20%);--tblr-bitbucket-lt: rgb(229.5, 237.7, 249.9);--tblr-bitbucket-lt: color-mix(in oklab, var(--tblr-bitbucket) 10%, transparent);--tblr-bitbucket-200: color-mix(in oklab, var(--tblr-bitbucket) 20%, transparent);--tblr-bitbucket-lt-rgb: 230, 238, 250;--tblr-tabler: #066fd1;--tblr-tabler-rgb: 6, 111, 209;--tblr-tabler-fg: var(--tblr-light);--tblr-tabler-darken: rgb(5.4, 99.9, 188.1);--tblr-tabler-darken: color-mix(in oklab, var(--tblr-tabler), transparent 20%);--tblr-tabler-lt: rgb(230.1, 240.6, 250.4);--tblr-tabler-lt: color-mix(in oklab, var(--tblr-tabler) 10%, transparent);--tblr-tabler-200: color-mix(in oklab, var(--tblr-tabler) 20%, transparent);--tblr-tabler-lt-rgb: 230, 241, 250;--tblr-gray-50-fg: var(--tblr-body-color);--tblr-gray-100-fg: var(--tblr-body-color);--tblr-gray-200-fg: var(--tblr-body-color);--tblr-gray-300-fg: var(--tblr-body-color);--tblr-gray-400-fg: var(--tblr-white);--tblr-gray-500-fg: var(--tblr-white);--tblr-gray-600-fg: var(--tblr-white);--tblr-gray-700-fg: var(--tblr-white);--tblr-gray-800-fg: var(--tblr-white);--tblr-gray-900-fg: var(--tblr-white);--tblr-gray-950-fg: var(--tblr-white);--tblr-spacer-0: 0;--tblr-spacer-1: .25rem;--tblr-spacer-2: .5rem;--tblr-spacer-3: 1rem;--tblr-spacer-4: 1.5rem;--tblr-spacer-5: 2rem;--tblr-spacer-6: 2.5rem;--tblr-font-weight-light: 300;--tblr-font-weight-normal: 400;--tblr-font-weight-medium: 500;--tblr-font-weight-bold: 600;--tblr-font-weight-black: 700;--tblr-font-weight-headings: var(--tblr-font-weight-bold);--tblr-font-size-h1: 1.5rem;--tblr-font-size-h2: 1.25rem;--tblr-font-size-h3: 1rem;--tblr-font-size-h4: .875rem;--tblr-font-size-h5: .75rem;--tblr-font-size-h6: .625rem;--tblr-line-height-h1: 2rem;--tblr-line-height-h2: 1.75rem;--tblr-line-height-h3: 1.5rem;--tblr-line-height-h4: 1.25rem;--tblr-line-height-h5: 1rem;--tblr-line-height-h6: 1rem;--tblr-shadow: rgba(var(--tblr-body-color-rgb), .04) 0 2px 4px 0;--tblr-shadow-border: inset 0 0 0 1px var(--tblr-border-color-translucent);--tblr-shadow-transparent: 0 0 0 0 transparent;--tblr-shadow-input: 0 1px 1px rgba(var(--tblr-body-color-rgb), .06);--tblr-shadow-card: 0 0 4px rgba(var(--tblr-body-color-rgb), .04);--tblr-shadow-card-hover: rgba(var(--tblr-body-color-rgb), .16) 0 2px 16px 0;--tblr-shadow-dropdown: 0 16px 24px 2px rgba(0, 0, 0, .07), 0 6px 30px 5px rgba(0, 0, 0, .06), 0 8px 10px -5px rgba(0, 0, 0, .1);--tblr-border-radius-scale: 1;--tblr-border-radius-0: calc(0 * var(--tblr-border-radius-scale, 1));--tblr-border-radius-sm: calc(4px * var(--tblr-border-radius-scale, 1));--tblr-border-radius-md: calc(6px * var(--tblr-border-radius-scale, 1));--tblr-border-radius-lg: calc(8px * var(--tblr-border-radius-scale, 1));--tblr-border-radius-pill: calc(100rem * var(--tblr-border-radius-scale, 1));--tblr-border-radius: var(--tblr-border-radius-md);--tblr-backdrop-opacity: 24%;--tblr-backdrop-bg: var(--tblr-bg-surface-dark);--tblr-backdrop-bg-dark: color-mix(in srgb, var(--tblr-color-dark), transparent var(--tblr-backdrop-opacity));--tblr-backdrop-bg-light: color-mix(in srgb, var(--tblr-color-light), transparent var(--tblr-backdrop-opacity));--tblr-backdrop-blur: 4px;--tblr-backdrop-filter: blur(var(--tblr-backdrop-blur))}:root,:host{font-size:16px;height:100%}@media(min-width:992px){:root,:host{margin-left:calc(100vw - 100%);margin-right:0}}:root,:host,[data-bs-theme=light]{color-scheme:light;--tblr-spacer: var(--tblr-spacer-2);--tblr-bg-surface: var(--tblr-bg-surface-primary);--tblr-bg-surface-primary: var(--tblr-white);--tblr-bg-surface-secondary: var(--tblr-gray-50);--tblr-bg-surface-tertiary: var(--tblr-gray-50);--tblr-bg-surface-dark: var(--tblr-gray-900);--tblr-bg-surface-inverted: var(--tblr-gray-900);--tblr-bg-forms: var(--tblr-bg-surface);--tblr-text-inverted: var(--tblr-gray-100);--tblr-body-color: var(--tblr-gray-700);--tblr-body-bg: var(--tblr-bg-surface-secondary);--tblr-link-color: var(--tblr-primary);--tblr-link-hover-color: color-mix(in srgb, var(--tblr-primary), #000 20%);--tblr-secondary: var(--tblr-gray-500);--tblr-tertiary: var(--tblr-gray-400);--tblr-border-color: #e5e7eb;--tblr-border-color-translucent: rgba(4, 32, 69, .1);--tblr-border-dark-color: #9ca3af;--tblr-border-dark-color-translucent: rgba(4, 32, 69, .27);--tblr-border-active-color: rgb(169.16, 173.22, 181.34);--tblr-icon-color: var(--tblr-gray-400);--tblr-active-bg: rgba(var(--tblr-primary-rgb), .04);--tblr-disabled-bg: var(--tblr-bg-surface-secondary);--tblr-disabled-color: color-mix(in srgb, var(--tblr-body-color) 40%, transparent);--tblr-code-color: light-dark(var(--tblr-gray-600), var(--tblr-gray-400));--tblr-code-bg: light-dark(var(--tblr-gray-100), var(--tblr-gray-900));--tblr-dark-mode-border-color: rgb(45.7069767442, 60.4511627907, 81.0930232558);--tblr-dark-mode-border-color-translucent: rgba(72, 110, 149, .14);--tblr-dark-mode-border-active-color: rgb(53.0604651163, 70.176744186, 94.1395348837);--tblr-dark-mode-border-dark-color: rgb(38.3534883721, 50.7255813953, 68.0465116279);--tblr-page-padding: var(--tblr-spacer-3);--tblr-page-padding-y: var(--tblr-spacer-4)}@media(max-width:991.98px){:root,:host,[data-bs-theme=light]{--tblr-page-padding: var(--tblr-spacer-2)}}@keyframes pulse{0%{transform:scale(1)}14%{transform:scale(1.25)}28%{transform:scale(1)}42%{transform:scale(1.25)}70%{transform:scale(1)}}@keyframes tada{0%{transform:scaleZ(1)}10%,5%{transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-5deg)}15%,25%,35%,45%{transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,5deg)}20%,30%,40%{transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-5deg)}50%{transform:scaleZ(1)}}@keyframes rotate-360{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes blink{0%{opacity:0}50%{opacity:1}to{opacity:0}}@keyframes shake{0%{transform:scaleX(1)}20%{transform:scale3d(.9,.9,.9) rotate(-5deg)}50%,70%,90%{transform:scale3d(1.25,1.25,1.25) rotate(5deg)}60%,80%{transform:scale3d(1.25,1.25,1.25) rotate(-5deg)}to{transform:scaleX(1)}}body{letter-spacing:0;touch-action:manipulation;text-rendering:optimizeLegibility;font-feature-settings:"liga" 0,"cv03","cv04","cv11";position:relative;min-height:100%;height:100%;padding:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media print{body{background:transparent}}*{scrollbar-color:color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent) transparent}*::-webkit-scrollbar{width:1rem;height:1rem;transition:background .3s}@media(prefers-reduced-motion:reduce){*::-webkit-scrollbar{transition:none}}*::-webkit-scrollbar-thumb{border-radius:1rem;border:5px solid transparent;box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent)}*::-webkit-scrollbar-track{background:transparent}*:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 40%,transparent)}*::-webkit-scrollbar-corner{background:transparent}.layout-fluid .container,.layout-fluid [class^=container-],.layout-fluid [class*=" container-"]{max-width:100%}.layout-boxed{--tblr-theme-boxed-border-radius: 0;--tblr-theme-boxed-width: 1320px}@media(min-width:768px){.layout-boxed{background:#1f2937 linear-gradient(to right,rgba(255,255,255,.1),transparent) fixed;padding:1rem;--tblr-theme-boxed-border-radius: 6px}}.layout-boxed .page{margin:0 auto;max-width:var(--tblr-theme-boxed-width);border-radius:var(--tblr-theme-boxed-border-radius);color:var(--tblr-body-color)}@media(min-width:768px){.layout-boxed .page{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);background:var(--tblr-body-bg)}}.layout-boxed .page>.navbar:first-child{border-top-left-radius:var(--tblr-theme-boxed-border-radius);border-top-right-radius:var(--tblr-theme-boxed-border-radius)}.navbar{--tblr-navbar-bg: var(--tblr-bg-surface);--tblr-navbar-border-width: var(--tblr-border-width);--tblr-navbar-active-border-color: #00857D;--tblr-navbar-active-bg: rgba(0, 0, 0, .2);--tblr-navbar-border-color: var(--tblr-border-color);--tblr-navbar-hover-color: var(--tblr-body-color);align-items:stretch;min-height:3.5rem;box-shadow:inset 0 calc(-1 * var(--tblr-navbar-border-width)) 0 0 var(--tblr-navbar-border-color);background:var(--tblr-navbar-bg);color:var(--tblr-navbar-color)}.navbar-collapse .navbar{flex-grow:1}.navbar.collapsing{min-height:0}.navbar .dropdown-menu{position:absolute;z-index:1030}.navbar .navbar-nav{min-height:3rem}.navbar .navbar-nav .nav-link{position:relative;min-width:2.5rem;min-height:2.5rem;justify-content:center;border-radius:var(--tblr-border-radius)}.navbar .navbar-nav .nav-link .badge{position:absolute;top:.375rem;right:.375rem;transform:translate(50%,-50%)}@media(max-width:575.98px){.navbar-expand-sm .navbar-collapse{flex-direction:column}.navbar-expand-sm .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-sm .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-sm .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-sm .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-sm .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-sm .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-sm .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:576px){.navbar-expand-sm .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-sm .nav-item.active{position:relative}.navbar-expand-sm .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-sm .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-sm.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-sm.navbar-vertical.navbar-right,.navbar-expand-sm.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-sm.navbar-vertical~.navbar,.navbar-expand-sm.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-sm.navbar-vertical.navbar-right~.navbar,.navbar-expand-sm.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-sm.navbar-vertical.navbar-end~.navbar,.navbar-expand-sm.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:767.98px){.navbar-expand-md .navbar-collapse{flex-direction:column}.navbar-expand-md .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-md .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-md .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-md .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-md .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-md .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-md .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:768px){.navbar-expand-md .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-md .nav-item.active{position:relative}.navbar-expand-md .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-md .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-md.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-md.navbar-vertical.navbar-right,.navbar-expand-md.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-md.navbar-vertical~.navbar,.navbar-expand-md.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-md.navbar-vertical.navbar-right~.navbar,.navbar-expand-md.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-md.navbar-vertical.navbar-end~.navbar,.navbar-expand-md.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:991.98px){.navbar-expand-lg .navbar-collapse{flex-direction:column}.navbar-expand-lg .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-lg .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-lg .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-lg .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-lg .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-lg .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-lg .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:992px){.navbar-expand-lg .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-lg .nav-item.active{position:relative}.navbar-expand-lg .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-lg .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-lg.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-lg.navbar-vertical.navbar-right,.navbar-expand-lg.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-lg.navbar-vertical~.navbar,.navbar-expand-lg.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-lg.navbar-vertical.navbar-right~.navbar,.navbar-expand-lg.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-lg.navbar-vertical.navbar-end~.navbar,.navbar-expand-lg.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:1199.98px){.navbar-expand-xl .navbar-collapse{flex-direction:column}.navbar-expand-xl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-xl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-xl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-xl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-xl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-xl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-xl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1200px){.navbar-expand-xl .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-xl .nav-item.active{position:relative}.navbar-expand-xl .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-xl .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-xl.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xl.navbar-vertical.navbar-right,.navbar-expand-xl.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xl.navbar-vertical~.navbar,.navbar-expand-xl.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-xl.navbar-vertical.navbar-right~.navbar,.navbar-expand-xl.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-xl.navbar-vertical.navbar-end~.navbar,.navbar-expand-xl.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:1399.98px){.navbar-expand-xxl .navbar-collapse{flex-direction:column}.navbar-expand-xxl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-xxl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-xxl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-xxl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-xxl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-xxl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-xxl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1400px){.navbar-expand-xxl .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-xxl .nav-item.active{position:relative}.navbar-expand-xxl .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-xxl .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-xxl.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xxl.navbar-vertical.navbar-right,.navbar-expand-xxl.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xxl.navbar-vertical~.navbar,.navbar-expand-xxl.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-xxl.navbar-vertical.navbar-right~.navbar,.navbar-expand-xxl.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-xxl.navbar-vertical.navbar-end~.navbar,.navbar-expand-xxl.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}.navbar-expand .navbar-collapse{flex-direction:column}.navbar-expand .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}.navbar-expand .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand .nav-item.active{position:relative}.navbar-expand .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand.navbar-vertical.navbar-right,.navbar-expand.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand.navbar-vertical~.navbar,.navbar-expand.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand.navbar-vertical.navbar-right~.navbar,.navbar-expand.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand.navbar-vertical.navbar-end~.navbar,.navbar-expand.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}.navbar-brand{display:inline-flex;align-items:center;font-weight:var(--tblr-font-weight-bold);margin:0;line-height:1;gap:.5rem}.navbar-brand-image{height:2rem;width:auto}.navbar-toggler{border:0;width:2rem;height:2rem;position:relative;display:flex;align-items:center;justify-content:center}.navbar-toggler-icon{height:2px;width:1.25em;background:currentColor;border-radius:10px;transition:top .2s .2s,bottom .2s .2s,transform .2s,opacity 0s .2s}@media(prefers-reduced-motion:reduce){.navbar-toggler-icon{transition:none}}.navbar-toggler-icon{position:relative}.navbar-toggler-icon:before,.navbar-toggler-icon:after{content:"";display:block;height:inherit;width:inherit;border-radius:inherit;background:inherit;position:absolute;left:0;transition:inherit}@media(prefers-reduced-motion:reduce){.navbar-toggler-icon:before,.navbar-toggler-icon:after{transition:none}}.navbar-toggler-icon:before{top:-.45em}.navbar-toggler-icon:after{bottom:-.45em}.navbar-toggler[aria-expanded=true] .navbar-toggler-icon{transform:rotate(45deg);transition:top .3s,bottom .3s,transform .3s .3s,opacity 0s .3s}@media(prefers-reduced-motion:reduce){.navbar-toggler[aria-expanded=true] .navbar-toggler-icon{transition:none}}.navbar-toggler[aria-expanded=true] .navbar-toggler-icon:before{top:0;transform:rotate(-90deg)}.navbar-toggler[aria-expanded=true] .navbar-toggler-icon:after{bottom:0;opacity:0}.navbar-transparent{--tblr-navbar-border-color: transparent !important;background:transparent!important}.navbar-nav{--tblr-nav-link-hover-bg: color-mix(in srgb, var(--tblr-nav-link-color) 4%, transparent);margin:0;padding:0;align-items:stretch}.navbar-nav .nav-item{display:flex;flex-direction:column;justify-content:center}.navbar-side{margin:0;display:flex;flex-direction:row;align-items:center;justify-content:space-around}@media(min-width:576px){.navbar-vertical.navbar-expand-sm{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:576px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-sm{transition:none}}@media(min-width:576px){.navbar-vertical.navbar-expand-sm.navbar-right,.navbar-vertical.navbar-expand-sm.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-sm .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-sm .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-sm .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-sm .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-sm>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-sm~.page{padding-left:18rem}.navbar-vertical.navbar-expand-sm~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-sm.navbar-right~.page,.navbar-vertical.navbar-expand-sm.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-sm .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-sm .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-sm .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-sm .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-sm .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:768px){.navbar-vertical.navbar-expand-md{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:768px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-md{transition:none}}@media(min-width:768px){.navbar-vertical.navbar-expand-md.navbar-right,.navbar-vertical.navbar-expand-md.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-md .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-md .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-md .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-md .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-md>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-md~.page{padding-left:18rem}.navbar-vertical.navbar-expand-md~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-md.navbar-right~.page,.navbar-vertical.navbar-expand-md.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-md .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-md .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-md .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-md .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-md .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:992px){.navbar-vertical.navbar-expand-lg{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:992px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-lg{transition:none}}@media(min-width:992px){.navbar-vertical.navbar-expand-lg.navbar-right,.navbar-vertical.navbar-expand-lg.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-lg .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-lg .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-lg .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-lg .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-lg>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-lg~.page{padding-left:18rem}.navbar-vertical.navbar-expand-lg~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-lg.navbar-right~.page,.navbar-vertical.navbar-expand-lg.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-lg .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-lg .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-lg .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1200px){.navbar-vertical.navbar-expand-xl{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:1200px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-xl{transition:none}}@media(min-width:1200px){.navbar-vertical.navbar-expand-xl.navbar-right,.navbar-vertical.navbar-expand-xl.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-xl .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-xl .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-xl .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-xl .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-xl>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-xl~.page{padding-left:18rem}.navbar-vertical.navbar-expand-xl~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-xl.navbar-right~.page,.navbar-vertical.navbar-expand-xl.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-xl .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-xl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-xl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-xl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-xl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1400px){.navbar-vertical.navbar-expand-xxl{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:1400px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-xxl{transition:none}}@media(min-width:1400px){.navbar-vertical.navbar-expand-xxl.navbar-right,.navbar-vertical.navbar-expand-xxl.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-xxl .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-xxl .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-xxl .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-xxl .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-xxl>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-xxl~.page{padding-left:18rem}.navbar-vertical.navbar-expand-xxl~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-xxl.navbar-right~.page,.navbar-vertical.navbar-expand-xxl.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-xxl .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-xxl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-xxl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-xxl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-xxl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}.navbar-vertical.navbar-expand{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s}@media(prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand{transition:none}}.navbar-vertical.navbar-expand{overflow-y:scroll;padding:0}.navbar-vertical.navbar-expand.navbar-right,.navbar-vertical.navbar-expand.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand~.page{padding-left:18rem}.navbar-vertical.navbar-expand~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand.navbar-right~.page,.navbar-vertical.navbar-expand.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}.navbar-overlap:after{content:"";height:9rem;position:absolute;top:100%;left:0;right:0;background:inherit;z-index:-1;box-shadow:inherit}.page{display:flex;flex-direction:column;position:relative;min-height:100%}.page-center{justify-content:center}.page-wrapper{flex:1;display:flex;flex-direction:column}@media print{.page-wrapper{margin:0!important}}.page-wrapper-full .page-body:first-child{margin:0;border-top:0}.page-body{margin-top:var(--tblr-page-padding-y);margin-bottom:var(--tblr-page-padding-y);display:flex;flex-direction:column;flex:1}.page-body-card{background:var(--tblr-bg-surface);border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);padding:var(--tblr-page-padding) 0;margin-bottom:0;flex:1}.page-body~.page-body-card{margin-top:0}.page-cover{background:no-repeat center/cover;min-height:9rem}@media(min-width:768px){.page-cover{min-height:12rem}}@media(min-width:992px){.page-cover{min-height:15rem}}.page-cover-overlay{position:relative}.page-cover-overlay:after{content:"";position:absolute;inset:0;background-image:linear-gradient(180deg,#0000,#0009)}.page-header{display:flex;flex-wrap:wrap;min-height:2.25rem;flex-direction:column;justify-content:center;max-width:100%}.page-wrapper .page-header{margin:var(--tblr-page-padding-y) 0 0}.page-header-border{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);padding:var(--tblr-page-padding-y) 0;margin:0!important;background-color:var(--tblr-bg-surface)}.page-pretitle{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary)}.page-title{margin:0;font-size:var(--tblr-font-size-h2);line-height:var(--tblr-line-height-h2);font-weight:var(--tblr-font-weight-headings);color:inherit;display:flex;align-items:center}.page-title svg{width:1.5rem;height:1.5rem;margin-right:.25rem}.page-title-lg{font-size:1.5rem;line-height:2rem}.page-subtitle{margin-top:.25rem;color:var(--tblr-secondary)}.page-cover{--tblr-page-cover-blur: 20px;--tblr-page-cover-padding: 1rem;min-height:6rem;padding:var(--tblr-page-cover-padding) 0;position:relative;overflow:hidden}.page-cover-img{position:absolute;top:calc(-2 * var(--tblr-page-cover-blur, 0));left:calc(-2 * var(--tblr-page-cover-blur, 0));right:calc(-2 * var(--tblr-page-cover-blur, 0));bottom:calc(-2 * var(--tblr-page-cover-blur, 0));pointer-events:none;filter:blur(var(--tblr-page-cover-blur));object-fit:cover;background-size:cover;background-position:center;z-index:-1}.page-tabs{margin-top:.5rem;position:relative}.page-header-tabs .nav-bordered{border:0}.page-header-tabs+.page-body-card{margin-top:0}.footer{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);background-color:var(--tblr-bg-surface);padding:2rem 0;color:var(--tblr-gray-500);margin-top:auto}.footer-transparent{background-color:transparent;border-top:0}:root:not(.theme-dark):not([data-bs-theme=dark]) .hide-theme-light{display:none!important}:root:not(.theme-dark):not([data-bs-theme=dark]) .img-dark{display:none!important}:root.theme-dark .hide-theme-dark,:root[data-bs-theme=dark] .hide-theme-dark,body[data-bs-theme=dark] [data-bs-theme=light]:root .hide-theme-dark{display:none!important}:root.theme-dark .img-light,:root[data-bs-theme=dark] .img-light,body[data-bs-theme=dark] [data-bs-theme=light]:root .img-light{display:none!important}[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{color-scheme:dark;--tblr-body-color: var(--tblr-gray-200);--tblr-secondary: var(--tblr-gray-400);--tblr-body-bg: var(--tblr-gray-900);--tblr-emphasis-color: #ffffff;--tblr-emphasis-color-rgb: 255, 255, 255;--tblr-bg-forms: var(--tblr-gray-900);--tblr-bg-surface: var(--tblr-gray-800);--tblr-bg-surface-inverted: var(--tblr-gray-100);--tblr-bg-surface-secondary: var(--tblr-gray-900);--tblr-bg-surface-tertiary: var(--tblr-gray-800);--tblr-text-inverted: var(--tblr-gray-800);--tblr-link-color: var(--tblr-primary);--tblr-link-hover-color: color-mix(in srgb, var(--tblr-primary), black 20%);--tblr-active-bg: rgb(34.676744186, 45.8627906977, 61.523255814);--tblr-disabled-color: color-mix(in srgb, var(--tblr-body-color) 40%, transparent);--tblr-border-color: var(--tblr-gray-700);--tblr-border-color-translucent: var( --tblr-dark-mode-border-color-translucent );--tblr-border-dark-color: var(--tblr-dark-mode-border-dark-color);--tblr-border-active-color: var( --tblr-dark-mode-border-active-color );--tblr-btn-color: rgb(27.323255814, 36.1372093023, 48.476744186)}[data-bs-theme=dark] .navbar-brand-autodark .navbar-brand-image{filter:brightness(0) invert(1)}.accordion{--tblr-accordion-color: var(--tblr-body-color);--tblr-accordion-border-color: var(--tblr-border-color);--tblr-accordion-border-radius: var(--tblr-border-radius);--tblr-accordion-inner-border-radius: calc(var(--tblr-border-radius) - (var(--tblr-border-width)));--tblr-accordion-padding-x: 1.25rem;--tblr-accordion-gap: 0;--tblr-accordion-active-color: inherit;--tblr-accordion-btn-color: var(--tblr-accordion-color);--tblr-accordion-btn-bg: transparent;--tblr-accordion-btn-toggle-width: 1.25rem;--tblr-accordion-btn-padding-x: var(--tblr-accordion-padding-x);--tblr-accordion-btn-padding-y: 1rem;--tblr-accordion-btn-font-weight: var(--tblr-font-weight-medium);--tblr-accordion-body-padding-x: var(--tblr-accordion-padding-x);--tblr-accordion-body-padding-y: 1rem;display:flex;flex-direction:column;gap:var(--tblr-accordion-gap)}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--tblr-accordion-btn-padding-y) var(--tblr-accordion-padding-x);color:inherit;text-align:inherit;background-color:transparent;border:0;font-size:inherit;font-weight:var(--tblr-accordion-btn-font-weight);gap:.75rem}.accordion-button:not(.collapsed){border-bottom-color:transparent;box-shadow:none;color:var(--tblr-accordion-active-color)}.accordion-header{margin:0;position:relative;display:flex;gap:1rem;align-items:center;width:100%;color:var(--tblr-accordion-btn-color);text-align:left;background-color:transparent;border:0;overflow-anchor:none;transition:transform .3s}.accordion-header:hover{z-index:2}.accordion-header:focus{z-index:3;outline:0;box-shadow:var(--tblr-accordion-btn-focus-box-shadow)}.accordion-header:focus:not(:focus-visible){outline:none;box-shadow:none}.accordion-button-icon{color:var(--tblr-secondary)}.accordion-button-toggle{display:flex;line-height:1;transition:.3s transform;margin-left:auto;margin-right:0;color:var(--tblr-secondary);width:var(--tblr-accordion-btn-toggle-width);height:var(--tblr-accordion-btn-toggle-width)}.accordion-button:not(.collapsed) .accordion-button-toggle{transform:rotate(-180deg);color:var(--tblr-accordion-active-color)}.accordion-button-toggle path{transition:.3s opacity}.accordion-button:not(.collapsed) .accordion-button-toggle-plus path:first-child{opacity:0}.accordion-item{color:var(--tblr-accordion-color);border:var(--tblr-border-width) solid var(--tblr-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--tblr-accordion-border-radius);border-top-right-radius:var(--tblr-accordion-border-radius)}.accordion-item:first-of-type>.accordion-header{border-top-left-radius:var(--tblr-accordion-inner-border-radius);border-top-right-radius:var(--tblr-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--tblr-accordion-border-radius);border-bottom-left-radius:var(--tblr-accordion-border-radius)}.accordion-item:last-of-type>.accordion-header.collapsed{border-bottom-right-radius:var(--tblr-accordion-inner-border-radius);border-bottom-left-radius:var(--tblr-accordion-inner-border-radius)}.accordion-item:last-of-type>.accordion-collapse{border-bottom-right-radius:var(--tblr-accordion-border-radius);border-bottom-left-radius:var(--tblr-accordion-border-radius)}.accordion-body{color:var(--tblr-secondary);padding:0 var(--tblr-accordion-body-padding-x) var(--tblr-accordion-body-padding-y)}.accordion-flush>.accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush>.accordion-item:first-child{border-top:0}.accordion-flush>.accordion-item:last-child{border-bottom:0}.accordion-flush>.accordion-item>.accordion-collapse,.accordion-flush>.accordion-item>.accordion-header .accordion-button,.accordion-flush>.accordion-item>.accordion-header .accordion-button.collapsed{border-radius:0}.accordion-tabs{--tblr-accordion-gap: .75rem}.accordion-tabs>.accordion-item{border:var(--tblr-border-width) solid var(--tblr-accordion-border-color);border-radius:var(--tblr-accordion-border-radius)}.accordion-inverted .accordion-button-toggle{order:-1;margin-left:0}.alert{--tblr-alert-color: var(--tblr-body-color);--tblr-alert-bg: color-mix(in srgb, var(--tblr-alert-color) 10%, transparent);--tblr-alert-padding-x: 1rem;--tblr-alert-padding-y: .75rem;--tblr-alert-margin-bottom: 1rem;--tblr-alert-border-color: color-mix(in srgb, var(--tblr-alert-color) 20%, transparent);--tblr-alert-border: var(--tblr-border-width) solid var(--tblr-alert-border-color);--tblr-alert-border-radius: var(--tblr-border-radius);--tblr-alert-link-color: inherit;--tblr-alert-heading-font-weight: var(--tblr-font-weight-medium);position:relative;padding:var(--tblr-alert-padding-y) var(--tblr-alert-padding-x);margin-bottom:var(--tblr-alert-margin-bottom);background-color:color-mix(in srgb,var(--tblr-alert-bg),var(--tblr-bg-surface));border-radius:var(--tblr-alert-border-radius);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-alert-border-color);display:flex;flex-direction:row;gap:1rem}.alert-heading{color:inherit;margin-bottom:.25rem;font-weight:var(--tblr-alert-heading-font-weight)}.alert-description{color:var(--tblr-secondary)}.alert-icon{color:var(--tblr-alert-color);width:1.25rem!important;height:1.25rem!important}.alert-action{color:var(--tblr-alert-color);text-decoration:underline}.alert-action:hover{text-decoration:none}.alert-list{margin:0}.alert-link{font-weight:var(--tblr-font-weight-bold);color:var(--tblr-alert-link-color)}.alert-link,.alert-link:hover{color:var(--tblr-alert-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:calc(var(--tblr-alert-padding-x) / 2 - 1px);right:calc(var(--tblr-alert-padding-y) / 2 - 1px);z-index:1;padding:calc(var(--tblr-alert-padding-y) * 1.25) var(--tblr-alert-padding-x)}.alert-important{border-color:var(--tblr-alert-color);background-color:var(--tblr-alert-color);color:var(--tblr-white)}.alert-important .alert-description,.alert-important .alert-icon{color:inherit}.alert-minor{background:transparent;border-color:var(--tblr-border-color)}.alert-primary{--tblr-alert-color: var(--tblr-primary)}.alert-secondary{--tblr-alert-color: var(--tblr-secondary)}.alert-success{--tblr-alert-color: var(--tblr-success)}.alert-info{--tblr-alert-color: var(--tblr-info)}.alert-warning{--tblr-alert-color: var(--tblr-warning)}.alert-danger{--tblr-alert-color: var(--tblr-danger)}.alert-light{--tblr-alert-color: var(--tblr-light)}.alert-dark{--tblr-alert-color: var(--tblr-dark)}.alert-muted{--tblr-alert-color: var(--tblr-muted)}.alert-blue{--tblr-alert-color: var(--tblr-blue)}.alert-azure{--tblr-alert-color: var(--tblr-azure)}.alert-indigo{--tblr-alert-color: var(--tblr-indigo)}.alert-purple{--tblr-alert-color: var(--tblr-purple)}.alert-pink{--tblr-alert-color: var(--tblr-pink)}.alert-red{--tblr-alert-color: var(--tblr-red)}.alert-orange{--tblr-alert-color: var(--tblr-orange)}.alert-yellow{--tblr-alert-color: var(--tblr-yellow)}.alert-lime{--tblr-alert-color: var(--tblr-lime)}.alert-green{--tblr-alert-color: var(--tblr-green)}.alert-teal{--tblr-alert-color: var(--tblr-teal)}.alert-cyan{--tblr-alert-color: var(--tblr-cyan)}.avatar{--tblr-avatar-size: var(--tblr-avatar-list-size, 2.5rem);--tblr-avatar-status-size: .75rem;--tblr-avatar-bg: var(--tblr-bg-surface-secondary);--tblr-avatar-box-shadow-color: var(--tblr-border-color-translucent);--tblr-avatar-box-shadow: inset 0 0 0 1px var(--tblr-avatar-box-shadow-color);--tblr-avatar-font-size: 1rem;--tblr-avatar-icon-size: 1.5rem;--tblr-avatar-brand-size: 1.25rem;position:relative;width:var(--tblr-avatar-size);height:var(--tblr-avatar-size);font-size:var(--tblr-avatar-font-size);font-weight:var(--tblr-font-weight-medium);line-height:1;display:inline-flex;align-items:center;justify-content:center;color:var(--tblr-secondary);text-align:center;text-transform:uppercase;vertical-align:bottom;user-select:none;background:var(--tblr-avatar-bg) no-repeat center/cover;border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-avatar-box-shadow);transition:color .3s,background-color .3s,box-shadow .3s}.avatar .icon{width:var(--tblr-avatar-icon-size);height:var(--tblr-avatar-icon-size)}.avatar .badge{position:absolute;right:0;bottom:0;border-radius:100rem;box-shadow:0 0 0 calc(var(--tblr-avatar-status-size) / 4) var(--tblr-bg-surface)}a.avatar{cursor:pointer}a.avatar:hover{color:var(--tblr-primary);--tblr-avatar-box-shadow-color: var(--tblr-primary)}.avatar-rounded{border-radius:100rem}.avatar-xxs{--tblr-avatar-size: 1rem;--tblr-avatar-status-size: .25rem;--tblr-avatar-font-size: .5rem;--tblr-avatar-icon-size: .5rem;--tblr-avatar-brand-size: .5rem}.avatar-xxs .badge:empty{width:.25rem;height:.25rem}.avatar-xs{--tblr-avatar-size: 1.25rem;--tblr-avatar-status-size: .375rem;--tblr-avatar-font-size: .625rem;--tblr-avatar-icon-size: .75rem;--tblr-avatar-brand-size: .75rem}.avatar-xs .badge:empty{width:.375rem;height:.375rem}.avatar-sm{--tblr-avatar-size: 2rem;--tblr-avatar-status-size: .5rem;--tblr-avatar-font-size: .75rem;--tblr-avatar-icon-size: 1.5rem;--tblr-avatar-brand-size: 1rem}.avatar-sm .badge:empty{width:.5rem;height:.5rem}.avatar-md{--tblr-avatar-size: 2.5rem;--tblr-avatar-status-size: .75rem;--tblr-avatar-font-size: .875rem;--tblr-avatar-icon-size: 1.5rem;--tblr-avatar-brand-size: 1.25rem}.avatar-md .badge:empty{width:.75rem;height:.75rem}.avatar-lg{--tblr-avatar-size: 3rem;--tblr-avatar-status-size: .75rem;--tblr-avatar-font-size: 1.25rem;--tblr-avatar-icon-size: 2rem;--tblr-avatar-brand-size: 1.25rem}.avatar-lg .badge:empty{width:.75rem;height:.75rem}.avatar-xl{--tblr-avatar-size: 5rem;--tblr-avatar-status-size: 1rem;--tblr-avatar-font-size: 2rem;--tblr-avatar-icon-size: 3rem;--tblr-avatar-brand-size: 1.25rem}.avatar-xl .badge:empty{width:1rem;height:1rem}.avatar-2xl{--tblr-avatar-size: 7rem;--tblr-avatar-status-size: 1rem;--tblr-avatar-font-size: 3rem;--tblr-avatar-icon-size: 5rem;--tblr-avatar-brand-size: 2rem}.avatar-2xl .badge:empty{width:1rem;height:1rem}.avatar-list{--tblr-avatar-list-size: 2.5rem;--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.avatar-list a.avatar:hover{z-index:1}.avatar-list-stacked{display:block;--tblr-list-gap: 0}.avatar-list-stacked .avatar{margin-right:calc(-.5 * var(--tblr-avatar-size))!important;box-shadow:var(--tblr-avatar-box-shadow),0 0 0 2px var(--tblr-card-bg, var(--tblr-bg-surface))}.avatar-list-xxs{--tblr-avatar-list-size: 1rem}.avatar-list-xs{--tblr-avatar-list-size: 1.25rem}.avatar-list-sm{--tblr-avatar-list-size: 2rem}.avatar-list-md{--tblr-avatar-list-size: 2.5rem}.avatar-list-lg{--tblr-avatar-list-size: 3rem}.avatar-list-xl{--tblr-avatar-list-size: 5rem}.avatar-list-2xl{--tblr-avatar-list-size: 7rem}.avatar-upload{border:var(--tblr-border-width) dashed var(--tblr-border-color);background:var(--tblr-bg-forms);box-shadow:none;flex-direction:column;transition:color .3s,background-color .3s}@media(prefers-reduced-motion:reduce){.avatar-upload{transition:none}}.avatar-upload svg{width:1.5rem;height:1.5rem;stroke-width:1}.avatar-upload:hover{border-color:var(--tblr-primary);color:var(--tblr-primary);text-decoration:none}.avatar-upload-text{font-size:.625rem;line-height:1;margin-top:.25rem}.avatar-cover{margin-top:calc(-.5 * var(--tblr-avatar-size));box-shadow:0 0 0 .25rem var(--tblr-card-bg, var(--tblr-body-bg))}.avatar-brand{width:var(--tblr-avatar-brand-size);height:var(--tblr-avatar-brand-size);position:absolute;right:-2px;bottom:-2px;z-index:1000;background:var(--tblr-bg-surface);border-radius:var(--tblr-border-radius);border:1px solid var(--tblr-border-color)}.badge{--tblr-badge-padding-x: .5em;--tblr-badge-padding-y: .25em;--tblr-badge-font-size: .85714285em;--tblr-badge-font-weight: var(--tblr-font-weight-medium);--tblr-badge-color: var(--tblr-secondary);--tblr-badge-border-radius: var(--tblr-border-radius);--tblr-badge-icon-size: 1em;--tblr-badge-line-height: 1;display:inline-flex;padding:var(--tblr-badge-padding-y) var(--tblr-badge-padding-x);font-weight:var(--tblr-badge-font-weight);font-size:var(--tblr-badge-font-size);color:var(--tblr-badge-color);text-align:center;white-space:nowrap;justify-content:center;align-items:center;gap:.25rem;background:var(--tblr-bg-surface-secondary);overflow:hidden;user-select:none;border:var(--tblr-border-width) var(--tblr-border-style) transparent;border-radius:var(--tblr-badge-border-radius);min-width:calc(1em + var(--tblr-badge-padding-y) * 2 + 2px);letter-spacing:.04em;vertical-align:bottom;line-height:var(--tblr-badge-line-height)}a.badge{background:var(--tblr-bg-surface-secondary)}.badge .icon{width:1em;height:1em;font-size:var(--tblr-badge-icon-size);stroke-width:2}.badge:empty,.badge-dot{display:inline-block;width:10px;height:10px;min-width:0;min-height:auto;padding:0;border-radius:100rem;vertical-align:baseline}.badge-outline{background-color:transparent;border:var(--tblr-border-width) var(--tblr-border-style) currentColor}.badge-pill{border-radius:100rem}.badges-list{--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.badge-notification{position:absolute!important;top:0!important;right:0!important;transform:translate(50%,-50%);z-index:1}.badge-blink{animation:blink 2s infinite}.badge-sm{--tblr-badge-font-size: .71428571em;--tblr-badge-icon-size: 1em;--tblr-badge-padding-y: 2px;--tblr-badge-padding-x: .25rem}.badge-lg{--tblr-badge-font-size: 1em;--tblr-badge-icon-size: 1em;--tblr-badge-padding-y: .25rem;--tblr-badge-padding-x: .5rem}.badge-icononly{--tblr-badge-padding-x: 0}.breadcrumb{--tblr-breadcrumb-padding-x: 0;--tblr-breadcrumb-padding-y: 0;--tblr-breadcrumb-margin-bottom: 1rem;--tblr-breadcrumb-font-size: ;--tblr-breadcrumb-bg: ;--tblr-breadcrumb-border-radius: ;--tblr-breadcrumb-divider-color: var(--tblr-gray-500);--tblr-breadcrumb-item-padding-x: .5rem;--tblr-breadcrumb-item-active-color: inherit;--tblr-breadcrumb-item-active-font-weight: var(--tblr-font-weight-bold);--tblr-breadcrumb-item-disabled-color: var(--tblr-disabled-color);--tblr-breadcrumb-link-color: var(--tblr-link-color);display:flex;flex-wrap:wrap;font-size:var(--tblr-breadcrumb-font-size);list-style:none;background-color:var(--tblr-breadcrumb-bg);border-radius:var(--tblr-breadcrumb-border-radius);padding:0;margin:0;background:transparent}.breadcrumb a{color:var(--tblr-breadcrumb-link-color)}.breadcrumb a:hover{text-decoration:underline}.breadcrumb-muted{--tblr-breadcrumb-link-color: var(--tblr-secondary)}.breadcrumb-item.active{color:var(--tblr-breadcrumb-item-active-color);font-weight:var(--tblr-breadcrumb-item-active-font-weight)}.breadcrumb-item.active a{color:inherit;pointer-events:none}.breadcrumb-item.disabled{color:var(--tblr-breadcrumb-item-disabled-color)}.breadcrumb-item.disabled:before{color:inherit}.breadcrumb-item.disabled a{color:inherit;pointer-events:none}.breadcrumb-item+.breadcrumb-item{padding-left:var(--tblr-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item:before{float:left;padding-right:var(--tblr-breadcrumb-item-padding-x);color:var(--tblr-breadcrumb-divider-color);content:var(--tblr-breadcrumb-divider, "/")}.breadcrumb-dots{--tblr-breadcrumb-divider: "\b7"}.breadcrumb-arrows{--tblr-breadcrumb-divider: "\203a"}.breadcrumb-bullets{--tblr-breadcrumb-divider: "\2022"}.btn{--tblr-btn-icon-size: 1.25rem;--tblr-btn-icon-color: inherit;--tblr-btn-bg: var(--tblr-bg-surface);--tblr-btn-color: var(--tblr-body-color);--tblr-btn-border-color: var(--tblr-border-color);--tblr-btn-hover-bg: var(--tblr-btn-bg);--tblr-btn-hover-border-color: var(--tblr-border-active-color);--tblr-btn-active-color: var(--tblr-primary);--tblr-btn-active-bg: rgba(var(--tblr-primary-rgb), .04);--tblr-btn-active-border-color: var(--tblr-primary);display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;box-shadow:var(--tblr-btn-box-shadow);position:relative;min-width:calc(var(--tblr-btn-line-height) * 1 + var(--tblr-btn-padding-y) * 2 + var(--tblr-btn-border-width) * 2);min-height:calc(var(--tblr-btn-line-height) * 1 + var(--tblr-btn-padding-y) * 2 + var(--tblr-btn-border-width) * 2)}.btn .icon{width:var(--tblr-btn-icon-size);height:var(--tblr-btn-icon-size);min-width:var(--tblr-btn-icon-size);font-size:var(--tblr-btn-icon-size);margin:0 calc(var(--tblr-btn-padding-x) / 2) 0 calc(var(--tblr-btn-padding-x) / -4);vertical-align:bottom;color:var(--tblr-btn-icon-color)}.btn .avatar{width:var(--tblr-btn-icon-size);height:var(--tblr-btn-icon-size);margin:0 calc(var(--tblr-btn-padding-x) / 2) 0 calc(var(--tblr-btn-padding-x) / -4)}.btn .icon-right,.btn .icon-end{margin:0 calc(var(--tblr-btn-padding-x) / -4) 0 calc(var(--tblr-btn-padding-x) / 2)}.btn .badge{top:auto}.btn-check+.btn:hover{color:var(--tblr-btn-hover-color);background-color:var(--tblr-btn-hover-bg);border-color:var(--tblr-btn-hover-border-color)}.btn-link{color:#009f95;background-color:transparent;border-color:transparent;box-shadow:none}.btn-link .icon{color:inherit}.btn-link:hover{color:#006a64;border-color:transparent}.btn-primary{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-primary-fg, #ffffff);--tblr-btn-bg: var(--tblr-primary);--tblr-btn-hover-color: var(--tblr-primary-fg);--tblr-btn-hover-bg: var(--tblr-primary-darken);--tblr-btn-active-color: var(--tblr-primary-fg);--tblr-btn-active-bg: var(--tblr-primary-darken);--tblr-btn-disabled-bg: var(--tblr-primary);--tblr-btn-disabled-color: var(--tblr-primary-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-primary,.btn-outline.btn-primary{--tblr-btn-color: var(--tblr-primary);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-primary);--tblr-btn-hover-color: var(--tblr-primary-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-primary);--tblr-btn-active-color: var(--tblr-primary-fg);--tblr-btn-active-bg: var(--tblr-primary);--tblr-btn-active-border-color: var(--tblr-primary);--tblr-btn-disabled-color: var(--tblr-primary);--tblr-btn-disabled-border-color: var(--tblr-primary)}.btn-ghost-primary,.btn-ghost.btn-primary{--tblr-btn-color: var(--tblr-primary);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-primary-fg);--tblr-btn-hover-bg: var(--tblr-primary);--tblr-btn-hover-border-color: var(--tblr-primary);--tblr-btn-active-color: var(--tblr-primary-fg);--tblr-btn-active-bg: var(--tblr-primary);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-primary);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-secondary,.btn-grey,.btn-gray{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-secondary-fg, #ffffff);--tblr-btn-bg: var(--tblr-secondary);--tblr-btn-hover-color: var(--tblr-secondary-fg);--tblr-btn-hover-bg: var(--tblr-secondary-darken);--tblr-btn-active-color: var(--tblr-secondary-fg);--tblr-btn-active-bg: var(--tblr-secondary-darken);--tblr-btn-disabled-bg: var(--tblr-secondary);--tblr-btn-disabled-color: var(--tblr-secondary-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-secondary,.btn-outline.btn-secondary,.btn-outline.btn-grey,.btn-outline.btn-gray{--tblr-btn-color: var(--tblr-secondary);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-secondary);--tblr-btn-hover-color: var(--tblr-secondary-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-secondary);--tblr-btn-active-color: var(--tblr-secondary-fg);--tblr-btn-active-bg: var(--tblr-secondary);--tblr-btn-active-border-color: var(--tblr-secondary);--tblr-btn-disabled-color: var(--tblr-secondary);--tblr-btn-disabled-border-color: var(--tblr-secondary)}.btn-ghost-secondary,.btn-ghost.btn-secondary,.btn-ghost.btn-grey,.btn-ghost.btn-gray{--tblr-btn-color: var(--tblr-secondary);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-secondary-fg);--tblr-btn-hover-bg: var(--tblr-secondary);--tblr-btn-hover-border-color: var(--tblr-secondary);--tblr-btn-active-color: var(--tblr-secondary-fg);--tblr-btn-active-bg: var(--tblr-secondary);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-secondary);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-success{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-success-fg, #ffffff);--tblr-btn-bg: var(--tblr-success);--tblr-btn-hover-color: var(--tblr-success-fg);--tblr-btn-hover-bg: var(--tblr-success-darken);--tblr-btn-active-color: var(--tblr-success-fg);--tblr-btn-active-bg: var(--tblr-success-darken);--tblr-btn-disabled-bg: var(--tblr-success);--tblr-btn-disabled-color: var(--tblr-success-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-success,.btn-outline.btn-success{--tblr-btn-color: var(--tblr-success);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-success);--tblr-btn-hover-color: var(--tblr-success-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-success);--tblr-btn-active-color: var(--tblr-success-fg);--tblr-btn-active-bg: var(--tblr-success);--tblr-btn-active-border-color: var(--tblr-success);--tblr-btn-disabled-color: var(--tblr-success);--tblr-btn-disabled-border-color: var(--tblr-success)}.btn-ghost-success,.btn-ghost.btn-success{--tblr-btn-color: var(--tblr-success);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-success-fg);--tblr-btn-hover-bg: var(--tblr-success);--tblr-btn-hover-border-color: var(--tblr-success);--tblr-btn-active-color: var(--tblr-success-fg);--tblr-btn-active-bg: var(--tblr-success);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-success);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-info{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-info-fg, #ffffff);--tblr-btn-bg: var(--tblr-info);--tblr-btn-hover-color: var(--tblr-info-fg);--tblr-btn-hover-bg: var(--tblr-info-darken);--tblr-btn-active-color: var(--tblr-info-fg);--tblr-btn-active-bg: var(--tblr-info-darken);--tblr-btn-disabled-bg: var(--tblr-info);--tblr-btn-disabled-color: var(--tblr-info-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-info,.btn-outline.btn-info{--tblr-btn-color: var(--tblr-info);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-info);--tblr-btn-hover-color: var(--tblr-info-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-info);--tblr-btn-active-color: var(--tblr-info-fg);--tblr-btn-active-bg: var(--tblr-info);--tblr-btn-active-border-color: var(--tblr-info);--tblr-btn-disabled-color: var(--tblr-info);--tblr-btn-disabled-border-color: var(--tblr-info)}.btn-ghost-info,.btn-ghost.btn-info{--tblr-btn-color: var(--tblr-info);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-info-fg);--tblr-btn-hover-bg: var(--tblr-info);--tblr-btn-hover-border-color: var(--tblr-info);--tblr-btn-active-color: var(--tblr-info-fg);--tblr-btn-active-bg: var(--tblr-info);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-info);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-warning{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-warning-fg, #ffffff);--tblr-btn-bg: var(--tblr-warning);--tblr-btn-hover-color: var(--tblr-warning-fg);--tblr-btn-hover-bg: var(--tblr-warning-darken);--tblr-btn-active-color: var(--tblr-warning-fg);--tblr-btn-active-bg: var(--tblr-warning-darken);--tblr-btn-disabled-bg: var(--tblr-warning);--tblr-btn-disabled-color: var(--tblr-warning-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-warning,.btn-outline.btn-warning{--tblr-btn-color: var(--tblr-warning);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-warning);--tblr-btn-hover-color: var(--tblr-warning-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-warning);--tblr-btn-active-color: var(--tblr-warning-fg);--tblr-btn-active-bg: var(--tblr-warning);--tblr-btn-active-border-color: var(--tblr-warning);--tblr-btn-disabled-color: var(--tblr-warning);--tblr-btn-disabled-border-color: var(--tblr-warning)}.btn-ghost-warning,.btn-ghost.btn-warning{--tblr-btn-color: var(--tblr-warning);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-warning-fg);--tblr-btn-hover-bg: var(--tblr-warning);--tblr-btn-hover-border-color: var(--tblr-warning);--tblr-btn-active-color: var(--tblr-warning-fg);--tblr-btn-active-bg: var(--tblr-warning);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-warning);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-danger{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-danger-fg, #ffffff);--tblr-btn-bg: var(--tblr-danger);--tblr-btn-hover-color: var(--tblr-danger-fg);--tblr-btn-hover-bg: var(--tblr-danger-darken);--tblr-btn-active-color: var(--tblr-danger-fg);--tblr-btn-active-bg: var(--tblr-danger-darken);--tblr-btn-disabled-bg: var(--tblr-danger);--tblr-btn-disabled-color: var(--tblr-danger-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-danger,.btn-outline.btn-danger{--tblr-btn-color: var(--tblr-danger);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-danger);--tblr-btn-hover-color: var(--tblr-danger-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-danger);--tblr-btn-active-color: var(--tblr-danger-fg);--tblr-btn-active-bg: var(--tblr-danger);--tblr-btn-active-border-color: var(--tblr-danger);--tblr-btn-disabled-color: var(--tblr-danger);--tblr-btn-disabled-border-color: var(--tblr-danger)}.btn-ghost-danger,.btn-ghost.btn-danger{--tblr-btn-color: var(--tblr-danger);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-danger-fg);--tblr-btn-hover-bg: var(--tblr-danger);--tblr-btn-hover-border-color: var(--tblr-danger);--tblr-btn-active-color: var(--tblr-danger-fg);--tblr-btn-active-bg: var(--tblr-danger);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-danger);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-light,.btn-white{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-light-fg, #ffffff);--tblr-btn-bg: var(--tblr-light);--tblr-btn-hover-color: var(--tblr-light-fg);--tblr-btn-hover-bg: var(--tblr-light-darken);--tblr-btn-active-color: var(--tblr-light-fg);--tblr-btn-active-bg: var(--tblr-light-darken);--tblr-btn-disabled-bg: var(--tblr-light);--tblr-btn-disabled-color: var(--tblr-light-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-light,.btn-outline.btn-light,.btn-outline.btn-white{--tblr-btn-color: var(--tblr-light);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-light);--tblr-btn-hover-color: var(--tblr-light-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-light);--tblr-btn-active-color: var(--tblr-light-fg);--tblr-btn-active-bg: var(--tblr-light);--tblr-btn-active-border-color: var(--tblr-light);--tblr-btn-disabled-color: var(--tblr-light);--tblr-btn-disabled-border-color: var(--tblr-light)}.btn-ghost-light,.btn-ghost.btn-light,.btn-ghost.btn-white{--tblr-btn-color: var(--tblr-light);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-light-fg);--tblr-btn-hover-bg: var(--tblr-light);--tblr-btn-hover-border-color: var(--tblr-light);--tblr-btn-active-color: var(--tblr-light-fg);--tblr-btn-active-bg: var(--tblr-light);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-light);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-dark,.btn-black{--tblr-btn-border-color: var(--tblr-dark-mode-border-color);--tblr-btn-hover-border-color: var(--tblr-dark-mode-border-active-color);--tblr-btn-active-border-color: var(--tblr-dark-mode-border-active-color);--tblr-btn-color: var(--tblr-dark-fg, #ffffff);--tblr-btn-bg: var(--tblr-dark);--tblr-btn-hover-color: var(--tblr-dark-fg);--tblr-btn-hover-bg: var(--tblr-dark-darken);--tblr-btn-active-color: var(--tblr-dark-fg);--tblr-btn-active-bg: var(--tblr-dark-darken);--tblr-btn-disabled-bg: var(--tblr-dark);--tblr-btn-disabled-color: var(--tblr-dark-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-dark,.btn-outline.btn-dark,.btn-outline.btn-black{--tblr-btn-color: var(--tblr-dark);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-dark);--tblr-btn-hover-color: var(--tblr-dark-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-dark);--tblr-btn-active-color: var(--tblr-dark-fg);--tblr-btn-active-bg: var(--tblr-dark);--tblr-btn-active-border-color: var(--tblr-dark);--tblr-btn-disabled-color: var(--tblr-dark);--tblr-btn-disabled-border-color: var(--tblr-dark)}.btn-ghost-dark,.btn-ghost.btn-dark,.btn-ghost.btn-black{--tblr-btn-color: var(--tblr-dark);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-dark-fg);--tblr-btn-hover-bg: var(--tblr-dark);--tblr-btn-hover-border-color: var(--tblr-dark);--tblr-btn-active-color: var(--tblr-dark-fg);--tblr-btn-active-bg: var(--tblr-dark);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-dark);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-muted{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-muted-fg, #ffffff);--tblr-btn-bg: var(--tblr-muted);--tblr-btn-hover-color: var(--tblr-muted-fg);--tblr-btn-hover-bg: var(--tblr-muted-darken);--tblr-btn-active-color: var(--tblr-muted-fg);--tblr-btn-active-bg: var(--tblr-muted-darken);--tblr-btn-disabled-bg: var(--tblr-muted);--tblr-btn-disabled-color: var(--tblr-muted-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-muted,.btn-outline.btn-muted{--tblr-btn-color: var(--tblr-muted);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-muted);--tblr-btn-hover-color: var(--tblr-muted-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-muted);--tblr-btn-active-color: var(--tblr-muted-fg);--tblr-btn-active-bg: var(--tblr-muted);--tblr-btn-active-border-color: var(--tblr-muted);--tblr-btn-disabled-color: var(--tblr-muted);--tblr-btn-disabled-border-color: var(--tblr-muted)}.btn-ghost-muted,.btn-ghost.btn-muted{--tblr-btn-color: var(--tblr-muted);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-muted-fg);--tblr-btn-hover-bg: var(--tblr-muted);--tblr-btn-hover-border-color: var(--tblr-muted);--tblr-btn-active-color: var(--tblr-muted-fg);--tblr-btn-active-bg: var(--tblr-muted);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-muted);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-blue{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-blue-fg, #ffffff);--tblr-btn-bg: var(--tblr-blue);--tblr-btn-hover-color: var(--tblr-blue-fg);--tblr-btn-hover-bg: var(--tblr-blue-darken);--tblr-btn-active-color: var(--tblr-blue-fg);--tblr-btn-active-bg: var(--tblr-blue-darken);--tblr-btn-disabled-bg: var(--tblr-blue);--tblr-btn-disabled-color: var(--tblr-blue-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-blue,.btn-outline.btn-blue{--tblr-btn-color: var(--tblr-blue);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-blue);--tblr-btn-hover-color: var(--tblr-blue-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-blue);--tblr-btn-active-color: var(--tblr-blue-fg);--tblr-btn-active-bg: var(--tblr-blue);--tblr-btn-active-border-color: var(--tblr-blue);--tblr-btn-disabled-color: var(--tblr-blue);--tblr-btn-disabled-border-color: var(--tblr-blue)}.btn-ghost-blue,.btn-ghost.btn-blue{--tblr-btn-color: var(--tblr-blue);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-blue-fg);--tblr-btn-hover-bg: var(--tblr-blue);--tblr-btn-hover-border-color: var(--tblr-blue);--tblr-btn-active-color: var(--tblr-blue-fg);--tblr-btn-active-bg: var(--tblr-blue);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-blue);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-azure{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-azure-fg, #ffffff);--tblr-btn-bg: var(--tblr-azure);--tblr-btn-hover-color: var(--tblr-azure-fg);--tblr-btn-hover-bg: var(--tblr-azure-darken);--tblr-btn-active-color: var(--tblr-azure-fg);--tblr-btn-active-bg: var(--tblr-azure-darken);--tblr-btn-disabled-bg: var(--tblr-azure);--tblr-btn-disabled-color: var(--tblr-azure-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-azure,.btn-outline.btn-azure{--tblr-btn-color: var(--tblr-azure);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-azure);--tblr-btn-hover-color: var(--tblr-azure-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-azure);--tblr-btn-active-color: var(--tblr-azure-fg);--tblr-btn-active-bg: var(--tblr-azure);--tblr-btn-active-border-color: var(--tblr-azure);--tblr-btn-disabled-color: var(--tblr-azure);--tblr-btn-disabled-border-color: var(--tblr-azure)}.btn-ghost-azure,.btn-ghost.btn-azure{--tblr-btn-color: var(--tblr-azure);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-azure-fg);--tblr-btn-hover-bg: var(--tblr-azure);--tblr-btn-hover-border-color: var(--tblr-azure);--tblr-btn-active-color: var(--tblr-azure-fg);--tblr-btn-active-bg: var(--tblr-azure);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-azure);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-indigo{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-indigo-fg, #ffffff);--tblr-btn-bg: var(--tblr-indigo);--tblr-btn-hover-color: var(--tblr-indigo-fg);--tblr-btn-hover-bg: var(--tblr-indigo-darken);--tblr-btn-active-color: var(--tblr-indigo-fg);--tblr-btn-active-bg: var(--tblr-indigo-darken);--tblr-btn-disabled-bg: var(--tblr-indigo);--tblr-btn-disabled-color: var(--tblr-indigo-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-indigo,.btn-outline.btn-indigo{--tblr-btn-color: var(--tblr-indigo);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-indigo);--tblr-btn-hover-color: var(--tblr-indigo-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-indigo);--tblr-btn-active-color: var(--tblr-indigo-fg);--tblr-btn-active-bg: var(--tblr-indigo);--tblr-btn-active-border-color: var(--tblr-indigo);--tblr-btn-disabled-color: var(--tblr-indigo);--tblr-btn-disabled-border-color: var(--tblr-indigo)}.btn-ghost-indigo,.btn-ghost.btn-indigo{--tblr-btn-color: var(--tblr-indigo);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-indigo-fg);--tblr-btn-hover-bg: var(--tblr-indigo);--tblr-btn-hover-border-color: var(--tblr-indigo);--tblr-btn-active-color: var(--tblr-indigo-fg);--tblr-btn-active-bg: var(--tblr-indigo);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-indigo);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-purple{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-purple-fg, #ffffff);--tblr-btn-bg: var(--tblr-purple);--tblr-btn-hover-color: var(--tblr-purple-fg);--tblr-btn-hover-bg: var(--tblr-purple-darken);--tblr-btn-active-color: var(--tblr-purple-fg);--tblr-btn-active-bg: var(--tblr-purple-darken);--tblr-btn-disabled-bg: var(--tblr-purple);--tblr-btn-disabled-color: var(--tblr-purple-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-purple,.btn-outline.btn-purple{--tblr-btn-color: var(--tblr-purple);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-purple);--tblr-btn-hover-color: var(--tblr-purple-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-purple);--tblr-btn-active-color: var(--tblr-purple-fg);--tblr-btn-active-bg: var(--tblr-purple);--tblr-btn-active-border-color: var(--tblr-purple);--tblr-btn-disabled-color: var(--tblr-purple);--tblr-btn-disabled-border-color: var(--tblr-purple)}.btn-ghost-purple,.btn-ghost.btn-purple{--tblr-btn-color: var(--tblr-purple);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-purple-fg);--tblr-btn-hover-bg: var(--tblr-purple);--tblr-btn-hover-border-color: var(--tblr-purple);--tblr-btn-active-color: var(--tblr-purple-fg);--tblr-btn-active-bg: var(--tblr-purple);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-purple);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-pink{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-pink-fg, #ffffff);--tblr-btn-bg: var(--tblr-pink);--tblr-btn-hover-color: var(--tblr-pink-fg);--tblr-btn-hover-bg: var(--tblr-pink-darken);--tblr-btn-active-color: var(--tblr-pink-fg);--tblr-btn-active-bg: var(--tblr-pink-darken);--tblr-btn-disabled-bg: var(--tblr-pink);--tblr-btn-disabled-color: var(--tblr-pink-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-pink,.btn-outline.btn-pink{--tblr-btn-color: var(--tblr-pink);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-pink);--tblr-btn-hover-color: var(--tblr-pink-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-pink);--tblr-btn-active-color: var(--tblr-pink-fg);--tblr-btn-active-bg: var(--tblr-pink);--tblr-btn-active-border-color: var(--tblr-pink);--tblr-btn-disabled-color: var(--tblr-pink);--tblr-btn-disabled-border-color: var(--tblr-pink)}.btn-ghost-pink,.btn-ghost.btn-pink{--tblr-btn-color: var(--tblr-pink);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-pink-fg);--tblr-btn-hover-bg: var(--tblr-pink);--tblr-btn-hover-border-color: var(--tblr-pink);--tblr-btn-active-color: var(--tblr-pink-fg);--tblr-btn-active-bg: var(--tblr-pink);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-pink);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-red{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-red-fg, #ffffff);--tblr-btn-bg: var(--tblr-red);--tblr-btn-hover-color: var(--tblr-red-fg);--tblr-btn-hover-bg: var(--tblr-red-darken);--tblr-btn-active-color: var(--tblr-red-fg);--tblr-btn-active-bg: var(--tblr-red-darken);--tblr-btn-disabled-bg: var(--tblr-red);--tblr-btn-disabled-color: var(--tblr-red-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-red,.btn-outline.btn-red{--tblr-btn-color: var(--tblr-red);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-red);--tblr-btn-hover-color: var(--tblr-red-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-red);--tblr-btn-active-color: var(--tblr-red-fg);--tblr-btn-active-bg: var(--tblr-red);--tblr-btn-active-border-color: var(--tblr-red);--tblr-btn-disabled-color: var(--tblr-red);--tblr-btn-disabled-border-color: var(--tblr-red)}.btn-ghost-red,.btn-ghost.btn-red{--tblr-btn-color: var(--tblr-red);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-red-fg);--tblr-btn-hover-bg: var(--tblr-red);--tblr-btn-hover-border-color: var(--tblr-red);--tblr-btn-active-color: var(--tblr-red-fg);--tblr-btn-active-bg: var(--tblr-red);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-red);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-orange{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-orange-fg, #ffffff);--tblr-btn-bg: var(--tblr-orange);--tblr-btn-hover-color: var(--tblr-orange-fg);--tblr-btn-hover-bg: var(--tblr-orange-darken);--tblr-btn-active-color: var(--tblr-orange-fg);--tblr-btn-active-bg: var(--tblr-orange-darken);--tblr-btn-disabled-bg: var(--tblr-orange);--tblr-btn-disabled-color: var(--tblr-orange-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-orange,.btn-outline.btn-orange{--tblr-btn-color: var(--tblr-orange);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-orange);--tblr-btn-hover-color: var(--tblr-orange-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-orange);--tblr-btn-active-color: var(--tblr-orange-fg);--tblr-btn-active-bg: var(--tblr-orange);--tblr-btn-active-border-color: var(--tblr-orange);--tblr-btn-disabled-color: var(--tblr-orange);--tblr-btn-disabled-border-color: var(--tblr-orange)}.btn-ghost-orange,.btn-ghost.btn-orange{--tblr-btn-color: var(--tblr-orange);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-orange-fg);--tblr-btn-hover-bg: var(--tblr-orange);--tblr-btn-hover-border-color: var(--tblr-orange);--tblr-btn-active-color: var(--tblr-orange-fg);--tblr-btn-active-bg: var(--tblr-orange);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-orange);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-yellow{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-yellow-fg, #ffffff);--tblr-btn-bg: var(--tblr-yellow);--tblr-btn-hover-color: var(--tblr-yellow-fg);--tblr-btn-hover-bg: var(--tblr-yellow-darken);--tblr-btn-active-color: var(--tblr-yellow-fg);--tblr-btn-active-bg: var(--tblr-yellow-darken);--tblr-btn-disabled-bg: var(--tblr-yellow);--tblr-btn-disabled-color: var(--tblr-yellow-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-yellow,.btn-outline.btn-yellow{--tblr-btn-color: var(--tblr-yellow);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-yellow);--tblr-btn-hover-color: var(--tblr-yellow-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-yellow);--tblr-btn-active-color: var(--tblr-yellow-fg);--tblr-btn-active-bg: var(--tblr-yellow);--tblr-btn-active-border-color: var(--tblr-yellow);--tblr-btn-disabled-color: var(--tblr-yellow);--tblr-btn-disabled-border-color: var(--tblr-yellow)}.btn-ghost-yellow,.btn-ghost.btn-yellow{--tblr-btn-color: var(--tblr-yellow);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-yellow-fg);--tblr-btn-hover-bg: var(--tblr-yellow);--tblr-btn-hover-border-color: var(--tblr-yellow);--tblr-btn-active-color: var(--tblr-yellow-fg);--tblr-btn-active-bg: var(--tblr-yellow);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-yellow);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-lime{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-lime-fg, #ffffff);--tblr-btn-bg: var(--tblr-lime);--tblr-btn-hover-color: var(--tblr-lime-fg);--tblr-btn-hover-bg: var(--tblr-lime-darken);--tblr-btn-active-color: var(--tblr-lime-fg);--tblr-btn-active-bg: var(--tblr-lime-darken);--tblr-btn-disabled-bg: var(--tblr-lime);--tblr-btn-disabled-color: var(--tblr-lime-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-lime,.btn-outline.btn-lime{--tblr-btn-color: var(--tblr-lime);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-lime);--tblr-btn-hover-color: var(--tblr-lime-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-lime);--tblr-btn-active-color: var(--tblr-lime-fg);--tblr-btn-active-bg: var(--tblr-lime);--tblr-btn-active-border-color: var(--tblr-lime);--tblr-btn-disabled-color: var(--tblr-lime);--tblr-btn-disabled-border-color: var(--tblr-lime)}.btn-ghost-lime,.btn-ghost.btn-lime{--tblr-btn-color: var(--tblr-lime);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-lime-fg);--tblr-btn-hover-bg: var(--tblr-lime);--tblr-btn-hover-border-color: var(--tblr-lime);--tblr-btn-active-color: var(--tblr-lime-fg);--tblr-btn-active-bg: var(--tblr-lime);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-lime);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-green{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-green-fg, #ffffff);--tblr-btn-bg: var(--tblr-green);--tblr-btn-hover-color: var(--tblr-green-fg);--tblr-btn-hover-bg: var(--tblr-green-darken);--tblr-btn-active-color: var(--tblr-green-fg);--tblr-btn-active-bg: var(--tblr-green-darken);--tblr-btn-disabled-bg: var(--tblr-green);--tblr-btn-disabled-color: var(--tblr-green-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-green,.btn-outline.btn-green{--tblr-btn-color: var(--tblr-green);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-green);--tblr-btn-hover-color: var(--tblr-green-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-green);--tblr-btn-active-color: var(--tblr-green-fg);--tblr-btn-active-bg: var(--tblr-green);--tblr-btn-active-border-color: var(--tblr-green);--tblr-btn-disabled-color: var(--tblr-green);--tblr-btn-disabled-border-color: var(--tblr-green)}.btn-ghost-green,.btn-ghost.btn-green{--tblr-btn-color: var(--tblr-green);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-green-fg);--tblr-btn-hover-bg: var(--tblr-green);--tblr-btn-hover-border-color: var(--tblr-green);--tblr-btn-active-color: var(--tblr-green-fg);--tblr-btn-active-bg: var(--tblr-green);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-green);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-teal{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-teal-fg, #ffffff);--tblr-btn-bg: var(--tblr-teal);--tblr-btn-hover-color: var(--tblr-teal-fg);--tblr-btn-hover-bg: var(--tblr-teal-darken);--tblr-btn-active-color: var(--tblr-teal-fg);--tblr-btn-active-bg: var(--tblr-teal-darken);--tblr-btn-disabled-bg: var(--tblr-teal);--tblr-btn-disabled-color: var(--tblr-teal-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-teal,.btn-outline.btn-teal{--tblr-btn-color: var(--tblr-teal);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-teal);--tblr-btn-hover-color: var(--tblr-teal-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-teal);--tblr-btn-active-color: var(--tblr-teal-fg);--tblr-btn-active-bg: var(--tblr-teal);--tblr-btn-active-border-color: var(--tblr-teal);--tblr-btn-disabled-color: var(--tblr-teal);--tblr-btn-disabled-border-color: var(--tblr-teal)}.btn-ghost-teal,.btn-ghost.btn-teal{--tblr-btn-color: var(--tblr-teal);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-teal-fg);--tblr-btn-hover-bg: var(--tblr-teal);--tblr-btn-hover-border-color: var(--tblr-teal);--tblr-btn-active-color: var(--tblr-teal-fg);--tblr-btn-active-bg: var(--tblr-teal);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-teal);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-cyan{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-cyan-fg, #ffffff);--tblr-btn-bg: var(--tblr-cyan);--tblr-btn-hover-color: var(--tblr-cyan-fg);--tblr-btn-hover-bg: var(--tblr-cyan-darken);--tblr-btn-active-color: var(--tblr-cyan-fg);--tblr-btn-active-bg: var(--tblr-cyan-darken);--tblr-btn-disabled-bg: var(--tblr-cyan);--tblr-btn-disabled-color: var(--tblr-cyan-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-cyan,.btn-outline.btn-cyan{--tblr-btn-color: var(--tblr-cyan);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-cyan);--tblr-btn-hover-color: var(--tblr-cyan-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-cyan);--tblr-btn-active-color: var(--tblr-cyan-fg);--tblr-btn-active-bg: var(--tblr-cyan);--tblr-btn-active-border-color: var(--tblr-cyan);--tblr-btn-disabled-color: var(--tblr-cyan);--tblr-btn-disabled-border-color: var(--tblr-cyan)}.btn-ghost-cyan,.btn-ghost.btn-cyan{--tblr-btn-color: var(--tblr-cyan);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-cyan-fg);--tblr-btn-hover-bg: var(--tblr-cyan);--tblr-btn-hover-border-color: var(--tblr-cyan);--tblr-btn-active-color: var(--tblr-cyan-fg);--tblr-btn-active-bg: var(--tblr-cyan);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-cyan);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-x{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-x-fg, #ffffff);--tblr-btn-bg: var(--tblr-x);--tblr-btn-hover-color: var(--tblr-x-fg);--tblr-btn-hover-bg: var(--tblr-x-darken);--tblr-btn-active-color: var(--tblr-x-fg);--tblr-btn-active-bg: var(--tblr-x-darken);--tblr-btn-disabled-bg: var(--tblr-x);--tblr-btn-disabled-color: var(--tblr-x-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-x,.btn-outline.btn-x{--tblr-btn-color: var(--tblr-x);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-x);--tblr-btn-hover-color: var(--tblr-x-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-x);--tblr-btn-active-color: var(--tblr-x-fg);--tblr-btn-active-bg: var(--tblr-x);--tblr-btn-active-border-color: var(--tblr-x);--tblr-btn-disabled-color: var(--tblr-x);--tblr-btn-disabled-border-color: var(--tblr-x)}.btn-ghost-x,.btn-ghost.btn-x{--tblr-btn-color: var(--tblr-x);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-x-fg);--tblr-btn-hover-bg: var(--tblr-x);--tblr-btn-hover-border-color: var(--tblr-x);--tblr-btn-active-color: var(--tblr-x-fg);--tblr-btn-active-bg: var(--tblr-x);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-x);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-facebook{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-facebook-fg, #ffffff);--tblr-btn-bg: var(--tblr-facebook);--tblr-btn-hover-color: var(--tblr-facebook-fg);--tblr-btn-hover-bg: var(--tblr-facebook-darken);--tblr-btn-active-color: var(--tblr-facebook-fg);--tblr-btn-active-bg: var(--tblr-facebook-darken);--tblr-btn-disabled-bg: var(--tblr-facebook);--tblr-btn-disabled-color: var(--tblr-facebook-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-facebook,.btn-outline.btn-facebook{--tblr-btn-color: var(--tblr-facebook);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-facebook);--tblr-btn-hover-color: var(--tblr-facebook-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-facebook);--tblr-btn-active-color: var(--tblr-facebook-fg);--tblr-btn-active-bg: var(--tblr-facebook);--tblr-btn-active-border-color: var(--tblr-facebook);--tblr-btn-disabled-color: var(--tblr-facebook);--tblr-btn-disabled-border-color: var(--tblr-facebook)}.btn-ghost-facebook,.btn-ghost.btn-facebook{--tblr-btn-color: var(--tblr-facebook);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-facebook-fg);--tblr-btn-hover-bg: var(--tblr-facebook);--tblr-btn-hover-border-color: var(--tblr-facebook);--tblr-btn-active-color: var(--tblr-facebook-fg);--tblr-btn-active-bg: var(--tblr-facebook);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-facebook);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-twitter{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-twitter-fg, #ffffff);--tblr-btn-bg: var(--tblr-twitter);--tblr-btn-hover-color: var(--tblr-twitter-fg);--tblr-btn-hover-bg: var(--tblr-twitter-darken);--tblr-btn-active-color: var(--tblr-twitter-fg);--tblr-btn-active-bg: var(--tblr-twitter-darken);--tblr-btn-disabled-bg: var(--tblr-twitter);--tblr-btn-disabled-color: var(--tblr-twitter-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-twitter,.btn-outline.btn-twitter{--tblr-btn-color: var(--tblr-twitter);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-twitter);--tblr-btn-hover-color: var(--tblr-twitter-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-twitter);--tblr-btn-active-color: var(--tblr-twitter-fg);--tblr-btn-active-bg: var(--tblr-twitter);--tblr-btn-active-border-color: var(--tblr-twitter);--tblr-btn-disabled-color: var(--tblr-twitter);--tblr-btn-disabled-border-color: var(--tblr-twitter)}.btn-ghost-twitter,.btn-ghost.btn-twitter{--tblr-btn-color: var(--tblr-twitter);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-twitter-fg);--tblr-btn-hover-bg: var(--tblr-twitter);--tblr-btn-hover-border-color: var(--tblr-twitter);--tblr-btn-active-color: var(--tblr-twitter-fg);--tblr-btn-active-bg: var(--tblr-twitter);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-twitter);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-linkedin{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-linkedin-fg, #ffffff);--tblr-btn-bg: var(--tblr-linkedin);--tblr-btn-hover-color: var(--tblr-linkedin-fg);--tblr-btn-hover-bg: var(--tblr-linkedin-darken);--tblr-btn-active-color: var(--tblr-linkedin-fg);--tblr-btn-active-bg: var(--tblr-linkedin-darken);--tblr-btn-disabled-bg: var(--tblr-linkedin);--tblr-btn-disabled-color: var(--tblr-linkedin-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-linkedin,.btn-outline.btn-linkedin{--tblr-btn-color: var(--tblr-linkedin);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-linkedin);--tblr-btn-hover-color: var(--tblr-linkedin-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-linkedin);--tblr-btn-active-color: var(--tblr-linkedin-fg);--tblr-btn-active-bg: var(--tblr-linkedin);--tblr-btn-active-border-color: var(--tblr-linkedin);--tblr-btn-disabled-color: var(--tblr-linkedin);--tblr-btn-disabled-border-color: var(--tblr-linkedin)}.btn-ghost-linkedin,.btn-ghost.btn-linkedin{--tblr-btn-color: var(--tblr-linkedin);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-linkedin-fg);--tblr-btn-hover-bg: var(--tblr-linkedin);--tblr-btn-hover-border-color: var(--tblr-linkedin);--tblr-btn-active-color: var(--tblr-linkedin-fg);--tblr-btn-active-bg: var(--tblr-linkedin);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-linkedin);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-google{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-google-fg, #ffffff);--tblr-btn-bg: var(--tblr-google);--tblr-btn-hover-color: var(--tblr-google-fg);--tblr-btn-hover-bg: var(--tblr-google-darken);--tblr-btn-active-color: var(--tblr-google-fg);--tblr-btn-active-bg: var(--tblr-google-darken);--tblr-btn-disabled-bg: var(--tblr-google);--tblr-btn-disabled-color: var(--tblr-google-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-google,.btn-outline.btn-google{--tblr-btn-color: var(--tblr-google);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-google);--tblr-btn-hover-color: var(--tblr-google-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-google);--tblr-btn-active-color: var(--tblr-google-fg);--tblr-btn-active-bg: var(--tblr-google);--tblr-btn-active-border-color: var(--tblr-google);--tblr-btn-disabled-color: var(--tblr-google);--tblr-btn-disabled-border-color: var(--tblr-google)}.btn-ghost-google,.btn-ghost.btn-google{--tblr-btn-color: var(--tblr-google);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-google-fg);--tblr-btn-hover-bg: var(--tblr-google);--tblr-btn-hover-border-color: var(--tblr-google);--tblr-btn-active-color: var(--tblr-google-fg);--tblr-btn-active-bg: var(--tblr-google);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-google);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-youtube{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-youtube-fg, #ffffff);--tblr-btn-bg: var(--tblr-youtube);--tblr-btn-hover-color: var(--tblr-youtube-fg);--tblr-btn-hover-bg: var(--tblr-youtube-darken);--tblr-btn-active-color: var(--tblr-youtube-fg);--tblr-btn-active-bg: var(--tblr-youtube-darken);--tblr-btn-disabled-bg: var(--tblr-youtube);--tblr-btn-disabled-color: var(--tblr-youtube-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-youtube,.btn-outline.btn-youtube{--tblr-btn-color: var(--tblr-youtube);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-youtube);--tblr-btn-hover-color: var(--tblr-youtube-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-youtube);--tblr-btn-active-color: var(--tblr-youtube-fg);--tblr-btn-active-bg: var(--tblr-youtube);--tblr-btn-active-border-color: var(--tblr-youtube);--tblr-btn-disabled-color: var(--tblr-youtube);--tblr-btn-disabled-border-color: var(--tblr-youtube)}.btn-ghost-youtube,.btn-ghost.btn-youtube{--tblr-btn-color: var(--tblr-youtube);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-youtube-fg);--tblr-btn-hover-bg: var(--tblr-youtube);--tblr-btn-hover-border-color: var(--tblr-youtube);--tblr-btn-active-color: var(--tblr-youtube-fg);--tblr-btn-active-bg: var(--tblr-youtube);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-youtube);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-vimeo{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-vimeo-fg, #ffffff);--tblr-btn-bg: var(--tblr-vimeo);--tblr-btn-hover-color: var(--tblr-vimeo-fg);--tblr-btn-hover-bg: var(--tblr-vimeo-darken);--tblr-btn-active-color: var(--tblr-vimeo-fg);--tblr-btn-active-bg: var(--tblr-vimeo-darken);--tblr-btn-disabled-bg: var(--tblr-vimeo);--tblr-btn-disabled-color: var(--tblr-vimeo-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-vimeo,.btn-outline.btn-vimeo{--tblr-btn-color: var(--tblr-vimeo);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-vimeo);--tblr-btn-hover-color: var(--tblr-vimeo-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-vimeo);--tblr-btn-active-color: var(--tblr-vimeo-fg);--tblr-btn-active-bg: var(--tblr-vimeo);--tblr-btn-active-border-color: var(--tblr-vimeo);--tblr-btn-disabled-color: var(--tblr-vimeo);--tblr-btn-disabled-border-color: var(--tblr-vimeo)}.btn-ghost-vimeo,.btn-ghost.btn-vimeo{--tblr-btn-color: var(--tblr-vimeo);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-vimeo-fg);--tblr-btn-hover-bg: var(--tblr-vimeo);--tblr-btn-hover-border-color: var(--tblr-vimeo);--tblr-btn-active-color: var(--tblr-vimeo-fg);--tblr-btn-active-bg: var(--tblr-vimeo);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-vimeo);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-dribbble{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-dribbble-fg, #ffffff);--tblr-btn-bg: var(--tblr-dribbble);--tblr-btn-hover-color: var(--tblr-dribbble-fg);--tblr-btn-hover-bg: var(--tblr-dribbble-darken);--tblr-btn-active-color: var(--tblr-dribbble-fg);--tblr-btn-active-bg: var(--tblr-dribbble-darken);--tblr-btn-disabled-bg: var(--tblr-dribbble);--tblr-btn-disabled-color: var(--tblr-dribbble-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-dribbble,.btn-outline.btn-dribbble{--tblr-btn-color: var(--tblr-dribbble);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-dribbble);--tblr-btn-hover-color: var(--tblr-dribbble-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-dribbble);--tblr-btn-active-color: var(--tblr-dribbble-fg);--tblr-btn-active-bg: var(--tblr-dribbble);--tblr-btn-active-border-color: var(--tblr-dribbble);--tblr-btn-disabled-color: var(--tblr-dribbble);--tblr-btn-disabled-border-color: var(--tblr-dribbble)}.btn-ghost-dribbble,.btn-ghost.btn-dribbble{--tblr-btn-color: var(--tblr-dribbble);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-dribbble-fg);--tblr-btn-hover-bg: var(--tblr-dribbble);--tblr-btn-hover-border-color: var(--tblr-dribbble);--tblr-btn-active-color: var(--tblr-dribbble-fg);--tblr-btn-active-bg: var(--tblr-dribbble);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-dribbble);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-github{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-github-fg, #ffffff);--tblr-btn-bg: var(--tblr-github);--tblr-btn-hover-color: var(--tblr-github-fg);--tblr-btn-hover-bg: var(--tblr-github-darken);--tblr-btn-active-color: var(--tblr-github-fg);--tblr-btn-active-bg: var(--tblr-github-darken);--tblr-btn-disabled-bg: var(--tblr-github);--tblr-btn-disabled-color: var(--tblr-github-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-github,.btn-outline.btn-github{--tblr-btn-color: var(--tblr-github);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-github);--tblr-btn-hover-color: var(--tblr-github-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-github);--tblr-btn-active-color: var(--tblr-github-fg);--tblr-btn-active-bg: var(--tblr-github);--tblr-btn-active-border-color: var(--tblr-github);--tblr-btn-disabled-color: var(--tblr-github);--tblr-btn-disabled-border-color: var(--tblr-github)}.btn-ghost-github,.btn-ghost.btn-github{--tblr-btn-color: var(--tblr-github);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-github-fg);--tblr-btn-hover-bg: var(--tblr-github);--tblr-btn-hover-border-color: var(--tblr-github);--tblr-btn-active-color: var(--tblr-github-fg);--tblr-btn-active-bg: var(--tblr-github);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-github);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-instagram{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-instagram-fg, #ffffff);--tblr-btn-bg: var(--tblr-instagram);--tblr-btn-hover-color: var(--tblr-instagram-fg);--tblr-btn-hover-bg: var(--tblr-instagram-darken);--tblr-btn-active-color: var(--tblr-instagram-fg);--tblr-btn-active-bg: var(--tblr-instagram-darken);--tblr-btn-disabled-bg: var(--tblr-instagram);--tblr-btn-disabled-color: var(--tblr-instagram-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-instagram,.btn-outline.btn-instagram{--tblr-btn-color: var(--tblr-instagram);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-instagram);--tblr-btn-hover-color: var(--tblr-instagram-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-instagram);--tblr-btn-active-color: var(--tblr-instagram-fg);--tblr-btn-active-bg: var(--tblr-instagram);--tblr-btn-active-border-color: var(--tblr-instagram);--tblr-btn-disabled-color: var(--tblr-instagram);--tblr-btn-disabled-border-color: var(--tblr-instagram)}.btn-ghost-instagram,.btn-ghost.btn-instagram{--tblr-btn-color: var(--tblr-instagram);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-instagram-fg);--tblr-btn-hover-bg: var(--tblr-instagram);--tblr-btn-hover-border-color: var(--tblr-instagram);--tblr-btn-active-color: var(--tblr-instagram-fg);--tblr-btn-active-bg: var(--tblr-instagram);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-instagram);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-pinterest{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-pinterest-fg, #ffffff);--tblr-btn-bg: var(--tblr-pinterest);--tblr-btn-hover-color: var(--tblr-pinterest-fg);--tblr-btn-hover-bg: var(--tblr-pinterest-darken);--tblr-btn-active-color: var(--tblr-pinterest-fg);--tblr-btn-active-bg: var(--tblr-pinterest-darken);--tblr-btn-disabled-bg: var(--tblr-pinterest);--tblr-btn-disabled-color: var(--tblr-pinterest-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-pinterest,.btn-outline.btn-pinterest{--tblr-btn-color: var(--tblr-pinterest);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-pinterest);--tblr-btn-hover-color: var(--tblr-pinterest-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-pinterest);--tblr-btn-active-color: var(--tblr-pinterest-fg);--tblr-btn-active-bg: var(--tblr-pinterest);--tblr-btn-active-border-color: var(--tblr-pinterest);--tblr-btn-disabled-color: var(--tblr-pinterest);--tblr-btn-disabled-border-color: var(--tblr-pinterest)}.btn-ghost-pinterest,.btn-ghost.btn-pinterest{--tblr-btn-color: var(--tblr-pinterest);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-pinterest-fg);--tblr-btn-hover-bg: var(--tblr-pinterest);--tblr-btn-hover-border-color: var(--tblr-pinterest);--tblr-btn-active-color: var(--tblr-pinterest-fg);--tblr-btn-active-bg: var(--tblr-pinterest);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-pinterest);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-vk{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-vk-fg, #ffffff);--tblr-btn-bg: var(--tblr-vk);--tblr-btn-hover-color: var(--tblr-vk-fg);--tblr-btn-hover-bg: var(--tblr-vk-darken);--tblr-btn-active-color: var(--tblr-vk-fg);--tblr-btn-active-bg: var(--tblr-vk-darken);--tblr-btn-disabled-bg: var(--tblr-vk);--tblr-btn-disabled-color: var(--tblr-vk-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-vk,.btn-outline.btn-vk{--tblr-btn-color: var(--tblr-vk);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-vk);--tblr-btn-hover-color: var(--tblr-vk-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-vk);--tblr-btn-active-color: var(--tblr-vk-fg);--tblr-btn-active-bg: var(--tblr-vk);--tblr-btn-active-border-color: var(--tblr-vk);--tblr-btn-disabled-color: var(--tblr-vk);--tblr-btn-disabled-border-color: var(--tblr-vk)}.btn-ghost-vk,.btn-ghost.btn-vk{--tblr-btn-color: var(--tblr-vk);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-vk-fg);--tblr-btn-hover-bg: var(--tblr-vk);--tblr-btn-hover-border-color: var(--tblr-vk);--tblr-btn-active-color: var(--tblr-vk-fg);--tblr-btn-active-bg: var(--tblr-vk);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-vk);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-rss{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-rss-fg, #ffffff);--tblr-btn-bg: var(--tblr-rss);--tblr-btn-hover-color: var(--tblr-rss-fg);--tblr-btn-hover-bg: var(--tblr-rss-darken);--tblr-btn-active-color: var(--tblr-rss-fg);--tblr-btn-active-bg: var(--tblr-rss-darken);--tblr-btn-disabled-bg: var(--tblr-rss);--tblr-btn-disabled-color: var(--tblr-rss-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-rss,.btn-outline.btn-rss{--tblr-btn-color: var(--tblr-rss);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-rss);--tblr-btn-hover-color: var(--tblr-rss-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-rss);--tblr-btn-active-color: var(--tblr-rss-fg);--tblr-btn-active-bg: var(--tblr-rss);--tblr-btn-active-border-color: var(--tblr-rss);--tblr-btn-disabled-color: var(--tblr-rss);--tblr-btn-disabled-border-color: var(--tblr-rss)}.btn-ghost-rss,.btn-ghost.btn-rss{--tblr-btn-color: var(--tblr-rss);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-rss-fg);--tblr-btn-hover-bg: var(--tblr-rss);--tblr-btn-hover-border-color: var(--tblr-rss);--tblr-btn-active-color: var(--tblr-rss-fg);--tblr-btn-active-bg: var(--tblr-rss);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-rss);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-flickr{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-flickr-fg, #ffffff);--tblr-btn-bg: var(--tblr-flickr);--tblr-btn-hover-color: var(--tblr-flickr-fg);--tblr-btn-hover-bg: var(--tblr-flickr-darken);--tblr-btn-active-color: var(--tblr-flickr-fg);--tblr-btn-active-bg: var(--tblr-flickr-darken);--tblr-btn-disabled-bg: var(--tblr-flickr);--tblr-btn-disabled-color: var(--tblr-flickr-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-flickr,.btn-outline.btn-flickr{--tblr-btn-color: var(--tblr-flickr);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-flickr);--tblr-btn-hover-color: var(--tblr-flickr-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-flickr);--tblr-btn-active-color: var(--tblr-flickr-fg);--tblr-btn-active-bg: var(--tblr-flickr);--tblr-btn-active-border-color: var(--tblr-flickr);--tblr-btn-disabled-color: var(--tblr-flickr);--tblr-btn-disabled-border-color: var(--tblr-flickr)}.btn-ghost-flickr,.btn-ghost.btn-flickr{--tblr-btn-color: var(--tblr-flickr);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-flickr-fg);--tblr-btn-hover-bg: var(--tblr-flickr);--tblr-btn-hover-border-color: var(--tblr-flickr);--tblr-btn-active-color: var(--tblr-flickr-fg);--tblr-btn-active-bg: var(--tblr-flickr);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-flickr);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-bitbucket{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-bitbucket-fg, #ffffff);--tblr-btn-bg: var(--tblr-bitbucket);--tblr-btn-hover-color: var(--tblr-bitbucket-fg);--tblr-btn-hover-bg: var(--tblr-bitbucket-darken);--tblr-btn-active-color: var(--tblr-bitbucket-fg);--tblr-btn-active-bg: var(--tblr-bitbucket-darken);--tblr-btn-disabled-bg: var(--tblr-bitbucket);--tblr-btn-disabled-color: var(--tblr-bitbucket-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-bitbucket,.btn-outline.btn-bitbucket{--tblr-btn-color: var(--tblr-bitbucket);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-bitbucket);--tblr-btn-hover-color: var(--tblr-bitbucket-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-bitbucket);--tblr-btn-active-color: var(--tblr-bitbucket-fg);--tblr-btn-active-bg: var(--tblr-bitbucket);--tblr-btn-active-border-color: var(--tblr-bitbucket);--tblr-btn-disabled-color: var(--tblr-bitbucket);--tblr-btn-disabled-border-color: var(--tblr-bitbucket)}.btn-ghost-bitbucket,.btn-ghost.btn-bitbucket{--tblr-btn-color: var(--tblr-bitbucket);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-bitbucket-fg);--tblr-btn-hover-bg: var(--tblr-bitbucket);--tblr-btn-hover-border-color: var(--tblr-bitbucket);--tblr-btn-active-color: var(--tblr-bitbucket-fg);--tblr-btn-active-bg: var(--tblr-bitbucket);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-bitbucket);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-tabler{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-tabler-fg, #ffffff);--tblr-btn-bg: var(--tblr-tabler);--tblr-btn-hover-color: var(--tblr-tabler-fg);--tblr-btn-hover-bg: var(--tblr-tabler-darken);--tblr-btn-active-color: var(--tblr-tabler-fg);--tblr-btn-active-bg: var(--tblr-tabler-darken);--tblr-btn-disabled-bg: var(--tblr-tabler);--tblr-btn-disabled-color: var(--tblr-tabler-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-tabler,.btn-outline.btn-tabler{--tblr-btn-color: var(--tblr-tabler);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-tabler);--tblr-btn-hover-color: var(--tblr-tabler-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-tabler);--tblr-btn-active-color: var(--tblr-tabler-fg);--tblr-btn-active-bg: var(--tblr-tabler);--tblr-btn-active-border-color: var(--tblr-tabler);--tblr-btn-disabled-color: var(--tblr-tabler);--tblr-btn-disabled-border-color: var(--tblr-tabler)}.btn-ghost-tabler,.btn-ghost.btn-tabler{--tblr-btn-color: var(--tblr-tabler);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-tabler-fg);--tblr-btn-hover-bg: var(--tblr-tabler);--tblr-btn-hover-border-color: var(--tblr-tabler);--tblr-btn-active-color: var(--tblr-tabler-fg);--tblr-btn-active-bg: var(--tblr-tabler);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-tabler);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-sm,.btn-group-sm>.btn{--tblr-btn-line-height: 1.3333333333;--tblr-btn-icon-size: 1rem}.btn-lg,.btn-group-lg>.btn{--tblr-btn-line-height: 1.5rem;--tblr-btn-icon-size: 1.5rem}.btn-xl,.btn-group-xl>.btn{--tblr-btn-line-height: 2;--tblr-btn-icon-size: 2rem;--tblr-btn-padding-y: .6875rem;--tblr-btn-padding-x: 2rem;--tblr-btn-font-size: 1.5rem}.btn-pill{padding-right:1.5em;padding-left:1.5em;border-radius:10rem}.btn-pill[class*=btn-icon]{padding:.375rem 15px}.btn-square{border-radius:0}.btn-icon,.btn-action{padding-left:0;padding-right:0}.btn-icon .icon,.btn-action .icon{margin:calc(-1 * var(--tblr-btn-padding-x))}.btn-list{--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.btn-floating{position:fixed;z-index:1030;bottom:1rem;left:1rem;box-shadow:var(--tblr-shadow-dropdown)}.btn-loading{position:relative;color:transparent!important;text-shadow:none!important;pointer-events:none}.btn-loading>*{opacity:0}.btn-loading:after{content:"";display:inline-block;vertical-align:text-bottom;border:2px var(--tblr-border-style) currentColor;border-right-color:transparent;border-radius:100rem;color:var(--tblr-btn-color);position:absolute;width:var(--tblr-btn-icon-size);height:var(--tblr-btn-icon-size);left:calc(50% - var(--tblr-btn-icon-size) / 2);top:calc(50% - var(--tblr-btn-icon-size) / 2);animation:spinner-border .75s linear infinite}.btn-action{--tblr-border-color: transparent;color:var(--tblr-secondary);border-radius:var(--tblr-border-radius);background:transparent;box-shadow:none}.btn-action:after{content:none}.btn-action:focus{outline:none;box-shadow:none}.btn-action:hover,.btn-action.show{color:var(--tblr-body-color);background:var(--tblr-active-bg);border-color:transparent}.btn-action.show{color:var(--tblr-primary)}.btn-actions{display:flex}.btn-animate-icon .icon{transition:transform .3s ease}.btn-animate-icon:hover .icon,.btn-animate-icon:focus-visible .icon{transform:translate(4px)}.btn-animate-icon.btn-animate-icon-rotate:hover .icon,.btn-animate-icon.btn-animate-icon-rotate:focus-visible .icon{transform:rotate(90deg)}.btn-animate-icon.btn-animate-icon-move-start:hover .icon,.btn-animate-icon.btn-animate-icon-move-start:focus-visible .icon{transform:translate(-4px)}.btn-animate-icon.btn-animate-icon-pulse:hover .icon,.btn-animate-icon.btn-animate-icon-pulse:focus-visible .icon{transform:none;animation:pulse .9s}.btn-animate-icon.btn-animate-icon-shake:hover .icon,.btn-animate-icon.btn-animate-icon-shake:focus-visible .icon{transform:none;animation:shake .9s}.btn-animate-icon.btn-animate-icon-tada:hover .icon,.btn-animate-icon.btn-animate-icon-tada:focus-visible .icon{transform:none;animation:tada .9s}.btn-group,.btn-group-vertical{box-shadow:var(--tblr-shadow-input)}.btn-group>.btn-check:checked+.btn,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:5}.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus{z-index:1}.calendar{display:block;font-size:.765625rem;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.calendar-nav{display:flex;align-items:center}.calendar-title{flex:1;text-align:center}.calendar-body,.calendar-header{display:flex;flex-wrap:wrap;justify-content:flex-start;padding:.5rem 0}.calendar-header{color:var(--tblr-secondary)}.calendar-date{flex:0 0 14.2857142857%;max-width:14.2857142857%;padding:.2rem;text-align:center;border:0}.calendar-date.prev-month,.calendar-date.next-month{opacity:.25}.calendar-date .date-item{position:relative;display:inline-block;width:1.4rem;height:1.4rem;line-height:1.4rem;color:#66758c;text-align:center;text-decoration:none;white-space:nowrap;vertical-align:middle;cursor:pointer;background:0 0;border:var(--tblr-border-width) var(--tblr-border-style) transparent;border-radius:100rem;outline:0;transition:background .3s,border .3s,box-shadow .32s,color .3s}@media(prefers-reduced-motion:reduce){.calendar-date .date-item{transition:none}}.calendar-date .date-item:hover{color:var(--tblr-primary);text-decoration:none;background:#fefeff;border-color:var(--tblr-border-color)}.calendar-date .date-today{color:var(--tblr-primary);border-color:var(--tblr-border-color)}.calendar-range{position:relative}.calendar-range:before{position:absolute;top:50%;right:0;left:0;height:1.4rem;content:"";background:rgba(var(--tblr-primary-rgb),.1);transform:translateY(-50%)}.calendar-range.range-start .date-item,.calendar-range.range-end .date-item{color:#fff;background:var(--tblr-primary);border-color:var(--tblr-primary)}.calendar-range.range-start:before{left:50%}.calendar-range.range-end:before{right:50%}.carousel-indicators-vertical{left:auto;top:0;margin:0 1rem 0 0;flex-direction:column}.carousel-indicators-vertical [data-bs-target]{margin:3px 0;width:3px;height:30px;border:0;border-left:10px var(--tblr-border-style) transparent;border-right:10px var(--tblr-border-style) transparent}.carousel-indicators-dot [data-bs-target]{width:.5rem;height:.5rem;border-radius:100rem;border:10px var(--tblr-border-style) transparent;margin:0}.carousel-indicators-thumb [data-bs-target]{width:2rem;height:auto;background:no-repeat center/cover;border:0;border-radius:var(--tblr-border-radius);box-shadow:rgba(var(--tblr-body-color-rgb),.04) 0 2px 4px;margin:0 3px;opacity:.75}@media(min-width:992px){.carousel-indicators-thumb [data-bs-target]{width:4rem}}.carousel-indicators-thumb [data-bs-target]:before{content:"";padding-top:var(--tblr-aspect-ratio, 100%);display:block}.carousel-indicators-thumb.carousel-indicators-vertical [data-bs-target]{margin:3px 0}.carousel-caption-background{background:red;position:absolute;left:0;right:0;bottom:0;height:90%;background:linear-gradient(0deg,#1f2937e6,#1f293700)}.card{transition:transform .3s ease-out,opacity .3s ease-out,box-shadow .3s ease-out}@media(prefers-reduced-motion:reduce){.card{transition:none}}@media print{.card{border:none;box-shadow:none}}a.card{color:inherit}a.card:hover{text-decoration:none;box-shadow:rgba(var(--tblr-body-color-rgb),.16) 0 2px 16px}.card .card{box-shadow:none}.card-borderless,.card-borderless .card-header,.card-borderless .card-footer{border-color:transparent}.card-stamp{--tblr-stamp-size: 7rem;position:absolute;top:0;right:0;width:calc(var(--tblr-stamp-size) * 1);height:calc(var(--tblr-stamp-size) * 1);max-height:100%;border-top-right-radius:6px;opacity:.2;overflow:hidden;pointer-events:none}.card-stamp-lg{--tblr-stamp-size: 13rem}.card-stamp-icon{background:var(--tblr-secondary);color:var(--tblr-card-bg, var(--tblr-bg-surface));display:flex;align-items:center;justify-content:center;border-radius:100rem;width:calc(var(--tblr-stamp-size) * 1);height:calc(var(--tblr-stamp-size) * 1);position:relative;top:calc(var(--tblr-stamp-size) * -.25);right:calc(var(--tblr-stamp-size) * -.25);font-size:calc(var(--tblr-stamp-size) * .75);transform:rotate(10deg)}.card-stamp-icon .icon{stroke-width:2;width:calc(var(--tblr-stamp-size) * .75);height:calc(var(--tblr-stamp-size) * .75)}.card-img,.card-img-start{border-top-left-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));border-bottom-left-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)))}.card-img,.card-img-end{border-top-right-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));border-bottom-right-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)))}.card-img-overlay{display:flex;flex-direction:column;justify-content:flex-end}.card-img-overlay-dark{background-image:linear-gradient(180deg,#0000,#0009)}.card-inactive{pointer-events:none;box-shadow:none}.card-inactive .card-body{opacity:.64}.card-active{--tblr-card-border-color: var(--tblr-primary);--tblr-card-bg: var(--tblr-active-bg)}.card-btn{display:flex;align-items:center;justify-content:center;padding:1rem 1.25rem;text-align:center;transition:background .3s}@media(prefers-reduced-motion:reduce){.card-btn{transition:none}}.card-btn{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);flex:1;color:inherit;font-weight:var(--tblr-font-weight-medium)}.card-btn:hover{text-decoration:none;background:rgba(var(--tblr-primary-rgb),.04)}.card-btn+.card-btn{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.card-stacked{--tblr-card-stacked-offset: .25rem;position:relative}.card-stacked:after{position:absolute;top:calc(-1 * var(--tblr-card-stacked-offset));right:var(--tblr-card-stacked-offset);left:var(--tblr-card-stacked-offset);height:var(--tblr-card-stacked-offset);content:"";background:var(--tblr-card-bg, var(--tblr-bg-surface));border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-card-border-color);border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-cover{position:relative;padding:1rem 1.25rem;background:#666 no-repeat center/cover}.card-cover:before{position:absolute;inset:0;content:"";background:#1f29377a}.card-cover:first-child,.card-cover:first-child:before{border-radius:6px 6px 0 0}.card-cover-blurred:before{backdrop-filter:blur(2px)}.card-actions{margin:-.5rem -.5rem -.5rem auto;padding-left:.5rem}.card-actions a{text-decoration:none}.card-header{color:inherit;display:flex;align-items:center;background:transparent}.card-header:first-child{border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-header-light{border-bottom-color:transparent;background:var(--tblr-bg-surface-tertiary)}.card-header-tabs{background:var(--tblr-bg-surface-tertiary);flex:1;margin:calc(var(--tblr-card-cap-padding-y) * -1) calc(var(--tblr-card-cap-padding-x) * -1) calc(var(--tblr-card-cap-padding-y) * -1);padding:calc(var(--tblr-card-cap-padding-y) * .5) calc(var(--tblr-card-cap-padding-x) * .5) 0;border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-header-pills{flex:1;margin-top:-.5rem;margin-bottom:-.5rem}.card-rotate-left,.card-rotate-start{transform:rotate(-1.5deg)}.card-rotate-right,.card-rotate-end{transform:rotate(1.5deg)}.card-link{color:inherit}.card-link:hover{color:inherit;text-decoration:none;box-shadow:0 1px 6px #00000014}.card-link-rotate:hover{transform:rotate(1.5deg);opacity:1}.card-link-pop:hover{transform:translateY(-2px);opacity:1}.card-footer{margin-top:auto}.card-footer:last-child{border-radius:0 0 var(--tblr-card-border-radius) var(--tblr-card-border-radius)}.card-footer-transparent{background:transparent;border-color:transparent;padding-top:0}.card-footer-borderless{border-top:none}.card-progress{height:.25rem}.card-progress:last-child{border-radius:0 0 2px 2px}.card-progress:first-child{border-radius:2px 2px 0 0}.card-meta{color:var(--tblr-secondary)}.card-title{display:block;margin:0 0 1rem;font-size:1rem;font-weight:var(--tblr-font-weight-medium);color:inherit;line-height:1.5rem}a.card-title:hover{color:inherit}.card-header .card-title{margin:0}.card-subtitle{margin-bottom:1.25rem;color:var(--tblr-secondary);font-weight:400}.card-header .card-subtitle{margin:0}.card-title .card-subtitle{margin:0 0 0 .25rem;font-size:.875rem}.card-body{position:relative}.card-body>:last-child{margin-bottom:0}.card-sm>.card-body{padding:1rem}@media(min-width:768px){.card-md>.card-body{padding:2.5rem}}@media(min-width:768px){.card-lg>.card-body{padding:2rem}}@media(min-width:992px){.card-lg>.card-body{padding:4rem}}@media print{.card-body{padding:0}}.card-body+.card-body{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.card-body-scrollable{overflow:auto}.card-options{top:1.5rem;right:.75rem;display:flex;margin-left:auto}.card-options-link{display:inline-block;min-width:1rem;margin-left:.25rem;color:var(--tblr-secondary)}.card-status-top{position:absolute;top:0;right:0;left:0;height:2px;border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-status-start{position:absolute;right:auto;bottom:0;width:2px;height:100%;border-radius:var(--tblr-card-border-radius) 0 0 var(--tblr-card-border-radius)}.card-status-bottom{position:absolute;top:initial;bottom:0;width:100%;height:2px;border-radius:0 0 var(--tblr-card-border-radius) var(--tblr-card-border-radius)}.card-table{margin-bottom:0!important}.card-table tr td:first-child,.card-table tr th:first-child{padding-left:1.25rem;border-left:0}.card-table tr td:last-child,.card-table tr th:last-child{padding-right:1.25rem;border-right:0}.card-table thead tr:first-child,.card-table tbody tr:first-child,.card-table tfoot tr:first-child,.card-table thead tr:first-child td,.card-table thead tr:first-child th,.card-table tbody tr:first-child td,.card-table tbody tr:first-child th,.card-table tfoot tr:first-child td,.card-table tfoot tr:first-child th{border-top:0}.card-body+.card-table{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-table-border-color)}.card-code{padding:0}.card-code .highlight{margin:0;border:0}.card-code pre{margin:0!important;border:0!important}.card-chart{position:relative;z-index:1;height:3.5rem}.card-avatar{margin-left:auto;margin-right:auto;box-shadow:0 0 0 .25rem var(--tblr-card-bg, var(--tblr-bg-surface));margin-top:calc(-1 * var(--tblr-avatar-size) * .5)}.card-body+.card-list-group{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.card-list-group .list-group-item{padding-right:1.25rem;padding-left:1.25rem;border-right:0;border-left:0;border-radius:0}.card-list-group .list-group-item:last-child{border-bottom:0}.card-list-group .list-group-item:first-child{border-top:0}.card-tabs .nav-tabs{position:relative;z-index:1000;border-bottom:0}.card-tabs .nav-tabs .nav-link{background:var(--tblr-bg-surface-tertiary);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.card-tabs .nav-tabs .nav-link.active,.card-tabs .nav-tabs .nav-link:active,.card-tabs .nav-tabs .nav-link:hover{border-color:var(--tblr-border-color-translucent);color:var(--tblr-body-color)}.card-tabs .nav-tabs .nav-link.active{color:inherit;background:var(--tblr-card-bg, var(--tblr-bg-surface));border-bottom-color:transparent}.card-tabs .nav-tabs .nav-item:not(:first-child) .nav-link{border-top-left-radius:0}.card-tabs .nav-tabs .nav-item:not(:last-child) .nav-link{border-top-right-radius:0}.card-tabs .nav-tabs .nav-item+.nav-item{margin-left:calc(-1 * var(--tblr-border-width))}.card-tabs .nav-tabs-bottom,.card-tabs .nav-tabs-bottom .nav-link{margin-bottom:0}.card-tabs .nav-tabs-bottom .nav-link.active{border-top-color:transparent}.card-tabs .nav-tabs-bottom .nav-item{margin-top:calc(-1 * var(--tblr-border-width));margin-bottom:0}.card-tabs .nav-tabs-bottom .nav-item .nav-link{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);border-radius:0 0 var(--tblr-border-radius-lg) var(--tblr-border-radius-lg)}.card-tabs .nav-tabs-bottom .nav-item:not(:first-child) .nav-link{border-bottom-left-radius:0}.card-tabs .nav-tabs-bottom .nav-item:not(:last-child) .nav-link{border-bottom-right-radius:0}.card-tabs .card{border-bottom-left-radius:0}.card-tabs .nav-tabs+.tab-content .card{border-bottom-left-radius:var(--tblr-card-border-radius);border-top-left-radius:0}.card-note{--tblr-card-bg: #fff7dd;--tblr-card-border-color: #fff1c9}.btn-close{--tblr-btn-close-color: currentColor;--tblr-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%231f2937'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");--tblr-btn-close-opacity: .4;--tblr-btn-close-hover-opacity: .75;--tblr-btn-close-focus-shadow: 0 0 0 .25rem rgba(var(--tblr-primary-rgb), .25);--tblr-btn-close-focus-opacity: 1;--tblr-btn-close-disabled-opacity: .25;--tblr-btn-close-size: 1em;width:var(--tblr-btn-close-size);height:var(--tblr-btn-close-size);padding:.25em;color:var(--tblr-btn-close-color);mask:var(--tblr-btn-close-bg) no-repeat center/calc(var(--tblr-btn-close-size) * .75);background-color:var(--tblr-btn-close-color);border:0;border-radius:var(--tblr-border-radius);opacity:var(--tblr-btn-close-opacity);cursor:pointer;display:block}.btn-close:hover{color:var(--tblr-btn-close-color);text-decoration:none;opacity:var(--tblr-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--tblr-btn-close-focus-shadow);opacity:var(--tblr-btn-close-focus-opacity)}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;opacity:var(--tblr-btn-close-disabled-opacity)}.dropdown-menu{user-select:none;background-clip:border-box}.dropdown-menu.card{padding:0;min-width:25rem;display:none}.dropdown-menu.card.show{display:flex}.dropdown-item{min-width:11rem;display:flex;align-items:center;margin:0;line-height:1.4285714286;gap:.5rem}.dropdown-item-icon{width:1.25rem!important;height:1.25rem!important;margin-right:.5rem;color:var(--tblr-secondary);opacity:.7;text-align:center}.dropdown-item-indicator{margin-right:.5rem;margin-left:-.25rem;height:1.25rem;display:inline-flex;line-height:1;vertical-align:bottom;align-items:center}.dropdown-header{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);padding-bottom:.25rem;pointer-events:none}.dropdown-menu-scrollable{height:auto;max-height:13rem;overflow-x:hidden}.dropdown-menu-column{min-width:11rem}.dropdown-menu-column .dropdown-item{min-width:0}.dropdown-menu-columns{display:flex;flex:0 .25rem}.dropdown-menu-arrow:before{content:"";position:absolute;top:-.25rem;left:.75rem;display:block;background:inherit;width:14px;height:14px;transform:rotate(45deg);transform-origin:center;border:1px solid;border-color:inherit;z-index:-1;clip:rect(0px,9px,9px,0px)}.dropdown-menu-arrow.dropdown-menu-end:before{right:.75rem;left:auto}.dropend>.dropdown-menu{margin-top:calc(-.25rem - 1px);margin-left:-.25rem}.dropend .dropdown-toggle:after{margin-left:auto}.dropdown-menu-card{padding:0;min-width:20rem}.dropdown-menu-card>.card{margin:0;border:0;box-shadow:none}.datagrid{--tblr-datagrid-padding: 1.5rem;--tblr-datagrid-item-width: 15rem;display:grid;grid-gap:var(--tblr-datagrid-padding);grid-template-columns:repeat(auto-fit,minmax(var(--tblr-datagrid-item-width),1fr))}.datagrid-title{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);margin-bottom:.25rem}.empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:1rem;text-align:center}@media(min-width:768px){.empty{padding:3rem}}.empty-icon{margin:0 0 1rem;width:3rem;height:3rem;line-height:1;color:var(--tblr-secondary)}.empty-icon svg{width:100%;height:100%}.empty-img{margin:0 0 2rem;line-height:1}.empty-header{margin:0 0 1rem;font-size:4rem;font-weight:var(--tblr-font-weight-light);line-height:1;color:var(--tblr-secondary)}.empty-title{font-size:1.25rem;line-height:1.75rem;font-weight:var(--tblr-font-weight-bold)}.empty-title,.empty-subtitle{margin:0 0 .5rem}.empty-action{margin-top:1.5rem}.empty-bordered{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.row>*{min-width:0}.col-separator{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.container-slim{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto;max-width:16rem}.container-tight{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto;max-width:30rem}.container-narrow{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto;max-width:61.875rem}.row-0{margin-right:0;margin-left:0}.row-0>.col,.row-0>[class*=col-]{padding-right:0;padding-left:0}.row-0 .card{margin-bottom:0}.row-sm{margin-right:-.375rem;margin-left:-.375rem}.row-sm>.col,.row-sm>[class*=col-]{padding-right:.375rem;padding-left:.375rem}.row-sm .card{margin-bottom:.75rem}.row-md{margin-right:-1.5rem;margin-left:-1.5rem}.row-md>.col,.row-md>[class*=col-]{padding-right:1.5rem;padding-left:1.5rem}.row-md .card{margin-bottom:3rem}.row-lg{margin-right:-3rem;margin-left:-3rem}.row-lg>.col,.row-lg>[class*=col-]{padding-right:3rem;padding-left:3rem}.row-lg .card{margin-bottom:6rem}.row-deck>.col,.row-deck>[class*=col-]{display:flex;align-items:stretch}.row-deck>.col .card,.row-deck>[class*=col-] .card{flex:1 1 auto}.row-cards{--tblr-gutter-x: var(--tblr-page-padding);--tblr-gutter-y: var(--tblr-page-padding);min-width:0}.row-cards .row-cards{flex:1}.space-y{display:flex;flex-direction:column;gap:1rem}.space-x{display:flex;gap:1rem}.space-y-0{display:flex;flex-direction:column;gap:0}.space-x-0{display:flex;gap:0}.space-y-1{display:flex;flex-direction:column;gap:.25rem}.space-x-1{display:flex;gap:.25rem}.space-y-2{display:flex;flex-direction:column;gap:.5rem}.space-x-2{display:flex;gap:.5rem}.space-y-3{display:flex;flex-direction:column;gap:1rem}.space-x-3{display:flex;gap:1rem}.space-y-4{display:flex;flex-direction:column;gap:1.5rem}.space-x-4{display:flex;gap:1.5rem}.space-y-5{display:flex;flex-direction:column;gap:2rem}.space-x-5{display:flex;gap:2rem}.space-y-6{display:flex;flex-direction:column;gap:2.5rem}.space-x-6{display:flex;gap:2.5rem}.divide-y>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y>:not(template):not(:first-child){padding-top:1rem!important}.divide-y>:not(template):not(:last-child){padding-bottom:1rem!important}.divide-x>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x>:not(template):not(:first-child){padding-left:1rem!important}.divide-x>:not(template):not(:last-child){padding-right:1rem!important}.divide-y-0>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-0>:not(template):not(:first-child){padding-top:0!important}.divide-y-0>:not(template):not(:last-child){padding-bottom:0!important}.divide-x-0>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-0>:not(template):not(:first-child){padding-left:0!important}.divide-x-0>:not(template):not(:last-child){padding-right:0!important}.divide-y-1>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-1>:not(template):not(:first-child){padding-top:.25rem!important}.divide-y-1>:not(template):not(:last-child){padding-bottom:.25rem!important}.divide-x-1>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-1>:not(template):not(:first-child){padding-left:.25rem!important}.divide-x-1>:not(template):not(:last-child){padding-right:.25rem!important}.divide-y-2>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-2>:not(template):not(:first-child){padding-top:.5rem!important}.divide-y-2>:not(template):not(:last-child){padding-bottom:.5rem!important}.divide-x-2>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-2>:not(template):not(:first-child){padding-left:.5rem!important}.divide-x-2>:not(template):not(:last-child){padding-right:.5rem!important}.divide-y-3>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-3>:not(template):not(:first-child){padding-top:1rem!important}.divide-y-3>:not(template):not(:last-child){padding-bottom:1rem!important}.divide-x-3>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-3>:not(template):not(:first-child){padding-left:1rem!important}.divide-x-3>:not(template):not(:last-child){padding-right:1rem!important}.divide-y-4>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-4>:not(template):not(:first-child){padding-top:1.5rem!important}.divide-y-4>:not(template):not(:last-child){padding-bottom:1.5rem!important}.divide-x-4>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-4>:not(template):not(:first-child){padding-left:1.5rem!important}.divide-x-4>:not(template):not(:last-child){padding-right:1.5rem!important}.divide-y-5>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-5>:not(template):not(:first-child){padding-top:2rem!important}.divide-y-5>:not(template):not(:last-child){padding-bottom:2rem!important}.divide-x-5>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-5>:not(template):not(:first-child){padding-left:2rem!important}.divide-x-5>:not(template):not(:last-child){padding-right:2rem!important}.divide-y-6>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-6>:not(template):not(:first-child){padding-top:2.5rem!important}.divide-y-6>:not(template):not(:last-child){padding-bottom:2.5rem!important}.divide-x-6>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-6>:not(template):not(:first-child){padding-left:2.5rem!important}.divide-x-6>:not(template):not(:last-child){padding-right:2.5rem!important}.divide-y-fill{display:flex;flex-direction:column;height:100%}.divide-y-fill>:not(template){flex:1;display:flex;justify-content:center;flex-direction:column}.icon{--tblr-icon-size: 1.25rem;width:var(--tblr-icon-size);height:var(--tblr-icon-size);font-size:var(--tblr-icon-size);vertical-align:bottom;stroke-width:1.5}.icon:hover{text-decoration:none}.icon-inline{--tblr-icon-size: 1rem;vertical-align:-.2rem}.icon-filled{fill:currentColor}.icon-sm{--tblr-icon-size: 1rem;stroke-width:1}.icon-md{--tblr-icon-size: 2.5rem;stroke-width:1}.icon-lg{--tblr-icon-size: 3.5rem;stroke-width:1}.icon-pulse{transition:all .15s ease 0s;animation:pulse 2s ease infinite;animation-fill-mode:both}.icon-tada{transition:all .15s ease 0s;animation:tada 3s ease infinite;animation-fill-mode:both}.icon-rotate{transition:all .15s ease 0s;animation:rotate-360 3s linear infinite;animation-fill-mode:both}.img-responsive{--tblr-img-responsive-ratio: 75%;background:no-repeat center/cover;padding-top:var(--tblr-img-responsive-ratio)}.img-responsive-grid{padding-top:calc(var(--tblr-img-responsive-ratio) - var(--tblr-gutter-y) / 2)}.img-responsive-1x1{--tblr-img-responsive-ratio: 100%}.img-responsive-2x1{--tblr-img-responsive-ratio: 50%}.img-responsive-1x2{--tblr-img-responsive-ratio: 200%}.img-responsive-3x1{--tblr-img-responsive-ratio: 33.3333333333%}.img-responsive-1x3{--tblr-img-responsive-ratio: 300%}.img-responsive-4x1{--tblr-img-responsive-ratio: 25%}.img-responsive-1x4{--tblr-img-responsive-ratio: 400%}.img-responsive-4x3{--tblr-img-responsive-ratio: 75%}.img-responsive-3x4{--tblr-img-responsive-ratio: 133.3333333333%}.img-responsive-16x9{--tblr-img-responsive-ratio: 56.25%}.img-responsive-9x16{--tblr-img-responsive-ratio: 177.7777777778%}.img-responsive-21x9{--tblr-img-responsive-ratio: 42.8571428571%}.img-responsive-9x21{--tblr-img-responsive-ratio: 233.3333333333%}.img-bg{background:no-repeat center/cover}textarea[cols]{height:auto}.col-form-label,.form-label{display:block;font-weight:var(--tblr-font-weight-medium)}.col-form-label.required:after,.form-label.required:after{content:"*";margin-left:.25rem;color:#d63939}.form-label-description{float:right;font-weight:var(--tblr-font-weight-normal);color:var(--tblr-secondary)}.form-hint{display:block;color:var(--tblr-secondary)}.form-hint:last-child{margin-bottom:0}.form-hint+.form-control{margin-top:.25rem}.form-label+.form-hint{margin-top:-.25rem}.input-group+.form-hint,.form-control+.form-hint,.form-select+.form-hint{margin-top:.5rem;color:var(--tblr-secondary)}.form-select:-moz-focusring{color:var(--tblr-body-color)}.form-control:-webkit-autofill{box-shadow:0 0 0 1000px var(--tblr-bg-surface-secondary) inset;color:var(--tblr-body-color);-webkit-text-fill-color:var(--tblr-body-color)}.form-control:disabled,.form-control.disabled{color:var(--tblr-secondary);user-select:none}.form-control[size]{width:auto}.form-control-light{background-color:var(--tblr-gray-100);border-color:transparent}.form-control-dark{background-color:#0000001a;color:#fff;border-color:transparent}.form-control-dark:focus{background-color:#0000001a;box-shadow:none;border-color:#ffffff3d}.form-control-dark::placeholder{color:#fff9}.form-control-rounded{border-radius:10rem}.form-control-flush{padding:0;background:none!important;border-color:transparent!important;resize:none;box-shadow:none!important;line-height:inherit}.form-footer{margin-top:2rem}.form-fieldset{padding:1rem;margin-bottom:1rem;background:var(--tblr-bg-surface-secondary);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius)}fieldset:empty{display:none}.form-help{display:inline-flex;font-weight:var(--tblr-font-weight-bold);align-items:center;justify-content:center;width:1.125rem;height:1.125rem;font-size:.75rem;color:var(--tblr-secondary);text-align:center;text-decoration:none;cursor:pointer;user-select:none;background:var(--tblr-gray-100);border-radius:100rem;transition:background-color .3s,color .3s}@media(prefers-reduced-motion:reduce){.form-help{transition:none}}.form-help:hover,.form-help[aria-describedby]{color:#fff;background:var(--tblr-primary)}.input-group{box-shadow:var(--tblr-shadow-input);border-radius:var(--tblr-border-radius)}.input-group .form-control,.input-group .btn{box-shadow:none}.input-group-link{font-size:.75rem}.input-group-flat:focus-within{box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25);border-radius:var(--tblr-border-radius)}.input-group-flat:focus-within .form-control,.input-group-flat:focus-within .input-group-text{border-color:#80c2be!important}.input-group-flat .form-control:focus{border-color:var(--tblr-border-color);box-shadow:none}.input-group-flat .form-control:not(:last-child){border-right:0}.input-group-flat .form-control:not(:first-child){border-left:0}.input-group-flat .input-group-text{background:var(--tblr-bg-forms);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.input-group-flat .input-group-text{transition:none}}.input-group-flat .input-group-text:first-child{padding-right:0}.input-group-flat .input-group-text:last-child{padding-left:0}.form-file-button{margin-left:0;border-left:0}label[for=floating-input]{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:575.98px){.form-control,.form-select{font-size:1rem}}.input-icon{position:relative}.input-icon .form-control:not(:last-child),.input-icon .form-select:not(:last-child){padding-right:2.5rem}.input-icon .form-control:not(:first-child),.input-icon .form-select:not(:last-child){padding-left:2.5rem}.input-icon-addon{position:absolute;top:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;min-width:2.5rem;color:var(--tblr-icon-color);pointer-events:none;font-size:1.2em}.input-icon-addon:last-child{right:0;left:auto}.form-colorinput{position:relative;display:inline-block;margin:0;line-height:1;cursor:pointer}.form-colorinput-input{position:absolute;z-index:-1;opacity:0}.form-colorinput-color{display:block;width:1.5rem;height:1.5rem;color:#fff;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);border-radius:var(--tblr-border-radius);box-shadow:0 1px 2px #0000000d}.form-colorinput-color:before{position:absolute;top:0;left:0;width:100%;height:100%;content:"";background:no-repeat center center/1.25rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e");opacity:0;transition:opacity .3s}@media(prefers-reduced-motion:reduce){.form-colorinput-color:before{transition:none}}.form-colorinput-input:checked~.form-colorinput-color:before{opacity:1}.form-colorinput-input:focus~.form-colorinput-color{border-color:var(--tblr-primary);box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-colorinput-light .form-colorinput-color:before{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%231f2937' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e")}.form-imagecheck{--tblr-form-imagecheck-radius: var(--tblr-border-radius);position:relative;margin:0;cursor:pointer}.form-imagecheck-input{position:absolute;z-index:-1;opacity:0}.form-imagecheck-figure{position:relative;display:block;margin:0;user-select:none;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-form-imagecheck-radius)}.form-imagecheck-input:focus~.form-imagecheck-figure{border-color:var(--tblr-primary);box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-imagecheck-input:checked~.form-imagecheck-figure{border-color:var(--tblr-primary)}.form-imagecheck-figure:before{position:absolute;top:.25rem;left:.25rem;z-index:1;display:block;width:1.25rem;height:1.25rem;color:#fff;pointer-events:none;content:"";user-select:none;background:var(--tblr-bg-forms);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius);transition:opacity .3s}@media(prefers-reduced-motion:reduce){.form-imagecheck-figure:before{transition:none}}.form-imagecheck-input:checked~.form-imagecheck-figure:before{background-color:var(--tblr-primary);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e");background-repeat:repeat;background-position:center;background-size:1.25rem;border-color:var(--tblr-border-color-translucent)}.form-imagecheck-input[type=radio]~.form-imagecheck-figure:before{border-radius:50%}.form-imagecheck-input[type=radio]:checked~.form-imagecheck-figure:before{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3ccircle r='3' fill='%23ffffff' cx='8' cy='8' /%3e%3c/svg%3e")}.form-imagecheck-image{max-width:100%;display:block;opacity:.64;transition:opacity .3s}@media(prefers-reduced-motion:reduce){.form-imagecheck-image{transition:none}}.form-imagecheck-image:first-child{border-top-left-radius:calc(var(--tblr-form-imagecheck-radius) - 1px);border-top-right-radius:calc(var(--tblr-form-imagecheck-radius) - 1px)}.form-imagecheck-image:last-child{border-bottom-right-radius:calc(var(--tblr-form-imagecheck-radius) - 1px);border-bottom-left-radius:calc(var(--tblr-form-imagecheck-radius) - 1px)}.form-imagecheck:hover .form-imagecheck-image,.form-imagecheck-input:focus~.form-imagecheck-figure .form-imagecheck-image,.form-imagecheck-input:checked~.form-imagecheck-figure .form-imagecheck-image{opacity:1}.form-imagecheck-caption{padding:.25rem;font-size:.765625rem;color:var(--tblr-secondary);text-align:center;transition:color .3s}@media(prefers-reduced-motion:reduce){.form-imagecheck-caption{transition:none}}.form-imagecheck:hover .form-imagecheck-caption,.form-imagecheck-input:focus~.form-imagecheck-figure .form-imagecheck-caption,.form-imagecheck-input:checked~.form-imagecheck-figure .form-imagecheck-caption{color:var(--tblr-body-color)}.form-selectgroup{display:inline-flex;margin:0 -.5rem -.5rem 0;flex-wrap:wrap}.form-selectgroup .form-selectgroup-item{margin:0 .5rem .5rem 0}.form-selectgroup-vertical{flex-direction:column}.form-selectgroup-item{display:block;position:relative}.form-selectgroup-input{position:absolute;top:0;left:0;z-index:-1;opacity:0}.form-selectgroup-label{position:relative;display:block;min-width:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2));margin:0;padding:.5625rem 1rem;font-size:.875rem;line-height:1.25rem;color:var(--tblr-secondary);background:var(--tblr-bg-forms);text-align:center;cursor:pointer;user-select:none;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-shadow-input);transition:border-color .3s,background .3s,color .3s}@media(prefers-reduced-motion:reduce){.form-selectgroup-label{transition:none}}.form-selectgroup-label .icon:only-child{margin:0 -.25rem}.form-selectgroup-label:hover{color:var(--tblr-body-color)}.form-selectgroup-check{display:inline-block;width:1.25rem;height:1.25rem;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);vertical-align:middle;box-shadow:var(--tblr-shadow-input)}.form-selectgroup-input[type=checkbox]+.form-selectgroup-label .form-selectgroup-check{border-radius:var(--tblr-border-radius)}.form-selectgroup-input[type=radio]+.form-selectgroup-label .form-selectgroup-check{border-radius:50%}.form-selectgroup-input:checked+.form-selectgroup-label .form-selectgroup-check{background-color:var(--tblr-primary);background-repeat:repeat;background-position:center;background-size:1.25rem;border-color:var(--tblr-border-color-translucent)}.form-selectgroup-input[type=checkbox]:checked+.form-selectgroup-label .form-selectgroup-check{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e")}.form-selectgroup-input[type=radio]:checked+.form-selectgroup-label .form-selectgroup-check{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3ccircle r='3' fill='%23ffffff' cx='8' cy='8' /%3e%3c/svg%3e")}.form-selectgroup-check-floated{position:absolute;top:.5625rem;right:.5625rem}.form-selectgroup-input:checked+.form-selectgroup-label{z-index:1;color:var(--tblr-primary);background:rgba(var(--tblr-primary-rgb),.04);border-color:var(--tblr-primary)}.form-selectgroup-input:focus+.form-selectgroup-label{z-index:2;color:var(--tblr-primary);border-color:var(--tblr-primary);box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-selectgroup-boxes .form-selectgroup-label{text-align:left;padding:1.25rem 1rem;color:inherit}.form-selectgroup-boxes .form-selectgroup-input:checked+.form-selectgroup-label{color:inherit}.form-selectgroup-boxes .form-selectgroup-input:checked+.form-selectgroup-label .form-selectgroup-title{color:var(--tblr-primary)}.form-selectgroup-boxes .form-selectgroup-input:checked+.form-selectgroup-label .form-selectgroup-label-content{opacity:1}.form-selectgroup-pills{flex-wrap:wrap;align-items:flex-start}.form-selectgroup-pills .form-selectgroup-item{flex-grow:0}.form-selectgroup-pills .form-selectgroup-label{border-radius:50px}.form-control-color::-webkit-color-swatch{border:none}[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}.form-control::file-selector-button{background-color:var(--tblr-btn-color, var(--tblr-tertiary-bg))}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--tblr-btn-color, var(--tblr-secondary-bg))}.form-check{user-select:none}.form-check.form-check-highlight .form-check-input:not(:checked)~.form-check-label{color:var(--tblr-secondary)}.form-check .form-check-label-off{color:var(--tblr-secondary)}.form-check .form-check-input:checked~.form-check-label-off{display:none}.form-check .form-check-input:not(:checked)~.form-check-label-on{display:none}.form-check-input{background-size:1.25rem;margin-top:0rem;box-shadow:var(--tblr-shadow-input)}.form-switch .form-check-input{transition:background-color .3s,background-position .3s}@media(prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-check-label{display:block}.form-check-label.required:after{content:"*";margin-left:.25rem;color:#d63939}.form-check-description{display:block;color:var(--tblr-secondary);font-size:.75rem;margin-top:.25rem}.form-check-single,.form-check-single .form-check-input{margin:0}.form-switch .form-check-input{height:1.25rem;margin-top:0rem}.form-switch-lg{padding-left:3.5rem;min-height:1.5rem}.form-switch-lg .form-check-input{height:1.5rem;width:2.75rem;background-size:1.5rem;margin-left:-3.5rem}.form-switch-lg .form-check-label{padding-top:.125rem}.form-check-input:checked{border:none}.form-select.is-invalid-lite,.form-control.is-invalid-lite,.form-select.is-valid-lite,.form-control.is-valid-lite{border-color:var(--tblr-border-color)!important}.legend{--tblr-legend-size: .75em;display:inline-block;background:var(--tblr-border-color);width:var(--tblr-legend-size);height:var(--tblr-legend-size);border-radius:var(--tblr-border-radius-sm);border:1px solid var(--tblr-border-color-translucent)}.list-group{margin-left:0;margin-right:0}.list-group-header{background:var(--tblr-bg-surface-tertiary);padding:.5rem 1.25rem;font-size:.75rem;font-weight:var(--tblr-font-weight-medium);line-height:1;text-transform:uppercase;color:var(--tblr-gray-500);border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.list-group-flush>.list-group-header:last-child{border-bottom-width:0}.list-group-item{background-color:inherit}.list-group-item.active{background-color:rgba(var(--tblr-secondary-rgb),.08);border-left-color:#00857d;border-left-width:2px}.list-group-item.disabled,.list-group-item:disabled{color:#6b7280;background-color:rgba(var(--tblr-secondary-rgb),.08)}.list-bordered .list-item{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);margin-top:-1px}.list-bordered .list-item:first-child{border-top:none}.list-group-hoverable .list-group-item:active,.list-group-hoverable .list-group-item:focus,.list-group-hoverable .list-group-item:hover{background-color:rgba(var(--tblr-secondary-rgb),.08)}.list-group-hoverable .list-group-item-actions{opacity:0;transition:opacity .3s}@media(prefers-reduced-motion:reduce){.list-group-hoverable .list-group-item-actions{transition:none}}.list-group-hoverable .list-group-item:hover .list-group-item-actions,.list-group-hoverable .list-group-item-actions.show{opacity:1}.list-group-transparent{--tblr-list-group-border-radius: 0;margin:0 -1.25rem}.list-group-transparent .list-group-item{background:none;border:0}.list-group-transparent .list-group-item .icon{color:var(--tblr-secondary)}.list-group-transparent .list-group-item.active{font-weight:var(--tblr-font-weight-bold);color:inherit;background:var(--tblr-active-bg)}.list-group-transparent .list-group-item.active .icon{color:inherit}.list-separated{display:flex;flex-direction:column;gap:1rem}.list-inline{margin:0}.list-inline-item:not(:last-child){margin-right:auto;margin-inline-end:.5rem}.list-inline-dots .list-inline-item+.list-inline-item:before{content:" \b7 ";margin-inline-end:.5rem}.loader{position:relative;display:block;width:2.5rem;height:2.5rem;color:#066fd1;vertical-align:middle}.loader:after{position:absolute;top:0;left:0;width:100%;height:100%;content:"";border:1px var(--tblr-border-style);border-color:transparent;border-top-color:currentColor;border-left-color:currentColor;border-radius:100rem;animation:rotate-360 .6s linear;animation-iteration-count:infinite}.dimmer{position:relative}.dimmer .loader{position:absolute;top:50%;right:0;left:0;display:none;margin:0 auto;transform:translateY(-50%)}.dimmer.active .loader{display:block}.dimmer.active .dimmer-content{pointer-events:none;opacity:.1}@keyframes animated-dots{0%{transform:translate(-100%)}}.animated-dots{display:inline-block;overflow:hidden;vertical-align:bottom}.animated-dots:after{display:inline-block;content:"...";animation:animated-dots 1.2s steps(4,jump-none) infinite}.modal-content>.btn-close,.modal-header>.btn-close{position:absolute;top:0;right:0;width:3.5rem;height:3.5rem;margin:0;padding:0;z-index:10}.modal-body{scrollbar-color:color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent) transparent}.modal-body::-webkit-scrollbar{width:1rem;height:1rem;transition:background .3s}@media(prefers-reduced-motion:reduce){.modal-body::-webkit-scrollbar{transition:none}}.modal-body::-webkit-scrollbar-thumb{border-radius:1rem;border:5px solid transparent;box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent)}.modal-body::-webkit-scrollbar-track{background:transparent}.modal-body:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 40%,transparent)}.modal-body::-webkit-scrollbar-corner{background:transparent}.modal-body .modal-title{margin-bottom:1rem}.modal-body+.modal-body{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.modal-status{position:absolute;top:0;left:0;right:0;height:2px;background:var(--tblr-secondary);border-radius:var(--tblr-border-radius-lg) var(--tblr-border-radius-lg) 0 0}.modal-header{align-items:center;min-height:3.5rem;background:transparent;padding:0 3.5rem 0 1.5rem}.modal-title{font-size:1rem;font-weight:var(--tblr-font-weight-bold);color:inherit;line-height:1.4285714286}.modal-footer{padding-top:.75rem;padding-bottom:.75rem}.modal-blur{backdrop-filter:blur(4px)}.modal-full-width{max-width:none;margin:0 .5rem}.nav{--tblr-nav-link-hover-bg: color-mix(in srgb, var(--tblr-nav-link-color) 4%, transparent)}.nav-vertical,.nav-vertical .nav{flex-direction:column;flex-wrap:nowrap}.nav-vertical .nav{margin-left:1.25rem;border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);padding-left:.5rem}.nav-vertical .nav-link.active,.nav-vertical .nav-item.show .nav-link{font-weight:var(--tblr-font-weight-bold);color:var(--tblr-nav-link-active-color)}.nav-vertical.nav-pills{margin:0 -.75rem}.nav-bordered{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.nav-bordered .nav-item+.nav-item{margin-left:1.25rem}.nav-bordered .nav-link{padding-left:0;padding-right:0;margin:0 0 calc(-1 * var(--tblr-border-width));border:0;border-bottom:2px var(--tblr-border-style) transparent}.nav-bordered .nav-link:hover{background-color:transparent}.nav-bordered .nav-link.active,.nav-bordered .nav-item.show .nav-link{color:var(--tblr-primary);border-color:var(--tblr-primary)}.nav-underline .nav-link{border-radius:0}.nav-link{display:flex;transition:color .3s,background-color .3s}@media(prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link{align-items:center}.nav-link:hover,.nav-link:focus{background-color:var(--tblr-nav-link-hover-bg)}.nav-link-toggle{margin-left:auto;padding:0 .25rem;transition:transform .3s}@media(prefers-reduced-motion:reduce){.nav-link-toggle{transition:none}}.nav-link-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(-45deg)}.nav-link-toggle:after{margin:0}.nav-link[aria-expanded=true] .nav-link-toggle{transform:rotate(180deg)}.nav-link-icon{width:1.25rem;height:1.25rem;margin-right:.5rem;color:inherit}.nav-link-icon svg{display:block;height:100%}.nav-fill .nav-item .nav-link{justify-content:center}.stars{display:inline-flex;color:#9ca3af;font-size:.75rem}.stars .star:not(:first-child){margin-left:.25rem}.pagination{margin:0;--tblr-pagination-gap: .25rem;user-select:none;gap:var(--tblr-pagination-gap);line-height:var(--tblr-body-line-height)}.page-link{min-width:2rem;border-radius:var(--tblr-pagination-border-radius)}.page-item:not(.active) .page-link:hover{background:var(--tblr-pagination-hover-bg)}.page-text{padding-left:.5rem;padding-right:.5rem}.page-item{text-align:center}.page-item.page-prev,.page-item.page-next{flex:0 0 50%;text-align:left}.page-item.page-next{margin-left:auto;text-align:right}.page-item-subtitle{margin-bottom:2px;font-size:12px;color:var(--tblr-secondary);text-transform:uppercase}.page-item.disabled .page-item-subtitle{color:var(--tblr-disabled-color)}.page-item-title{font-size:1rem;font-weight:var(--tblr-font-weight-normal);color:var(--tblr-body-color)}.page-link:hover .page-item-title{color:#00857d}.page-item.disabled .page-item-title{color:var(--tblr-disabled-color)}.pagination-outline{--tblr-pagination-border-color: var(--tblr-border-color);--tblr-pagination-disabled-border-color: var(--tblr-border-color);--tblr-pagination-border-width: 1px}.pagination-circle{--tblr-pagination-border-radius: var(--tblr-border-radius-pill)}@keyframes progress-indeterminate{0%{right:100%;left:-35%}to,60%{right:-90%;left:100%}}.progress{position:relative;width:100%;line-height:.5rem;appearance:none}.progress::-webkit-progress-bar{background:var(--tblr-progress-bg)}.progress::-webkit-progress-value{background-color:var(--tblr-primary)}.progress::-moz-progress-bar{background-color:var(--tblr-primary)}.progress::-ms-fill{background-color:var(--tblr-primary);border:none}.progress-sm{height:.25rem}.progress-bar{height:100%}.progress-bar-indeterminate:after,.progress-bar-indeterminate:before{position:absolute;top:0;bottom:0;left:0;content:"";background-color:inherit;will-change:left,right}.progress-bar-indeterminate:before{animation:progress-indeterminate 1.5s cubic-bezier(.65,.815,.735,.395) infinite}.progress-separated .progress-bar{box-shadow:0 0 0 2px var(--tblr-card-bg, var(--tblr-bg-surface))}.progressbg{position:relative;padding:.25rem .5rem;display:flex}.progressbg-text{position:relative;z-index:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.progressbg-progress{position:absolute;inset:0;z-index:0;height:100%;background:transparent;pointer-events:none}.progressbg-value{font-weight:var(--tblr-font-weight-medium);margin-left:auto;padding-left:2rem}.ribbon{--tblr-ribbon-margin: .25rem;--tblr-ribbon-border-radius: var(--tblr-border-radius);position:absolute;top:.75rem;right:calc(-1 * var(--tblr-ribbon-margin));z-index:1;padding:.25rem .75rem;font-size:.625rem;font-weight:var(--tblr-font-weight-bold);line-height:1;color:#fff;text-align:center;text-transform:uppercase;background:var(--tblr-primary);border-color:var(--tblr-primary);border-radius:var(--tblr-ribbon-border-radius) 0 var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius);display:inline-flex;align-items:center;justify-content:center;min-height:2rem;min-width:2rem}.ribbon:before{position:absolute;right:0;bottom:100%;width:0;height:0;content:"";filter:brightness(70%);border:calc(var(--tblr-ribbon-margin) * .5) var(--tblr-border-style);border-color:inherit;border-top-color:transparent;border-right-color:transparent}.ribbon.bg-blue{border-color:var(--tblr-blue)}.ribbon.bg-blue-lt{border-color:rgba(var(--tblr-blue-rgb),.1)!important}.ribbon.bg-azure{border-color:var(--tblr-azure)}.ribbon.bg-azure-lt{border-color:rgba(var(--tblr-azure-rgb),.1)!important}.ribbon.bg-indigo{border-color:var(--tblr-indigo)}.ribbon.bg-indigo-lt{border-color:rgba(var(--tblr-indigo-rgb),.1)!important}.ribbon.bg-purple{border-color:var(--tblr-purple)}.ribbon.bg-purple-lt{border-color:rgba(var(--tblr-purple-rgb),.1)!important}.ribbon.bg-pink{border-color:var(--tblr-pink)}.ribbon.bg-pink-lt{border-color:rgba(var(--tblr-pink-rgb),.1)!important}.ribbon.bg-red{border-color:var(--tblr-red)}.ribbon.bg-red-lt{border-color:rgba(var(--tblr-red-rgb),.1)!important}.ribbon.bg-orange{border-color:var(--tblr-orange)}.ribbon.bg-orange-lt{border-color:rgba(var(--tblr-orange-rgb),.1)!important}.ribbon.bg-yellow{border-color:var(--tblr-yellow)}.ribbon.bg-yellow-lt{border-color:rgba(var(--tblr-yellow-rgb),.1)!important}.ribbon.bg-lime{border-color:var(--tblr-lime)}.ribbon.bg-lime-lt{border-color:rgba(var(--tblr-lime-rgb),.1)!important}.ribbon.bg-green{border-color:var(--tblr-green)}.ribbon.bg-green-lt{border-color:rgba(var(--tblr-green-rgb),.1)!important}.ribbon.bg-teal{border-color:var(--tblr-teal)}.ribbon.bg-teal-lt{border-color:rgba(var(--tblr-teal-rgb),.1)!important}.ribbon.bg-cyan{border-color:var(--tblr-cyan)}.ribbon.bg-cyan-lt{border-color:rgba(var(--tblr-cyan-rgb),.1)!important}.ribbon .icon{width:1.25rem;height:1.25rem;font-size:1.25rem}.ribbon-top{top:calc(-1 * var(--tblr-ribbon-margin));right:.75rem;width:2rem;padding:.5rem 0;border-radius:0 var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius)}.ribbon-top:before{top:0;right:100%;bottom:auto;border-color:inherit;border-top-color:transparent;border-left-color:transparent}.ribbon-top.ribbon-start{right:auto;left:.75rem}.ribbon-top.ribbon-start:before{top:0;right:100%;left:auto}.ribbon-start{right:auto;left:calc(-1 * var(--tblr-ribbon-margin));border-radius:0 var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius)}.ribbon-start:before{top:auto;bottom:100%;left:0;border-color:inherit;border-top-color:transparent;border-left-color:transparent}.ribbon-bottom{top:auto;bottom:.75rem}.ribbon-bookmark{padding-left:.25rem;border-radius:0 0 var(--tblr-ribbon-border-radius) 0}.ribbon-bookmark:after{position:absolute;top:0;right:100%;display:block;width:0;height:0;content:"";border:1rem var(--tblr-border-style);border-color:inherit;border-right-width:0;border-left-color:transparent;border-left-width:.5rem}.ribbon-bookmark.ribbon-left{padding-right:.5rem}.ribbon-bookmark.ribbon-left:after{right:auto;left:100%;border-right-color:transparent;border-right-width:.5rem;border-left-width:0}.ribbon-bookmark.ribbon-top{padding-right:0;padding-bottom:.25rem;padding-left:0;border-radius:0 var(--tblr-ribbon-border-radius) 0 0}.ribbon-bookmark.ribbon-top:after{top:100%;right:0;left:0;border-color:inherit;border-width:1rem;border-top-width:0;border-bottom-color:transparent;border-bottom-width:.5rem}.markdown{line-height:2}.markdown>:first-child{margin-top:0}.markdown>:last-child,.markdown>:last-child .highlight{margin-bottom:0}@media(min-width:768px){.markdown>hr,.markdown>.hr{margin-top:3em;margin-bottom:3em}}.markdown>h1,.markdown>.h1,.markdown>h2,.markdown>.h2,.markdown>h3,.markdown>.h3,.markdown>h4,.markdown>.h4,.markdown>h5,.markdown>.h5,.markdown>h6,.markdown>.h6{font-weight:var(--tblr-font-weight-bold)}.markdown>h2,.markdown>.h2,.markdown>h3,.markdown>.h3,.markdown>h4,.markdown>.h4,.markdown>h5,.markdown>.h5,.markdown>h6,.markdown>.h6{margin-top:2.5rem}.markdown>table{font-size:var(--tblr-body-font-size)}.markdown>blockquote{font-size:1rem;margin:1.5rem 0;padding:.5rem 1.5rem}.markdown>img,.markdown>p>img{border-radius:var(--tblr-border-radius);border:1px solid var(--tblr-border-color)}.markdown pre{max-height:20rem}.placeholder:not(.btn):not([class*=bg-]){background-color:currentColor!important}.placeholder:not(.avatar):not([class*=card-img-]){border-radius:var(--tblr-border-radius)}.nav-segmented{--tblr-nav-bg: var(--tblr-bg-surface-tertiary);--tblr-nav-padding: 2px;--tblr-nav-height: 2.5rem;--tblr-nav-gap: .25rem;--tblr-nav-active-bg: var(--tblr-bg-surface);--tblr-nav-font-size: inherit;--tblr-nav-radius: 6px;--tblr-nav-link-disabled-color: var(--tblr-disabled-color);--tblr-nav-link-gap: .25rem;--tblr-nav-link-padding-x: .75rem;--tblr-nav-link-icon-size: 1.25rem;display:inline-flex;flex-wrap:wrap;gap:var(--tblr-nav-gap);padding:var(--tblr-nav-padding);list-style:none;background:var(--tblr-nav-bg);border-radius:calc(var(--tblr-nav-radius) + var(--tblr-nav-padding));box-shadow:inset 0 0 0 1px #0000000a}.nav-segmented .nav-link{display:inline-flex;gap:calc(.25rem + var(--tblr-nav-link-gap));align-items:center;margin:0;font-size:var(--tblr-nav-font-size);min-width:calc(var(--tblr-nav-height) - 2 * var(--tblr-nav-padding));height:calc(var(--tblr-nav-height) - 2 * var(--tblr-nav-padding));padding:0 calc(var(--tblr-nav-link-padding-x) - 2px);border:1px solid transparent;background:transparent;color:var(--tblr-secondary);text-align:center;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .3s,color .3s;border-radius:var(--tblr-nav-radius);flex-grow:1;justify-content:center}.nav-segmented .nav-link:hover,.nav-segmented .nav-link.hover{background:#0000000a;color:var(--tblr-body-color)}.nav-segmented .nav-link.disabled,.nav-segmented .nav-link:disabled{color:var(--tblr-nav-link-disabled-color);cursor:not-allowed}.nav-segmented .nav-link-input:checked+.nav-link,.nav-segmented .nav-link.active{color:var(--tblr-body-color);background:var(--tblr-nav-active-bg);border-color:var(--tblr-border-color)}.nav-segmented .nav-link-input{display:none}.nav-segmented .nav-link-icon{width:var(--tblr-nav-link-icon-size);height:var(--tblr-nav-link-icon-size);margin:0 -.25rem;color:inherit}.nav-segmented-vertical{flex-direction:column}.nav-segmented-vertical .nav-link{justify-content:flex-start}.nav-sm{--tblr-nav-height: 2rem;--tblr-nav-font-size: var(--tblr-font-size-h5);--tblr-nav-radius: 4px;--tblr-nav-link-padding-x: .5rem;--tblr-nav-link-gap: .25rem;--tblr-nav-link-icon-size: 1rem}.nav-lg{--tblr-nav-height: 3rem;--tblr-nav-font-size: var(--tblr-font-size-h3);--tblr-nav-radius: 8px;--tblr-nav-link-padding-x: 1rem;--tblr-nav-link-gap: .5rem;--tblr-nav-link-icon-size: 1.5rem}.steps{--tblr-steps-color: var(--tblr-primary);--tblr-steps-inactive-color: var(--tblr-border-color);--tblr-steps-dot-size: .5rem;--tblr-steps-border-width: 2px;display:flex;flex-wrap:nowrap;width:100%;padding:0;margin:0;list-style:none}.steps-blue{--tblr-steps-color: var(--tblr-blue)}.steps-blue-lt{--tblr-steps-color: var(--tblr-blue-lt)}.steps-azure{--tblr-steps-color: var(--tblr-azure)}.steps-azure-lt{--tblr-steps-color: var(--tblr-azure-lt)}.steps-indigo{--tblr-steps-color: var(--tblr-indigo)}.steps-indigo-lt{--tblr-steps-color: var(--tblr-indigo-lt)}.steps-purple{--tblr-steps-color: var(--tblr-purple)}.steps-purple-lt{--tblr-steps-color: var(--tblr-purple-lt)}.steps-pink{--tblr-steps-color: var(--tblr-pink)}.steps-pink-lt{--tblr-steps-color: var(--tblr-pink-lt)}.steps-red{--tblr-steps-color: var(--tblr-red)}.steps-red-lt{--tblr-steps-color: var(--tblr-red-lt)}.steps-orange{--tblr-steps-color: var(--tblr-orange)}.steps-orange-lt{--tblr-steps-color: var(--tblr-orange-lt)}.steps-yellow{--tblr-steps-color: var(--tblr-yellow)}.steps-yellow-lt{--tblr-steps-color: var(--tblr-yellow-lt)}.steps-lime{--tblr-steps-color: var(--tblr-lime)}.steps-lime-lt{--tblr-steps-color: var(--tblr-lime-lt)}.steps-green{--tblr-steps-color: var(--tblr-green)}.steps-green-lt{--tblr-steps-color: var(--tblr-green-lt)}.steps-teal{--tblr-steps-color: var(--tblr-teal)}.steps-teal-lt{--tblr-steps-color: var(--tblr-teal-lt)}.steps-cyan{--tblr-steps-color: var(--tblr-cyan)}.steps-cyan-lt{--tblr-steps-color: var(--tblr-cyan-lt)}.step-item{position:relative;flex:1 1 0;min-height:1rem;margin-top:0;color:inherit;text-align:center;cursor:default;padding-top:calc(var(--tblr-steps-dot-size))}a.step-item{cursor:pointer}a.step-item:hover{color:inherit}.step-item:after,.step-item:before{background:var(--tblr-steps-color)}.step-item:not(:last-child):after{position:absolute;left:50%;width:100%;content:"";transform:translateY(-50%)}.step-item:after{top:calc(var(--tblr-steps-dot-size) * .5);height:var(--tblr-steps-border-width)}.step-item:before{content:"";position:absolute;top:0;left:50%;z-index:1;box-sizing:content-box;display:flex;align-items:center;justify-content:center;border-radius:100rem;transform:translate(-50%);color:var(--tblr-white);width:var(--tblr-steps-dot-size);height:var(--tblr-steps-dot-size)}.step-item.active{font-weight:var(--tblr-font-weight-bold)}.step-item.active:after{background:var(--tblr-steps-inactive-color)}.step-item.active~.step-item{color:var(--tblr-disabled-color)}.step-item.active~.step-item:after,.step-item.active~.step-item:before{background:var(--tblr-steps-inactive-color)}.steps-counter{--tblr-steps-dot-size: 1.5rem;counter-reset:steps}.steps-counter .step-item{counter-increment:steps}.steps-counter .step-item:before{content:counter(steps)}.steps-vertical{--tblr-steps-dot-offset: 6px;flex-direction:column}.steps-vertical.steps-counter{--tblr-steps-dot-offset: -2px}.steps-vertical .step-item{text-align:left;padding-top:0;padding-left:calc(var(--tblr-steps-dot-size) + 1rem);min-height:auto}.steps-vertical .step-item:not(:first-child){margin-top:1rem}.steps-vertical .step-item:before{top:var(--tblr-steps-dot-offset);left:0;transform:translate(0)}.steps-vertical .step-item:not(:last-child):after{position:absolute;content:"";transform:translate(-50%);top:var(--tblr-steps-dot-offset);left:calc(var(--tblr-steps-dot-size) * .5);width:var(--tblr-steps-border-width);height:calc(100% + 1rem)}@keyframes status-pulsate-main{40%{transform:scale(1.25)}60%{transform:scale(1.25)}}@keyframes status-pulsate-secondary{10%{transform:scale(1)}30%{transform:scale(3)}80%{transform:scale(3)}to{transform:scale(1)}}@keyframes status-pulsate-tertiary{25%{transform:scale(1)}80%{transform:scale(3);opacity:0}to{transform:scale(3);opacity:0}}.status{--tblr-status-height: 1.5rem;--tblr-status-color: #6b7280;--tblr-status-color-rgb: 107, 114, 128;display:inline-flex;align-items:center;height:var(--tblr-status-height);padding:.25rem .75rem;gap:.5rem;color:var(--tblr-status-color);background:rgba(var(--tblr-status-color-rgb),.1);font-size:.875rem;text-transform:none;letter-spacing:normal;border-radius:100rem;font-weight:var(--tblr-font-weight-medium);line-height:1;margin:0}.status .status-dot{background:var(--tblr-status-color)}.status .icon{font-size:1.25rem}.status-lite{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)!important;background:transparent!important;color:var(--tblr-body-color)!important}.status-primary{--tblr-status-color: #00857D;--tblr-status-color-rgb: 0, 133, 125}.status-secondary{--tblr-status-color: #6b7280;--tblr-status-color-rgb: 107, 114, 128}.status-success{--tblr-status-color: #2fb344;--tblr-status-color-rgb: 47, 179, 68}.status-info{--tblr-status-color: #4299e1;--tblr-status-color-rgb: 66, 153, 225}.status-warning{--tblr-status-color: #f59f00;--tblr-status-color-rgb: 245, 159, 0}.status-danger{--tblr-status-color: #d63939;--tblr-status-color-rgb: 214, 57, 57}.status-light{--tblr-status-color: #f9fafb;--tblr-status-color-rgb: 249, 250, 251}.status-dark{--tblr-status-color: #1f2937;--tblr-status-color-rgb: 31, 41, 55}.status-muted{--tblr-status-color: #6b7280;--tblr-status-color-rgb: 107, 114, 128}.status-blue{--tblr-status-color: #066fd1;--tblr-status-color-rgb: 6, 111, 209}.status-azure{--tblr-status-color: #4299e1;--tblr-status-color-rgb: 66, 153, 225}.status-indigo{--tblr-status-color: #4263eb;--tblr-status-color-rgb: 66, 99, 235}.status-purple{--tblr-status-color: #ae3ec9;--tblr-status-color-rgb: 174, 62, 201}.status-pink{--tblr-status-color: #d6336c;--tblr-status-color-rgb: 214, 51, 108}.status-red{--tblr-status-color: #d63939;--tblr-status-color-rgb: 214, 57, 57}.status-orange{--tblr-status-color: #f76707;--tblr-status-color-rgb: 247, 103, 7}.status-yellow{--tblr-status-color: #f59f00;--tblr-status-color-rgb: 245, 159, 0}.status-lime{--tblr-status-color: #74b816;--tblr-status-color-rgb: 116, 184, 22}.status-green{--tblr-status-color: #2fb344;--tblr-status-color-rgb: 47, 179, 68}.status-teal{--tblr-status-color: #0ca678;--tblr-status-color-rgb: 12, 166, 120}.status-cyan{--tblr-status-color: #17a2b8;--tblr-status-color-rgb: 23, 162, 184}.status-dot{--tblr-status-dot-color: var(--tblr-status-color, #6b7280);--tblr-status-size: .5rem;position:relative;display:inline-block;width:var(--tblr-status-size);height:var(--tblr-status-size);background:var(--tblr-status-dot-color);border-radius:100rem}.status-dot-animated:before{content:"";position:absolute;inset:0;z-index:0;background:inherit;border-radius:inherit;opacity:.6;animation:1s linear 2s backwards infinite status-pulsate-tertiary}.status-indicator{--tblr-status-indicator-size: 2.5rem;--tblr-status-indicator-color: var(--tblr-status-color, #6b7280);display:block;position:relative;width:var(--tblr-status-indicator-size);height:var(--tblr-status-indicator-size)}.status-indicator-circle{--tblr-status-circle-size: .75rem;position:absolute;left:50%;top:50%;margin:calc(var(--tblr-status-circle-size) / -2) 0 0 calc(var(--tblr-status-circle-size) / -2);width:var(--tblr-status-circle-size);height:var(--tblr-status-circle-size);border-radius:100rem;background:var(--tblr-status-color)}.status-indicator-circle:nth-child(1){z-index:3}.status-indicator-circle:nth-child(2){z-index:2;opacity:.1}.status-indicator-circle:nth-child(3){z-index:1;opacity:.3}.status-indicator-animated .status-indicator-circle:nth-child(1){animation:2s linear 1s infinite backwards status-pulsate-main}.status-indicator-animated .status-indicator-circle:nth-child(2){animation:2s linear 1s infinite backwards status-pulsate-secondary}.status-indicator-animated .status-indicator-circle:nth-child(3){animation:2s linear 1s infinite backwards status-pulsate-tertiary}.switch-icon{display:inline-block;line-height:1;border:0;padding:0;background:transparent;width:1.25rem;height:1.25rem;vertical-align:bottom;position:relative;cursor:pointer}.switch-icon.disabled{pointer-events:none;opacity:.4}.switch-icon:focus{outline:none}.switch-icon svg{display:block;width:100%;height:100%}.switch-icon .switch-icon-a,.switch-icon .switch-icon-b{display:block;width:100%;height:100%}.switch-icon .switch-icon-a{opacity:1}.switch-icon .switch-icon-b{position:absolute;top:0;left:0;opacity:0}.switch-icon.active .switch-icon-a{opacity:0}.switch-icon.active .switch-icon-b{opacity:1}.switch-icon-fade .switch-icon-a,.switch-icon-fade .switch-icon-b{transition:opacity .5s}@media(prefers-reduced-motion:reduce){.switch-icon-fade .switch-icon-a,.switch-icon-fade .switch-icon-b{transition:none}}.switch-icon-scale .switch-icon-a,.switch-icon-scale .switch-icon-b{transition:opacity .5s,transform 0s .5s}@media(prefers-reduced-motion:reduce){.switch-icon-scale .switch-icon-a,.switch-icon-scale .switch-icon-b{transition:none}}.switch-icon-scale .switch-icon-b{transform:scale(1.5)}.switch-icon-scale.active .switch-icon-a,.switch-icon-scale.active .switch-icon-b{transition:opacity 0s,transform .5s}@media(prefers-reduced-motion:reduce){.switch-icon-scale.active .switch-icon-a,.switch-icon-scale.active .switch-icon-b{transition:none}}.switch-icon-scale.active .switch-icon-b{transform:scale(1)}.switch-icon-flip{perspective:10em}.switch-icon-flip .switch-icon-a,.switch-icon-flip .switch-icon-b{backface-visibility:hidden;transform-style:preserve-3d;transition:opacity 0s .2s,transform .4s ease-in-out}@media(prefers-reduced-motion:reduce){.switch-icon-flip .switch-icon-a,.switch-icon-flip .switch-icon-b{transition:none}}.switch-icon-flip .switch-icon-a{opacity:1;transform:rotateY(0)}.switch-icon-flip .switch-icon-b{opacity:1;transform:rotateY(-180deg)}.switch-icon-flip.active .switch-icon-a{opacity:1;transform:rotateY(180deg)}.switch-icon-flip.active .switch-icon-b{opacity:1;transform:rotateY(0)}.switch-icon-slide-up,.switch-icon-slide-left,.switch-icon-slide-start,.switch-icon-slide-right,.switch-icon-slide-end,.switch-icon-slide-down{overflow:hidden}.switch-icon-slide-up .switch-icon-a,.switch-icon-slide-up .switch-icon-b,.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-a,.switch-icon-slide-start .switch-icon-b,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-a,.switch-icon-slide-end .switch-icon-b,.switch-icon-slide-down .switch-icon-a,.switch-icon-slide-down .switch-icon-b{transition:opacity .3s,transform .3s}@media(prefers-reduced-motion:reduce){.switch-icon-slide-up .switch-icon-a,.switch-icon-slide-up .switch-icon-b,.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-a,.switch-icon-slide-start .switch-icon-b,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-a,.switch-icon-slide-end .switch-icon-b,.switch-icon-slide-down .switch-icon-a,.switch-icon-slide-down .switch-icon-b{transition:none}}.switch-icon-slide-up .switch-icon-a,.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-start .switch-icon-a,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-end .switch-icon-a,.switch-icon-slide-down .switch-icon-a{transform:translateY(0)}.switch-icon-slide-up .switch-icon-b,.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-b,.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-b,.switch-icon-slide-down .switch-icon-b{transform:translateY(100%)}.switch-icon-slide-up.active .switch-icon-a,.switch-icon-slide-left.active .switch-icon-a,.switch-icon-slide-start.active .switch-icon-a,.switch-icon-slide-right.active .switch-icon-a,.switch-icon-slide-end.active .switch-icon-a,.switch-icon-slide-down.active .switch-icon-a{transform:translateY(-100%)}.switch-icon-slide-up.active .switch-icon-b,.switch-icon-slide-left.active .switch-icon-b,.switch-icon-slide-start.active .switch-icon-b,.switch-icon-slide-right.active .switch-icon-b,.switch-icon-slide-end.active .switch-icon-b,.switch-icon-slide-down.active .switch-icon-b{transform:translateY(0)}.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-start .switch-icon-a{transform:translate(0)}.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-b{transform:translate(100%)}.switch-icon-slide-left.active .switch-icon-a,.switch-icon-slide-start.active .switch-icon-a{transform:translate(-100%)}.switch-icon-slide-left.active .switch-icon-b,.switch-icon-slide-start.active .switch-icon-b,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-end .switch-icon-a{transform:translate(0)}.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-b{transform:translate(-100%)}.switch-icon-slide-right.active .switch-icon-a,.switch-icon-slide-end.active .switch-icon-a{transform:translate(100%)}.switch-icon-slide-right.active .switch-icon-b,.switch-icon-slide-end.active .switch-icon-b{transform:translate(0)}.switch-icon-slide-down .switch-icon-a{transform:translateY(0)}.switch-icon-slide-down .switch-icon-b{transform:translateY(-100%)}.switch-icon-slide-down.active .switch-icon-a{transform:translateY(100%)}.switch-icon-slide-down.active .switch-icon-b{transform:translateY(0)}.table thead th,.markdown>table thead th{background:var(--tblr-bg-surface-tertiary);font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);padding-top:.5rem;padding-bottom:.5rem;white-space:nowrap}@media print{.table thead th,.markdown>table thead th{background:transparent}}.table-responsive .table,.table-responsive .markdown>table{margin-bottom:0}.table-responsive+.card-footer{border-top:0}.table-transparent thead th{background:transparent}.table-nowrap>:not(caption)>*>*{white-space:nowrap}.table-vcenter>:not(caption)>*>*{vertical-align:middle}.table-center>:not(caption)>*>*{text-align:center}.td-truncate{max-width:1px;width:100%}.table-mobile{display:block}.table-mobile thead{display:none}.table-mobile tbody,.table-mobile tr{display:flex;flex-direction:column}.table-mobile td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile .btn{display:block}@media(max-width:575.98px){.table-mobile-sm{display:block}.table-mobile-sm thead{display:none}.table-mobile-sm tbody,.table-mobile-sm tr{display:flex;flex-direction:column}.table-mobile-sm td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-sm td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-sm tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-sm .btn{display:block}}@media(max-width:767.98px){.table-mobile-md{display:block}.table-mobile-md thead{display:none}.table-mobile-md tbody,.table-mobile-md tr{display:flex;flex-direction:column}.table-mobile-md td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-md td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-md tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-md .btn{display:block}}@media(max-width:991.98px){.table-mobile-lg{display:block}.table-mobile-lg thead{display:none}.table-mobile-lg tbody,.table-mobile-lg tr{display:flex;flex-direction:column}.table-mobile-lg td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-lg td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-lg tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-lg .btn{display:block}}@media(max-width:1199.98px){.table-mobile-xl{display:block}.table-mobile-xl thead{display:none}.table-mobile-xl tbody,.table-mobile-xl tr{display:flex;flex-direction:column}.table-mobile-xl td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-xl td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-xl tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-xl .btn{display:block}}@media(max-width:1399.98px){.table-mobile-xxl{display:block}.table-mobile-xxl thead{display:none}.table-mobile-xxl tbody,.table-mobile-xxl tr{display:flex;flex-direction:column}.table-mobile-xxl td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-xxl td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-xxl tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-xxl .btn{display:block}}.table-sort{font:inherit;color:inherit;text-transform:inherit;letter-spacing:inherit;border:0;background:inherit;display:block;width:100%;text-align:inherit;transition:color .3s}@media(prefers-reduced-motion:reduce){.table-sort{transition:none}}.table-sort{margin:-.5rem;padding:.5rem}.table-sort:hover,.table-sort.asc,.table-sort.desc{color:var(--tblr-body-color)}.table-sort:after{content:"";display:inline-flex;width:1rem;height:1rem;vertical-align:bottom;mask-image:url("data:image/svg+xml,");background:currentColor;margin-left:.25rem}.table-sort.asc:after{mask-image:url("data:image/svg+xml,")}.table-sort.desc:after{mask-image:url("data:image/svg+xml,")}.table-borderless thead th{background:transparent}.table-selectable tbody tr .on-checked{display:none}.table-selectable tbody tr .on-unchecked{display:initial}.table-selectable tbody tr:has(.table-selectable-check:checked){background-color:var(--tblr-active-bg)}.table-selectable tbody tr:has(.table-selectable-check:checked) .on-checked{display:initial}.table-selectable tbody tr:has(.table-selectable-check:checked) .on-unchecked{display:none}.tag{--tblr-tag-height: 1.5rem;border:1px solid var(--tblr-border-color);display:inline-flex;align-items:center;height:var(--tblr-tag-height);border-radius:var(--tblr-border-radius);padding:0 .5rem;background:var(--tblr-bg-surface);box-shadow:var(--tblr-shadow-input);gap:.5rem}.tag .btn-close{margin-right:-.25rem;margin-left:-.125rem;padding:0;width:1rem;height:1rem;font-size:.5rem}.tag-badge{--tblr-badge-font-size: .625rem;--tblr-badge-padding-x: .25rem;--tblr-badge-padding-y: .125rem;margin-right:-.25rem}.tag-avatar,.tag-flag,.tag-payment,.tag-icon,.tag-check{margin-left:-.25rem}.tag-icon{color:var(--tblr-secondary);margin-right:-.125rem;width:1rem;height:1rem}.tag-check{width:1rem;height:1rem;background-size:1rem}.tags-list{--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.toast{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);box-shadow:#1f29370a 0 2px 4px}.toast .toast-header{user-select:none}.toast button[data-bs-dismiss=toast]{outline:none}.toast-primary{--tblr-toast-color: #00857D}.toast-secondary{--tblr-toast-color: #6b7280}.toast-success{--tblr-toast-color: #2fb344}.toast-info{--tblr-toast-color: #4299e1}.toast-warning{--tblr-toast-color: #f59f00}.toast-danger{--tblr-toast-color: #d63939}.toast-light{--tblr-toast-color: #f9fafb}.toast-dark{--tblr-toast-color: #1f2937}.toast-muted{--tblr-toast-color: #6b7280}.toast-blue{--tblr-toast-color: #066fd1}.toast-azure{--tblr-toast-color: #4299e1}.toast-indigo{--tblr-toast-color: #4263eb}.toast-purple{--tblr-toast-color: #ae3ec9}.toast-pink{--tblr-toast-color: #d6336c}.toast-red{--tblr-toast-color: #d63939}.toast-orange{--tblr-toast-color: #f76707}.toast-yellow{--tblr-toast-color: #f59f00}.toast-lime{--tblr-toast-color: #74b816}.toast-green{--tblr-toast-color: #2fb344}.toast-teal{--tblr-toast-color: #0ca678}.toast-cyan{--tblr-toast-color: #17a2b8}.toolbar{display:flex;flex-wrap:nowrap;flex-shrink:0;margin:0 -.5rem}.toolbar>*{margin:0 .5rem}.tracking{--tblr-tracking-height: 1.5rem;--tblr-tracking-gap-width: .125rem;--tblr-tracking-block-border-radius: var(--tblr-border-radius);display:flex;gap:var(--tblr-tracking-gap-width)}.tracking-squares{--tblr-tracking-block-border-radius: var(--tblr-border-radius-sm)}.tracking-squares .tracking-block{height:auto}.tracking-squares .tracking-block:before{content:"";display:block;padding-top:100%}.tracking-block{flex:1;border-radius:var(--tblr-tracking-block-border-radius);height:var(--tblr-tracking-height);min-width:.25rem;background:var(--tblr-border-color)}.timeline{--tblr-timeline-icon-size: 2.5rem;position:relative;list-style:none;padding:0}.timeline-event{position:relative}.timeline-event:not(:last-child){margin-bottom:var(--tblr-page-padding)}.timeline-event:not(:last-child):before{content:"";position:absolute;top:var(--tblr-timeline-icon-size);left:calc(var(--tblr-timeline-icon-size) / 2);bottom:calc(-1 * var(--tblr-page-padding));width:var(--tblr-border-width);background-color:var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.timeline-event-icon{position:absolute;display:flex;align-items:center;justify-content:center;width:var(--tblr-timeline-icon-size, 2.5rem);height:var(--tblr-timeline-icon-size, 2.5rem);background:var(--tblr-bg-surface-secondary);color:var(--tblr-secondary);border-radius:var(--tblr-border-radius);z-index:5}.timeline-event-card{margin-left:calc(var(--tblr-timeline-icon-size, 2.5rem) + var(--tblr-page-padding))}.timeline-simple .timeline-event-icon{display:none}.timeline-simple .timeline-event-card{margin-left:0}.hr-text{display:flex;align-items:center;margin:2rem 0;font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);height:1px}.hr-text:after,.hr-text:before{flex:1 1 auto;height:1px;background-color:var(--tblr-border-color)}.hr-text:before{content:"";margin-right:.5rem}.hr-text:after{content:"";margin-left:.5rem}.hr-text>*:first-child{padding-right:.5rem;padding-left:0;color:var(--tblr-secondary)}.hr-text.hr-text-left:before,.hr-text.hr-text-start:before{content:none}.hr-text.hr-text-left>*:first-child,.hr-text.hr-text-start>*:first-child{padding-right:.5rem;padding-left:.5rem}.hr-text.hr-text-right:before,.hr-text.hr-text-end:before{content:""}.hr-text.hr-text-right:after,.hr-text.hr-text-end:after{content:none}.hr-text.hr-text-right>*:first-child,.hr-text.hr-text-end>*:first-child{padding-right:0;padding-left:.5rem}.card>.hr-text{margin:0}.hr-text-spaceless{margin:-.5rem 0}.lead{color:var(--tblr-secondary);font-size:inherit}a{text-decoration-skip-ink:auto;color:color-mix(in srgb,transparent,var(--tblr-link-color) var(--tblr-link-opacity, 100%))}a:hover{color:color-mix(in srgb,transparent,var(--tblr-link-hover-color) var(--tblr-link-opacity, 100%))}h1 a,h2 a,h3 a,.field-group h2 a,h4 a,h5 a,h6 a,.h1 a,.h2 a,.h3 a,.h4 a,.h5 a,.h6 a,h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover,.h1 a:hover,.h2 a:hover,.h3 a:hover,.h4 a:hover,.h5 a:hover,.h6 a:hover{color:inherit}h1,.h1{font-size:var(--tblr-font-size-h1);line-height:var(--tblr-line-height-h1)}h2,.h2{font-size:var(--tblr-font-size-h2);line-height:var(--tblr-line-height-h2)}h3,.field-group h2,.field-group .h2,.h3{font-size:var(--tblr-font-size-h3);line-height:var(--tblr-line-height-h3)}h4,.h4{font-size:var(--tblr-font-size-h4);line-height:var(--tblr-line-height-h4)}h5,.h5{font-size:var(--tblr-font-size-h5);line-height:var(--tblr-line-height-h5)}h6,.h6{font-size:var(--tblr-font-size-h6);line-height:var(--tblr-line-height-h6)}.fs-base{font-size:var(--tblr-body-font-size)}strong,.strong,b{font-weight:var(--tblr-font-weight-bold)}blockquote{padding:1rem;border-left:2px var(--tblr-border-style) var(--tblr-border-color)}blockquote p{margin-bottom:1rem}blockquote cite{display:block;text-align:right}blockquote cite:before{content:"\2014 "}ul,ol{padding-left:1.5rem}hr,.hr{margin:2rem 0}dl dd:last-child{margin-bottom:0}pre{--tblr-scrollbar-color: var(--tblr-light);padding:1rem;background:var(--tblr-bg-surface-dark);color:var(--tblr-light);border-radius:var(--tblr-border-radius);line-height:1.4285714286}pre{scrollbar-color:color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent) transparent}pre::-webkit-scrollbar{width:1rem;height:1rem;transition:background .3s}@media(prefers-reduced-motion:reduce){pre::-webkit-scrollbar{transition:none}}pre::-webkit-scrollbar-thumb{border-radius:1rem;border:5px solid transparent;box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent)}pre::-webkit-scrollbar-track{background:transparent}pre:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 40%,transparent)}pre::-webkit-scrollbar-corner{background:transparent}pre code{background:transparent;padding:0}code{background:var(--tblr-code-bg);padding:2px 4px;border-radius:var(--tblr-border-radius)}abbr{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}kbd,.kbd{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);display:inline-block;box-sizing:border-box;max-width:100%;font-size:var(--tblr-font-size-h5);font-weight:var(--tblr-font-weight-medium);line-height:1;vertical-align:baseline;border-radius:var(--tblr-border-radius)}img{max-width:100%;height:auto}.list-unstyled{margin-left:0}::selection,.text-selected{background-color:color-mix(in srgb,var(--tblr-primary) 10%,transparent)}.text-selected{display:inline-block}[class^=link-].disabled,[class*=" link-"].disabled{color:var(--tblr-disabled-color)!important;pointer-events:none}a:hover:has(.icon){text-decoration:none}.link-hoverable{border-radius:var(--tblr-border-radius);transition:background-color .15s ease-in-out}.link-hoverable:hover{text-decoration:none;color:var(--tblr-primary);background:color-mix(in srgb,var(--tblr-secondary) 4%,transparent)}.subheader{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary)}.mention{display:inline-block;box-shadow:var(--tblr-shadow-border);border-radius:var(--tblr-border-radius-pill);line-height:1.3333333333em;font-size:.8571428571em;color:var(--tblr-body-color);background:var(--tblr-bg-surface-tertiary);padding:.1666666667em .6666666667em;font-weight:var(--tblr-font-weight-medium)}a.mention{cursor:pointer}a.mention:hover,a.mention.hover{background:var(--tblr-bg-surface-secondary);text-decoration:underline}.mention-avatar,.mention-app,.mention-color{width:1.1666666667em;height:1.1666666667em;border-radius:var(--tblr-border-radius-pill);margin:-.1666666667em .3333333333em 0 -.3333333333em;display:inline-flex;background:no-repeat center center/cover;box-shadow:var(--tblr-shadow-border);vertical-align:middle;text-align:center}.mention-app{box-shadow:none;background:none;border-radius:0}.mention-count{color:var(--tblr-secondary);margin-left:.6666666667em}.text-incorrect{background:color-mix(in srgb,var(--tblr-red) 4%,transparent);text-decoration:underline;text-decoration-thickness:1px;text-decoration-color:var(--tblr-red)}.text-correct{background:color-mix(in srgb,var(--tblr-green) 4%,transparent);text-decoration:underline;text-decoration-thickness:1px;text-decoration-color:var(--tblr-green)}.steps{--tblr-steps-padding: 2rem;--tblr-steps-item-size: 1.5rem;margin-left:1rem;padding-left:var(--tblr-steps-padding);counter-reset:step;border-left:1px solid var(--tblr-border-color);margin-bottom:2rem}.steps h3,.steps .field-group h2,.field-group .steps h2,.steps .field-group .h2,.field-group .steps .h2,.steps .h3{counter-increment:step}.steps h3:not(:first-child),.steps .field-group h2:not(:first-child),.field-group .steps h2:not(:first-child),.steps .field-group .h2:not(:first-child),.field-group .steps .h2:not(:first-child),.steps .h3:not(:first-child){margin-top:2.5rem!important}.steps h3:before,.steps .field-group h2:before,.field-group .steps h2:before,.steps .field-group .h2:before,.field-group .steps .h2:before,.steps .h3:before{content:counter(step);display:inline-block;position:absolute;margin-top:1px;margin-left:calc(-1 * var(--tblr-steps-padding) - var(--tblr-steps-item-size) / 2);width:var(--tblr-steps-item-size);height:var(--tblr-steps-item-size);text-align:center;color:var(--tblr-body-color);border:1px solid var(--tblr-border-color);background:var(--tblr-bg-surface);border-radius:var(--tblr-border-radius);line-height:calc(var(--tblr-steps-item-size) - 2px);font-size:var(--tblr-font-size-h4);font-weight:var(--tblr-font-weight-bold)}.steps>:last-child{margin-bottom:0}.callout{margin-bottom:1.5rem;border:1px solid var(--tblr-primary-200);border-radius:var(--tblr-border-radius);padding:.5rem 1rem;background:var(--tblr-primary-lt)}.callout>:last-child{margin-bottom:0}.chart{display:block;min-height:10rem}.chart text{font-family:inherit}.chart-sm{height:2.5rem}.chart-lg{height:15rem}.chart-square{height:5.75rem}.chart-sparkline{position:relative;width:4rem;height:2.5rem;line-height:1;min-height:0!important}.chart-sparkline-sm{height:1.5rem}.chart-sparkline-square{width:2.5rem}.chart-sparkline-wide{width:6rem}.chart-sparkline-label{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:.625rem}.chart-sparkline-label .icon{width:1rem;height:1rem;font-size:1rem}.offcanvas-header{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.offcanvas-footer{padding:1.5rem}.offcanvas-title{font-size:1rem;font-weight:var(--tblr-font-weight-medium);line-height:1.5rem}.offcanvas-narrow{width:20rem}.chat-bubbles{display:flex;flex-direction:column;gap:1rem}.chat-bubble{background:var(--tblr-bg-surface-secondary);border-radius:var(--tblr-border-radius-lg);padding:1rem;position:relative}.chat-bubble-me{background-color:var(--tblr-primary-lt);box-shadow:none}.chat-bubble-title{margin-bottom:.25rem}.chat-bubble-author{font-weight:600}.chat-bubble-date{color:var(--tblr-secondary)}.chat-bubble-body>*:last-child{margin-bottom:0}.signature{--tblr-signature-padding: var(--tblr-spacer-1);--tblr-signature-border-radius: var(--tblr-border-radius);border:var(--tblr-border-width) solid var(--tblr-border-color);padding:var(--tblr-signature-padding);border-radius:var(--tblr-border-radius)}.signature-canvas{border:var(--tblr-border-width) dashed var(--tblr-border-color);border-radius:calc(var(--tblr-signature-border-radius) - var(--tblr-signature-padding));display:block;cursor:crosshair;width:100%}.clearfix:after{display:block;clear:both;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:var(--tblr-border-width);min-height:1em;background-color:currentcolor;opacity:.16}.stretched-link:after{position:absolute;inset:0;z-index:1;content:""}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.visually-hidden:not(caption),.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption){position:absolute!important}.visually-hidden *,.visually-hidden-focusable:not(:focus):not(:focus-within) *{overflow:hidden!important}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media(min-width:576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.ratio{position:relative;width:100%}.ratio:before{display:block;padding-top:var(--tblr-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--tblr-aspect-ratio: 100%}.ratio-2x1{--tblr-aspect-ratio: 50%}.ratio-1x2{--tblr-aspect-ratio: 200%}.ratio-3x1{--tblr-aspect-ratio: 33.3333333333%}.ratio-1x3{--tblr-aspect-ratio: 300%}.ratio-4x1{--tblr-aspect-ratio: 25%}.ratio-1x4{--tblr-aspect-ratio: 400%}.ratio-4x3{--tblr-aspect-ratio: 75%}.ratio-3x4{--tblr-aspect-ratio: 133.3333333333%}.ratio-16x9{--tblr-aspect-ratio: 56.25%}.ratio-9x16{--tblr-aspect-ratio: 177.7777777778%}.ratio-21x9{--tblr-aspect-ratio: 42.8571428571%}.ratio-9x21{--tblr-aspect-ratio: 233.3333333333%}.focus-ring:focus{outline:0;box-shadow:var(--tblr-focus-ring-x, 0) var(--tblr-focus-ring-y, 0) var(--tblr-focus-ring-blur, 0) var(--tblr-focus-ring-width) var(--tblr-focus-ring-color)}.bg-white-overlay{color:#fff;background-color:#f9fafb3d}.bg-dark-overlay{color:#fff;background-color:#1f29373d}.bg-cover{background-repeat:no-repeat;background-size:cover;background-position:center}.bg-primary{background-color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-primary-lt{color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-primary-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-primary{border-color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-primary{--tblr-gradient-from: var(--tblr-primary)}.bg-gradient-to-primary{--tblr-gradient-to: var(--tblr-primary)}.bg-gradient-via-primary{--tblr-gradient-via: var(--tblr-primary);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-primary{color:#f9fafb!important;background-color:RGBA(var(--tblr-primary-rgb),var(--tblr-bg-opacity, 1))!important}.link-primary{color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-primary:hover,.link-primary:focus{color:RGBA(0,106,100,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(0,106,100,var(--tblr-link-underline-opacity, 1))!important}.bg-secondary{background-color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-secondary-lt{color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-secondary-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-secondary{border-color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-secondary{--tblr-gradient-from: var(--tblr-secondary)}.bg-gradient-to-secondary{--tblr-gradient-to: var(--tblr-secondary)}.bg-gradient-via-secondary{--tblr-gradient-via: var(--tblr-secondary);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-secondary,.text-bg-gray{color:#f9fafb!important;background-color:RGBA(var(--tblr-secondary-rgb),var(--tblr-bg-opacity, 1))!important}.link-secondary{color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-secondary:hover,.link-secondary:focus{color:RGBA(86,91,102,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(86,91,102,var(--tblr-link-underline-opacity, 1))!important}.bg-success{background-color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-success-lt{color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-success-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-success{border-color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-success{--tblr-gradient-from: var(--tblr-success)}.bg-gradient-to-success{--tblr-gradient-to: var(--tblr-success)}.bg-gradient-via-success{--tblr-gradient-via: var(--tblr-success);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-success{color:#f9fafb!important;background-color:RGBA(var(--tblr-success-rgb),var(--tblr-bg-opacity, 1))!important}.link-success{color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-success:hover,.link-success:focus{color:RGBA(38,143,54,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(38,143,54,var(--tblr-link-underline-opacity, 1))!important}.bg-info{background-color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-info-lt{color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-info-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-info{border-color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-info{--tblr-gradient-from: var(--tblr-info)}.bg-gradient-to-info{--tblr-gradient-to: var(--tblr-info)}.bg-gradient-via-info{--tblr-gradient-via: var(--tblr-info);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-info{color:#f9fafb!important;background-color:RGBA(var(--tblr-info-rgb),var(--tblr-bg-opacity, 1))!important}.link-info{color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-info:hover,.link-info:focus{color:RGBA(53,122,180,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(53,122,180,var(--tblr-link-underline-opacity, 1))!important}.bg-warning{background-color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-warning-lt{color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-warning-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-warning{border-color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-warning{--tblr-gradient-from: var(--tblr-warning)}.bg-gradient-to-warning{--tblr-gradient-to: var(--tblr-warning)}.bg-gradient-via-warning{--tblr-gradient-via: var(--tblr-warning);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-warning{color:#f9fafb!important;background-color:RGBA(var(--tblr-warning-rgb),var(--tblr-bg-opacity, 1))!important}.link-warning{color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-warning:hover,.link-warning:focus{color:RGBA(196,127,0,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(196,127,0,var(--tblr-link-underline-opacity, 1))!important}.bg-danger{background-color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-danger-lt{color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-danger-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-danger{border-color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-danger{--tblr-gradient-from: var(--tblr-danger)}.bg-gradient-to-danger{--tblr-gradient-to: var(--tblr-danger)}.bg-gradient-via-danger{--tblr-gradient-via: var(--tblr-danger);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-danger{color:#f9fafb!important;background-color:RGBA(var(--tblr-danger-rgb),var(--tblr-bg-opacity, 1))!important}.link-danger{color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-danger:hover,.link-danger:focus{color:RGBA(171,46,46,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(171,46,46,var(--tblr-link-underline-opacity, 1))!important}.bg-light{background-color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-light-lt{color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-light-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-light{border-color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-light{--tblr-gradient-from: var(--tblr-light)}.bg-gradient-to-light{--tblr-gradient-to: var(--tblr-light)}.bg-gradient-via-light{--tblr-gradient-via: var(--tblr-light);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-light,.text-bg-white{color:#1f2937!important;background-color:RGBA(var(--tblr-light-rgb),var(--tblr-bg-opacity, 1))!important}.link-light{color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-light:hover,.link-light:focus{color:RGBA(250,251,252,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(250,251,252,var(--tblr-link-underline-opacity, 1))!important}.bg-dark{background-color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-dark-lt{color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-dark-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-dark{border-color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-dark{--tblr-gradient-from: var(--tblr-dark)}.bg-gradient-to-dark{--tblr-gradient-to: var(--tblr-dark)}.bg-gradient-via-dark{--tblr-gradient-via: var(--tblr-dark);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-dark,.text-bg-black{color:#f9fafb!important;background-color:RGBA(var(--tblr-dark-rgb),var(--tblr-bg-opacity, 1))!important}.link-dark{color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-dark:hover,.link-dark:focus{color:RGBA(25,33,44,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(25,33,44,var(--tblr-link-underline-opacity, 1))!important}.bg-muted{background-color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-muted-lt{color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-muted-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-muted{border-color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-muted{--tblr-gradient-from: var(--tblr-muted)}.bg-gradient-to-muted{--tblr-gradient-to: var(--tblr-muted)}.bg-gradient-via-muted{--tblr-gradient-via: var(--tblr-muted);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-muted{color:#f9fafb!important;background-color:RGBA(var(--tblr-muted-rgb),var(--tblr-bg-opacity, 1))!important}.link-muted{color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-muted:hover,.link-muted:focus{color:RGBA(86,91,102,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(86,91,102,var(--tblr-link-underline-opacity, 1))!important}.bg-blue{background-color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-blue-lt{color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-blue-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-blue{border-color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-blue{--tblr-gradient-from: var(--tblr-blue)}.bg-gradient-to-blue{--tblr-gradient-to: var(--tblr-blue)}.bg-gradient-via-blue{--tblr-gradient-via: var(--tblr-blue);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-blue{color:#f9fafb!important;background-color:RGBA(var(--tblr-blue-rgb),var(--tblr-bg-opacity, 1))!important}.link-blue{color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-blue:hover,.link-blue:focus{color:RGBA(5,89,167,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(5,89,167,var(--tblr-link-underline-opacity, 1))!important}.bg-azure{background-color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-azure-lt{color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-azure-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-azure{border-color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-azure{--tblr-gradient-from: var(--tblr-azure)}.bg-gradient-to-azure{--tblr-gradient-to: var(--tblr-azure)}.bg-gradient-via-azure{--tblr-gradient-via: var(--tblr-azure);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-azure{color:#f9fafb!important;background-color:RGBA(var(--tblr-azure-rgb),var(--tblr-bg-opacity, 1))!important}.link-azure{color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-azure:hover,.link-azure:focus{color:RGBA(53,122,180,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(53,122,180,var(--tblr-link-underline-opacity, 1))!important}.bg-indigo{background-color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-indigo-lt{color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-indigo-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-indigo{border-color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-indigo{--tblr-gradient-from: var(--tblr-indigo)}.bg-gradient-to-indigo{--tblr-gradient-to: var(--tblr-indigo)}.bg-gradient-via-indigo{--tblr-gradient-via: var(--tblr-indigo);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-indigo{color:#f9fafb!important;background-color:RGBA(var(--tblr-indigo-rgb),var(--tblr-bg-opacity, 1))!important}.link-indigo{color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-indigo:hover,.link-indigo:focus{color:RGBA(53,79,188,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(53,79,188,var(--tblr-link-underline-opacity, 1))!important}.bg-purple{background-color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-purple-lt{color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-purple-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-purple{border-color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-purple{--tblr-gradient-from: var(--tblr-purple)}.bg-gradient-to-purple{--tblr-gradient-to: var(--tblr-purple)}.bg-gradient-via-purple{--tblr-gradient-via: var(--tblr-purple);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-purple{color:#f9fafb!important;background-color:RGBA(var(--tblr-purple-rgb),var(--tblr-bg-opacity, 1))!important}.link-purple{color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-purple:hover,.link-purple:focus{color:RGBA(139,50,161,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(139,50,161,var(--tblr-link-underline-opacity, 1))!important}.bg-pink{background-color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-pink-lt{color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-pink-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-pink{border-color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-pink{--tblr-gradient-from: var(--tblr-pink)}.bg-gradient-to-pink{--tblr-gradient-to: var(--tblr-pink)}.bg-gradient-via-pink{--tblr-gradient-via: var(--tblr-pink);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-pink{color:#f9fafb!important;background-color:RGBA(var(--tblr-pink-rgb),var(--tblr-bg-opacity, 1))!important}.link-pink{color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-pink:hover,.link-pink:focus{color:RGBA(171,41,86,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(171,41,86,var(--tblr-link-underline-opacity, 1))!important}.bg-red{background-color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-red-lt{color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-red-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-red{border-color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-red{--tblr-gradient-from: var(--tblr-red)}.bg-gradient-to-red{--tblr-gradient-to: var(--tblr-red)}.bg-gradient-via-red{--tblr-gradient-via: var(--tblr-red);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-red{color:#f9fafb!important;background-color:RGBA(var(--tblr-red-rgb),var(--tblr-bg-opacity, 1))!important}.link-red{color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-red:hover,.link-red:focus{color:RGBA(171,46,46,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(171,46,46,var(--tblr-link-underline-opacity, 1))!important}.bg-orange{background-color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-orange-lt{color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-orange-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-orange{border-color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-orange{--tblr-gradient-from: var(--tblr-orange)}.bg-gradient-to-orange{--tblr-gradient-to: var(--tblr-orange)}.bg-gradient-via-orange{--tblr-gradient-via: var(--tblr-orange);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-orange{color:#f9fafb!important;background-color:RGBA(var(--tblr-orange-rgb),var(--tblr-bg-opacity, 1))!important}.link-orange{color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-orange:hover,.link-orange:focus{color:RGBA(198,82,6,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(198,82,6,var(--tblr-link-underline-opacity, 1))!important}.bg-yellow{background-color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-yellow-lt{color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-yellow-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-yellow{border-color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-yellow{--tblr-gradient-from: var(--tblr-yellow)}.bg-gradient-to-yellow{--tblr-gradient-to: var(--tblr-yellow)}.bg-gradient-via-yellow{--tblr-gradient-via: var(--tblr-yellow);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-yellow{color:#f9fafb!important;background-color:RGBA(var(--tblr-yellow-rgb),var(--tblr-bg-opacity, 1))!important}.link-yellow{color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-yellow:hover,.link-yellow:focus{color:RGBA(196,127,0,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(196,127,0,var(--tblr-link-underline-opacity, 1))!important}.bg-lime{background-color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-lime-lt{color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-lime-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-lime{border-color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-lime{--tblr-gradient-from: var(--tblr-lime)}.bg-gradient-to-lime{--tblr-gradient-to: var(--tblr-lime)}.bg-gradient-via-lime{--tblr-gradient-via: var(--tblr-lime);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-lime{color:#f9fafb!important;background-color:RGBA(var(--tblr-lime-rgb),var(--tblr-bg-opacity, 1))!important}.link-lime{color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-lime:hover,.link-lime:focus{color:RGBA(93,147,18,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(93,147,18,var(--tblr-link-underline-opacity, 1))!important}.bg-green{background-color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-green-lt{color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-green-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-green{border-color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-green{--tblr-gradient-from: var(--tblr-green)}.bg-gradient-to-green{--tblr-gradient-to: var(--tblr-green)}.bg-gradient-via-green{--tblr-gradient-via: var(--tblr-green);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-green{color:#f9fafb!important;background-color:RGBA(var(--tblr-green-rgb),var(--tblr-bg-opacity, 1))!important}.link-green{color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-green:hover,.link-green:focus{color:RGBA(38,143,54,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(38,143,54,var(--tblr-link-underline-opacity, 1))!important}.bg-teal{background-color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-teal-lt{color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-teal-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-teal{border-color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-teal{--tblr-gradient-from: var(--tblr-teal)}.bg-gradient-to-teal{--tblr-gradient-to: var(--tblr-teal)}.bg-gradient-via-teal{--tblr-gradient-via: var(--tblr-teal);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-teal{color:#f9fafb!important;background-color:RGBA(var(--tblr-teal-rgb),var(--tblr-bg-opacity, 1))!important}.link-teal{color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-teal:hover,.link-teal:focus{color:RGBA(10,133,96,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(10,133,96,var(--tblr-link-underline-opacity, 1))!important}.bg-cyan{background-color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-cyan-lt{color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-cyan-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-cyan{border-color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-cyan{--tblr-gradient-from: var(--tblr-cyan)}.bg-gradient-to-cyan{--tblr-gradient-to: var(--tblr-cyan)}.bg-gradient-via-cyan{--tblr-gradient-via: var(--tblr-cyan);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-cyan{color:#f9fafb!important;background-color:RGBA(var(--tblr-cyan-rgb),var(--tblr-bg-opacity, 1))!important}.link-cyan{color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-cyan:hover,.link-cyan:focus{color:RGBA(18,130,147,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(18,130,147,var(--tblr-link-underline-opacity, 1))!important}.bg-white{background-color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-white-lt{color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-white-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-white{border-color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-white{--tblr-gradient-from: var(--tblr-white)}.bg-gradient-to-white{--tblr-gradient-to: var(--tblr-white)}.bg-gradient-via-white{--tblr-gradient-via: var(--tblr-white);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-white{color:#1f2937!important;background-color:RGBA(var(--tblr-white-rgb),var(--tblr-bg-opacity, 1))!important}.link-white{color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-white:hover,.link-white:focus{color:RGBA(255,255,255,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(255,255,255,var(--tblr-link-underline-opacity, 1))!important}.text-primary{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-primary-fg{color:var(--tblr-primary-fg)!important}.text-secondary{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-secondary-fg{color:var(--tblr-secondary-fg)!important}.text-success{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-success-fg{color:var(--tblr-success-fg)!important}.text-info{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-info-fg{color:var(--tblr-info-fg)!important}.text-warning{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-warning-fg{color:var(--tblr-warning-fg)!important}.text-danger{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-danger-fg{color:var(--tblr-danger-fg)!important}.text-light{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-light-fg{color:var(--tblr-light-fg)!important}.text-dark{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-dark-fg{color:var(--tblr-dark-fg)!important}.text-muted{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-muted-fg{color:var(--tblr-muted-fg)!important}.text-blue{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-blue-fg{color:var(--tblr-blue-fg)!important}.text-azure{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-azure-fg{color:var(--tblr-azure-fg)!important}.text-indigo{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-indigo-fg{color:var(--tblr-indigo-fg)!important}.text-purple{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-purple-fg{color:var(--tblr-purple-fg)!important}.text-pink{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-pink-fg{color:var(--tblr-pink-fg)!important}.text-red{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-red-fg{color:var(--tblr-red-fg)!important}.text-orange{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-orange-fg{color:var(--tblr-orange-fg)!important}.text-yellow{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-yellow-fg{color:var(--tblr-yellow-fg)!important}.text-lime{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-lime-fg{color:var(--tblr-lime-fg)!important}.text-green{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-green-fg{color:var(--tblr-green-fg)!important}.text-teal{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-teal-fg{color:var(--tblr-teal-fg)!important}.text-cyan{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-cyan-fg{color:var(--tblr-cyan-fg)!important}.bg-gray-50{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-50) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-50-fg{color:var(--tblr-gray-50-fg)!important}.bg-gray-100{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-100) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-100-fg{color:var(--tblr-gray-100-fg)!important}.bg-gray-200{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-200) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-200-fg{color:var(--tblr-gray-200-fg)!important}.bg-gray-300{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-300) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-300-fg{color:var(--tblr-gray-300-fg)!important}.bg-gray-400{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-400) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-400-fg{color:var(--tblr-gray-400-fg)!important}.bg-gray-500{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-500) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-500-fg{color:var(--tblr-gray-500-fg)!important}.bg-gray-600{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-600) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-600-fg{color:var(--tblr-gray-600-fg)!important}.bg-gray-700{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-700) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-700-fg{color:var(--tblr-gray-700-fg)!important}.bg-gray-800{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-800) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-800-fg{color:var(--tblr-gray-800-fg)!important}.bg-gray-900{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-900) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-900-fg{color:var(--tblr-gray-900-fg)!important}.bg-gray-950{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-950) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-950-fg{color:var(--tblr-gray-950-fg)!important}.bg-x{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-x) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-x-fg{color:var(--tblr-x-fg)!important}.bg-facebook{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-facebook) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-facebook-fg{color:var(--tblr-facebook-fg)!important}.bg-twitter{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-twitter) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-twitter-fg{color:var(--tblr-twitter-fg)!important}.bg-linkedin{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-linkedin) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-linkedin-fg{color:var(--tblr-linkedin-fg)!important}.bg-google{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-google) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-google-fg{color:var(--tblr-google-fg)!important}.bg-youtube{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-youtube) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-youtube-fg{color:var(--tblr-youtube-fg)!important}.bg-vimeo{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-vimeo) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-vimeo-fg{color:var(--tblr-vimeo-fg)!important}.bg-dribbble{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-dribbble) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-dribbble-fg{color:var(--tblr-dribbble-fg)!important}.bg-github{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-github) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-github-fg{color:var(--tblr-github-fg)!important}.bg-instagram{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-instagram) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-instagram-fg{color:var(--tblr-instagram-fg)!important}.bg-pinterest{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-pinterest) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-pinterest-fg{color:var(--tblr-pinterest-fg)!important}.bg-vk{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-vk) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-vk-fg{color:var(--tblr-vk-fg)!important}.bg-rss{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-rss) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-rss-fg{color:var(--tblr-rss-fg)!important}.bg-flickr{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-flickr) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-flickr-fg{color:var(--tblr-flickr-fg)!important}.bg-bitbucket{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-bitbucket) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-bitbucket-fg{color:var(--tblr-bitbucket-fg)!important}.bg-tabler{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-tabler) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-tabler-fg{color:var(--tblr-tabler-fg)!important}.bg-inverted{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-bg-surface-inverted) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.bg-surface{background-color:var(--tblr-bg-surface)!important}.bg-surface-secondary{background-color:var(--tblr-bg-surface-secondary)!important}.bg-surface-tertiary{background-color:var(--tblr-bg-surface-tertiary)!important}.bg-surface-backdrop{background-color:color-mix(in srgb,var(--tblr-gray-800) 24%,transparent)!important}.scrollable{overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch}.scrollable.hover{overflow-y:hidden}.scrollable.hover>*{margin-top:-1px}.scrollable.hover:hover,.scrollable.hover:focus,.scrollable.hover:active{overflow:visible;overflow-y:auto}.touch .scrollable{overflow-y:auto!important}.scroll-x,.scroll-y{overflow:hidden;-webkit-overflow-scrolling:touch}.scroll-y{overflow-y:auto}.scroll-x{overflow-x:auto}.no-scroll{overflow:hidden}.w-0{width:0!important}.h-0{height:0!important}.w-1{width:.25rem!important}.h-1{height:.25rem!important}.w-2{width:.5rem!important}.h-2{height:.5rem!important}.w-3{width:1rem!important}.h-3{height:1rem!important}.w-4{width:1.5rem!important}.h-4{height:1.5rem!important}.w-5{width:2rem!important}.h-5{height:2rem!important}.w-6{width:2.5rem!important}.h-6{height:2.5rem!important}.w-auto{width:auto!important}.h-auto{height:auto!important}.w-px{width:1px!important}.h-px{height:1px!important}.w-full{width:100%!important}.h-full{height:100%!important}.opacity-0{opacity:0!important}.opacity-5{opacity:.05!important}.opacity-10{opacity:.1!important}.opacity-15{opacity:.15!important}.opacity-20{opacity:.2!important}.opacity-25{opacity:.25!important}.opacity-30{opacity:.3!important}.opacity-35{opacity:calc(35 / 100)!important}.opacity-40{opacity:.4!important}.opacity-45{opacity:.45!important}.opacity-50{opacity:.5!important}.opacity-55{opacity:.55!important}.opacity-60{opacity:.6!important}.opacity-65{opacity:.65!important}.opacity-70{opacity:calc(70 / 100)!important}.opacity-75{opacity:.75!important}.opacity-80{opacity:.8!important}.opacity-85{opacity:.85!important}.opacity-90{opacity:.9!important}.opacity-95{opacity:calc(95 / 100)!important}.opacity-100{opacity:1!important}.hover-shadow-sm:hover{box-shadow:0 .125rem .25rem #00000013!important}.hover-shadow:hover{box-shadow:rgba(var(--tblr-body-color-rgb),.04) 0 2px 4px!important}.hover-shadow-lg:hover{box-shadow:0 1rem 3rem #0000002d!important}.hover-shadow-none:hover{box-shadow:none!important}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.hover-rotate-start,.hover-rotate-end,.hover-scale,.hover-elevate-down,.hover-elevate-up{transition:transform .3s ease}.hover-rotate-start:hover,.hover-rotate-end:hover,.hover-scale:hover,.hover-elevate-down:hover,.hover-elevate-up:hover{will-change:transform}.hover-elevate-up:hover{transform:translateY(-4px)}.hover-elevate-down:hover{transform:translateY(4px)}.hover-scale:hover{transform:scale(1.1)}.hover-rotate-end:hover{transform:rotate(4deg)}.hover-rotate-start:hover{transform:rotate(-4deg)}.ts-control{border:1px solid var(--tblr-border-color);padding:.5625rem 1rem;width:100%;overflow:hidden;position:relative;z-index:1;box-sizing:border-box;box-shadow:none;border-radius:var(--tblr-border-radius);display:flex;flex-wrap:wrap}.ts-wrapper.multi.has-items .ts-control{padding:calc(.5625rem - 1px) 1rem calc(.5625rem - 4px)}.full .ts-control{background-color:var(--tblr-bg-forms)}.disabled .ts-control,.disabled .ts-control *{cursor:default!important}.focus .ts-control{box-shadow:none}.ts-control>*{vertical-align:baseline;display:inline-block}.ts-wrapper.multi .ts-control>div{cursor:pointer;margin:0 3px 3px 0;padding:1px 5px;background:#efefef;color:#1f2937;border:0px solid #e5e7eb;overflow:auto}.ts-wrapper.multi .ts-control>div.active{background:#00857d;color:#fff;border:0px solid rgba(0,0,0,0)}.ts-wrapper.multi.disabled .ts-control>div,.ts-wrapper.multi.disabled .ts-control>div.active{color:#787878;background:#fff;border:0px solid white}.ts-control>input{flex:1 1 auto;min-width:7rem;display:inline-block!important;padding:0!important;min-height:0!important;max-height:none!important;max-width:100%!important;margin:0!important;text-indent:0!important;border:0 none!important;background:none!important;line-height:inherit!important;user-select:auto!important;box-shadow:none!important}.ts-control>input::-ms-clear{display:none}.ts-control>input:focus{outline:none!important}.has-items .ts-control>input{margin:0 4px!important}.ts-control.rtl{text-align:right}.ts-control.rtl.single .ts-control:after{left:calc(1rem + 5px);right:auto}.ts-control.rtl .ts-control>input{margin:0 4px 0 -2px!important}.disabled .ts-control{opacity:1;background-color:var(--tblr-bg-surface-secondary)}.input-hidden .ts-control>input{opacity:0;position:absolute;left:-10000px}.ts-dropdown{position:absolute;top:100%;left:0;width:100%;z-index:10;border:1px solid #d0d0d0;background:var(--tblr-bg-surface);margin:.25rem 0 0;border-top:0 none;box-sizing:border-box;box-shadow:0 1px 3px #0000001a;border-radius:0 0 var(--tblr-border-radius) var(--tblr-border-radius)}.ts-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.ts-dropdown [data-selectable] .highlight{background:#ffed2866;border-radius:1px}.ts-dropdown .option,.ts-dropdown .optgroup-header,.ts-dropdown .no-results,.ts-dropdown .create{padding:3px 1rem}.ts-dropdown .option,.ts-dropdown [data-disabled],.ts-dropdown [data-disabled] [data-selectable].option{cursor:inherit;opacity:.5}.ts-dropdown [data-selectable].option{opacity:1;cursor:pointer}.ts-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.ts-dropdown .optgroup-header{color:#4b5563;background:var(--tblr-bg-surface);cursor:default}.ts-dropdown .active{background-color:rgba(var(--tblr-secondary-rgb),.08);color:inherit}.ts-dropdown .active.create{color:inherit}.ts-dropdown .create{color:#1f293780}.ts-dropdown .spinner{display:inline-block;width:30px;height:30px;margin:3px 1rem}.ts-dropdown .spinner:after{content:" ";display:block;width:24px;height:24px;margin:3px;border-radius:50%;border:5px solid #d0d0d0;border-color:#d0d0d0 transparent #d0d0d0 transparent;animation:lds-dual-ring 1.2s linear infinite}@keyframes lds-dual-ring{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ts-dropdown-content{overflow:hidden auto;max-height:200px;scroll-behavior:smooth}.ts-wrapper.plugin-drag_drop .ts-dragging{color:transparent!important}.ts-wrapper.plugin-drag_drop .ts-dragging>*{visibility:hidden!important}.plugin-checkbox_options:not(.rtl) .option input{margin-right:.5rem}.plugin-checkbox_options.rtl .option input{margin-left:.5rem}.plugin-clear_button{--ts-pr-clear-button: 1em}.plugin-clear_button .clear-button{opacity:0;position:absolute;top:50%;transform:translateY(-50%);right:calc(1rem - 5px);margin-right:0!important;background:transparent!important;transition:opacity .5s;cursor:pointer}.plugin-clear_button.form-select .clear-button,.plugin-clear_button.single .clear-button{right:max(var(--ts-pr-caret),1rem)}.plugin-clear_button.focus.has-items .clear-button,.plugin-clear_button:not(.disabled):hover.has-items .clear-button{opacity:1}.ts-wrapper .dropdown-header{position:relative;padding:6px 1rem;border-bottom:1px solid #d0d0d0;background:color-mix(var(--tblr-bg-surface),#d0d0d0,85%);border-radius:var(--tblr-border-radius) var(--tblr-border-radius) 0 0}.ts-wrapper .dropdown-header-close{position:absolute;right:1rem;top:50%;color:#1f2937;opacity:.4;margin-top:-12px;line-height:20px;font-size:20px!important}.ts-wrapper .dropdown-header-close:hover{color:#000}.plugin-dropdown_input.focus.dropdown-active .ts-control{box-shadow:none;border:1px solid var(--tblr-border-color);box-shadow:var(--tblr-shadow-input)}.plugin-dropdown_input .dropdown-input{border:1px solid #d0d0d0;border-width:0 0 1px;display:block;padding:.5625rem 1rem;box-shadow:none;width:100%;background:transparent}.plugin-dropdown_input.focus .ts-dropdown .dropdown-input{border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.plugin-dropdown_input .items-placeholder{border:0 none!important;box-shadow:none!important;width:100%}.plugin-dropdown_input.has-items .items-placeholder,.plugin-dropdown_input.dropdown-active .items-placeholder{display:none!important}.ts-wrapper.plugin-input_autogrow.has-items .ts-control>input{min-width:0}.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control>input{flex:none;min-width:4px}.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control>input::placeholder{color:transparent}.ts-dropdown.plugin-optgroup_columns .ts-dropdown-content{display:flex}.ts-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;flex-grow:1;flex-basis:0;min-width:0}.ts-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.ts-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.ts-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.ts-wrapper.plugin-remove_button .item{display:inline-flex;align-items:center}.ts-wrapper.plugin-remove_button .item .remove{color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:0 5px;border-radius:0 2px 2px 0;box-sizing:border-box}.ts-wrapper.plugin-remove_button .item .remove:hover{background:#0000000d}.ts-wrapper.plugin-remove_button.disabled .item .remove:hover{background:none}.ts-wrapper.plugin-remove_button .remove-single{position:absolute;right:0;top:0;font-size:23px}.ts-wrapper.plugin-remove_button:not(.rtl) .item{padding-right:0!important}.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove{border-left:1px solid #e5e7eb;margin-left:5px}.ts-wrapper.plugin-remove_button:not(.rtl) .item.active .remove{border-left-color:#0000}.ts-wrapper.plugin-remove_button:not(.rtl).disabled .item .remove{border-left-color:#fff}.ts-wrapper.plugin-remove_button.rtl .item{padding-left:0!important}.ts-wrapper.plugin-remove_button.rtl .item .remove{border-right:1px solid #e5e7eb;margin-right:5px}.ts-wrapper.plugin-remove_button.rtl .item.active .remove{border-right-color:#0000}.ts-wrapper.plugin-remove_button.rtl.disabled .item .remove{border-right-color:#fff}:root{--ts-pr-clear-button: 0px;--ts-pr-caret: 0px;--ts-pr-min: .75rem}.ts-wrapper.single .ts-control,.ts-wrapper.single .ts-control input{cursor:pointer}.ts-control:not(.rtl){padding-right:max(var(--ts-pr-min),var(--ts-pr-clear-button) + var(--ts-pr-caret))!important}.ts-control.rtl{padding-left:max(var(--ts-pr-min),var(--ts-pr-clear-button) + var(--ts-pr-caret))!important}.ts-wrapper{position:relative}.ts-dropdown,.ts-control,.ts-control input{color:#1f2937;font-family:inherit;font-size:inherit;line-height:1.25rem}.ts-control,.ts-wrapper.single.input-active .ts-control{background:var(--tblr-bg-forms);cursor:text}.ts-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;white-space:nowrap!important}.ts-dropdown,.ts-dropdown.form-control,.ts-dropdown.form-select{height:auto;padding:0;z-index:1000;background:var(--tblr-bg-surface);border:1px solid var(--tblr-border-color-translucent);border-radius:6px;box-shadow:0 6px 12px #0000002d}.ts-dropdown .optgroup-header{font-size:.765625rem;line-height:1.4285714286}.ts-dropdown .optgroup:first-child:before{display:none}.ts-dropdown .optgroup:before{content:" ";display:block;height:0;margin:var(--tblr-spacer-2) 0;overflow:hidden;border-top:1px solid var(--tblr-border-color-translucent);margin-left:-1rem;margin-right:-1rem}.ts-dropdown .create{padding-left:1rem}.ts-dropdown-content{padding:5px 0}.ts-control{box-shadow:var(--tblr-shadow-input);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.ts-control{transition:none}}.ts-control{display:flex;align-items:center}.focus .ts-control{border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.ts-control .item{display:flex;align-items:center}.ts-control input::placeholder{color:var(--bs-secondary-color, #a7aeb8);opacity:1}.ts-wrapper.is-invalid,select.tomselected.is-invalid+div.ts-wrapper,.was-validated .invalid,.was-validated :invalid+.ts-wrapper{border-color:var(--tblr-form-invalid-color)}.ts-wrapper.is-invalid:not(.single),select.tomselected.is-invalid+div.ts-wrapper:not(.single),.was-validated .invalid:not(.single),.was-validated :invalid+.ts-wrapper:not(.single){background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-invalid.single,select.tomselected.is-invalid+div.ts-wrapper.single,.was-validated .invalid.single,.was-validated :invalid+.ts-wrapper.single{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-invalid.focus .ts-control,select.tomselected.is-invalid+div.ts-wrapper.focus .ts-control,.was-validated .invalid.focus .ts-control,.was-validated :invalid+.ts-wrapper.focus .ts-control{border-color:var(--tblr-form-invalid-color);box-shadow:0 0 0 .25rem rgba(var(--tblr-form-invalid-color),.25)}.ts-wrapper.is-valid,.was-validated .valid,.was-validated :valid+.ts-wrapper{border-color:var(--tblr-form-valid-color)}.ts-wrapper.is-valid:not(.single),.was-validated .valid:not(.single),.was-validated :valid+.ts-wrapper:not(.single){background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-valid.single,.was-validated .valid.single,.was-validated :valid+.ts-wrapper.single{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-valid.focus .ts-control,.was-validated .valid.focus .ts-control,.was-validated :valid+.ts-wrapper.focus .ts-control{border-color:var(--tblr-form-valid-color);box-shadow:0 0 0 .25rem rgba(var(--tblr-form-valid-color),.25)}.ts-wrapper{min-height:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2));display:flex}.input-group-sm>.ts-wrapper,.ts-wrapper.form-select-sm,.ts-wrapper.form-control-sm{min-height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2))}.input-group-sm>.ts-wrapper .ts-control,.ts-wrapper.form-select-sm .ts-control,.ts-wrapper.form-control-sm .ts-control{border-radius:var(--tblr-border-radius-sm);font-size:.75rem}.input-group-sm>.ts-wrapper.has-items .ts-control,.ts-wrapper.form-select-sm.has-items .ts-control,.ts-wrapper.form-control-sm.has-items .ts-control{font-size:.75rem}.input-group-sm>.ts-wrapper.multi.has-items .ts-control,.ts-wrapper.form-select-sm.multi.has-items .ts-control,.ts-wrapper.form-control-sm.multi.has-items .ts-control{padding-top:calc((calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2)) - 1.25rem * .75rem - calc((var(--tblr-border-width) + 1px) * 2)) / 2)!important}.ts-wrapper.multi.has-items .ts-control{padding-left:calc(1rem - 5px);--ts-pr-min: calc(1rem - 5px) }.ts-wrapper.multi .ts-control>div{border-radius:calc(var(--tblr-border-radius) - 1px)}.input-group-lg>.ts-wrapper,.ts-wrapper.form-control-lg,.ts-wrapper.form-select-lg{min-height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2))}.input-group-lg>.ts-wrapper .ts-control,.ts-wrapper.form-control-lg .ts-control,.ts-wrapper.form-select-lg .ts-control{border-radius:var(--tblr-border-radius-lg);font-size:1rem}.ts-wrapper:not(.form-control,.form-select){padding:0;border:none;height:auto;box-shadow:none;background:none}.ts-wrapper:not(.form-control,.form-select).single .ts-control{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right 1rem center;background-size:16px 12px}.ts-wrapper.form-select,.ts-wrapper.single{--ts-pr-caret: 3rem}.ts-wrapper.form-control,.ts-wrapper.form-select{padding:0!important;height:auto;box-shadow:none;display:flex}.ts-wrapper.form-control .ts-control,.ts-wrapper.form-control.single.input-active .ts-control,.ts-wrapper.form-select .ts-control,.ts-wrapper.form-select.single.input-active .ts-control{border:none!important}.ts-wrapper.form-control:not(.disabled) .ts-control,.ts-wrapper.form-control:not(.disabled).single.input-active .ts-control,.ts-wrapper.form-select:not(.disabled) .ts-control,.ts-wrapper.form-select:not(.disabled).single.input-active .ts-control{background:transparent!important}.input-group>.ts-wrapper{flex-grow:1;width:1%}.input-group>.ts-wrapper:not(:nth-child(2))>.ts-control{border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.ts-wrapper:not(:last-child)>.ts-control{border-top-right-radius:0;border-bottom-right-radius:0}.form-select .ts-dropdown,.form-select .ts-control,.form-select .ts-control input{color:var(--tblr-body-color)}:root{--ts-pr-clear-button: 0rem;--ts-pr-caret: 0rem}.ts-input{color:inherit}.focus .ts-control{border-radius:var(--tblr-border-radius)}.ts-control{color:inherit}.ts-control .dropdown-menu{width:100%;height:auto}.ts-wrapper .form-control,.ts-wrapper .form-select,.ts-wrapper.form-control,.ts-wrapper.form-select{box-shadow:var(--tblr-shadow-input)}.ts-wrapper.is-invalid .ts-control,select.tomselected.is-invalid+div.ts-wrapper .ts-control,.ts-wrapper.is-valid .ts-control{--ts-pr-clear-button: 1.5rem}.ts-dropdown{background:var(--tblr-bg-surface);color:var(--tblr-body-color);box-shadow:var(--tblr-shadow-dropdown);z-index:1000}.ts-dropdown .option{padding:.5rem .75rem}.ts-control,.ts-control input{color:var(--tblr-body-color)}.ts-control input::placeholder{color:var(--tblr-tertiary)}.ts-wrapper.multi .ts-control>div,.ts-wrapper.multi.disabled .ts-control>div{background:var(--tblr-bg-surface-secondary);border:1px solid var(--tblr-border-color);color:var(--tblr-body-color)}.ts-wrapper.disabled .ts-control{opacity:1}.ts-wrapper.disabled .ts-control>div.item{color:var(--tblr-gray-500)}html{scroll-behavior:auto!important}mark,.mark{padding-left:0;padding-right:0}.table-responsive .dropdown,.table-responsive .btn-group,.table-responsive .btn-group-vertical{position:static}.progress{min-width:80px}hr.dropdown-divider,.dropdown-divider.hr{margin-bottom:.25rem;margin-top:.25rem}.dropdown-item{font-weight:400}*{font-feature-settings:"liga" 0;font-variant-ligatures:none}@media(min-width:992px){:root,:host{margin-left:0;scrollbar-gutter:stable}}pre{background-color:transparent;color:inherit}.alert{background:var(--tblr-bg-surface)}.badge{user-select:text}.btn{display:inline-block}.btn:focus{border:1px solid var(--tblr-primary-fg);outline:2px solid var(--tblr-primary)!important}.btn-sm,.btn-group-sm>.btn{border-radius:6px}.dropdown-item{display:inline-block}.footer .text-primary{color:#001423!important}.nav-tabs .nav-link{display:inline-block}.page,.page-tabs .nav-tabs .nav-link.active{background-color:var(--tblr-bg-surface-tertiary)!important}.navbar{--tblr-navbar-active-bg: rgba(0, 0, 0, .06)}[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{--tblr-alert-color: darken(var(--tblr-warning),10%);--tblr-link-color: #00F2D4;--tblr-link-color-rgb: 0,242,212;--tblr-link-hover-color-rgb: 0,242,212;--tblr-secondary: #9ca3af;--tblr-primary: #00F2D4;--tblr-primary-fg: #001423;--tblr-primary-rgb: 0,242,212;--tblr-btn-active-color: #001423}html[data-bs-theme=dark] ::selection,body[data-bs-theme=dark] html[data-bs-theme=light] ::selection{background-color:rgba(var(--tblr-primary-rgb),.48)}html[data-bs-theme=dark] .btn-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .btn-primary,html[data-bs-theme=dark] .bg-primary .card-title,body[data-bs-theme=dark] html[data-bs-theme=light] .bg-primary .card-title,html[data-bs-theme=dark] .bg-primary a,body[data-bs-theme=dark] html[data-bs-theme=light] .bg-primary a,html[data-bs-theme=dark] .bg-primary i,body[data-bs-theme=dark] html[data-bs-theme=light] .bg-primary i,html[data-bs-theme=dark] .text-bg-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .text-bg-primary{color:#001423!important}html[data-bs-theme=dark] .card,body[data-bs-theme=dark] html[data-bs-theme=light] .card{background:#001423!important}html[data-bs-theme=dark],body[data-bs-theme=dark] html[data-bs-theme=light],html[data-bs-theme=dark] .navbar,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar,html[data-bs-theme=dark] .page-header,body[data-bs-theme=dark] html[data-bs-theme=light] .page-header{background-color:#001423}html[data-bs-theme=dark] .page,body[data-bs-theme=dark] html[data-bs-theme=light] .page,html[data-bs-theme=dark] .page-tabs .nav-tabs .nav-link.active,body[data-bs-theme=dark] html[data-bs-theme=light] .page-tabs .nav-tabs .nav-link.active{background-color:#081b2a!important}html[data-bs-theme=dark] .page-link.active,body[data-bs-theme=dark] html[data-bs-theme=light] .page-link.active,html[data-bs-theme=dark] .active>.page-link,body[data-bs-theme=dark] html[data-bs-theme=light] .active>.page-link{color:#001423}html[data-bs-theme=dark] .text-bg-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .text-bg-primary{color:#001423!important}html[data-bs-theme=dark] .text-muted,body[data-bs-theme=dark] html[data-bs-theme=light] .text-muted{color:var(--tblr-secondary-color)!important}html[data-bs-theme=dark] .text-secondary,body[data-bs-theme=dark] html[data-bs-theme=light] .text-secondary{color:#9ca3af!important}html[data-bs-theme=dark] .footer .text-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .footer .text-primary{color:#fff!important}html[data-bs-theme=dark] .toast,body[data-bs-theme=dark] html[data-bs-theme=light] .toast{color:var(--tblr-body-color)}html[data-bs-theme=dark] .table-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .table-primary{--tblr-table-bg: rgba(var(--tblr-secondary-rgb), .48);--tblr-table-hover-bg: inherit;--tblr-table-hover-color: inherit}pre code{padding:unset}.dropdown-toggle:after{font-family:Material Design Icons;content:"\f0140";padding-right:9px;border-bottom:none;border-left:none;transform:none;vertical-align:.05em;height:auto}.accordion-button-toggle{align-items:center;justify-content:center;flex:0 0 auto}.accordion-button-toggle>i{display:block;line-height:1}:root:not(.dummy)[data-bs-theme=light] .hide-theme-light,:root:not(.dummy)[data-bs-theme=dark] .hide-theme-dark,body[data-bs-theme=dark] [data-bs-theme=light]:root:not(.dummy) .hide-theme-dark{display:none!important}:root:not(.dummy)[data-bs-theme=dark] .hide-theme-light,body[data-bs-theme=dark] [data-bs-theme=light]:root:not(.dummy) .hide-theme-light,:root:not(.dummy)[data-bs-theme=light] .hide-theme-dark{display:inline-flex!important}.ts-wrapper.multi .ts-control{padding:7px 7px 3px}.ts-wrapper.multi .ts-control div{margin:0 4px 4px 0}.badge a{color:inherit;text-decoration:none}.page-body .card{margin-bottom:1rem}.page-body .card .card-header,.page-body .card .card-body,.page-body .card .card-footer{padding:.75rem}.page-body .card .card-header{background:var(--tblr-bg-surface-tertiary)}.page-body .card h2.card-header,.page-body .card .card-header.h2{font-size:var(--tblr-font-size-h5);line-height:var(--tblr-line-height-h5);margin-bottom:0}.page-body .card .list-group-item{padding:.5rem .75rem}.page-body .card .table,.page-body .card .markdown>table{margin-bottom:0}form.object-edit{margin:auto;max-width:800px}.col-form-label.required{font-weight:700}.col-form-label.required:after{position:absolute;display:inline-block;margin-left:0;font-family:Material Design Icons;font-size:8px;content:"\f06c4"}.has-errors input,.has-errors select,.has-errors textarea{border:1px solid #d63939}select[multiple] optgroup{top:0;background-color:var(--bs-body-bg);font-style:normal;font-weight:700}select[multiple] option{padding-left:.5rem}.modifier-select{min-width:10rem;max-width:15rem;width:auto;white-space:nowrap}.page{background-color:var(--tblr-bg-surface-secondary)}.page-header{background-color:var(--tblr-bg-surface);min-height:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .nav-link-icon,.navbar-vertical.navbar-expand-lg .navbar-collapse .nav-link-title{color:#001423}.navbar-vertical.navbar-expand-lg .navbar-collapse .text-secondary{color:#00857d!important}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item a{color:#001423}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item .btn-group{visibility:hidden}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:hover,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active{background-color:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:hover a,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active a{text-decoration:none}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:hover .btn-group,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active .btn-group{visibility:visible}.navbar-vertical.navbar-expand-lg .navbar-nav{z-index:1}@media(max-width:991.98px){.navbar-vertical.navbar-expand-lg .navbar-brand{padding:.2rem 0}}.navbar-vertical.navbar-expand-lg .navbar-brand a:hover{text-decoration:none}.navbar-vertical.navbar-expand-lg img.motif{bottom:0;display:none;left:0;mask-image:linear-gradient(180deg,#0000,#0000004d);opacity:.5;position:fixed;user-drag:none;user-select:none;-moz-user-select:none;-webkit-user-drag:none;-webkit-user-select:none;-ms-user-select:none;width:18rem}@media(min-width:992px){.navbar-vertical.navbar-expand-lg img.motif{display:block}}html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg{background:linear-gradient(180deg,#00857d00,#00857d1a),#fff}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg{background:linear-gradient(180deg,#00f2d400,#00f2d41a),#001423}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .nav-item.dropdown.active:after,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .nav-item.dropdown.active:after{border-color:#00f2d4!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .nav-link-title,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .nav-link-title,html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .nav-link-icon,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .nav-link-icon,html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .dropdown-item a,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .dropdown-item a{color:#fff!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .dropdown-item.active,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .dropdown-item.active,html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .dropdown-item:hover,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .dropdown-item:hover{background-color:#ffffff0f!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .text-secondary,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .text-secondary{color:#00f2d4!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg img.motif,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg img.motif{opacity:.25}.progress{height:20px}.progress .progress-label{display:flex;flex-direction:column;justify-content:center;padding-left:.25rem}.table thead th,.markdown>table thead th{font-size:.625rem}table.object-list tbody>tr:last-child>td{border-bottom-width:0}table.object-list th.asc>a:after{content:"\f0140";font-family:Material Design Icons}table.object-list th.desc>a:after{content:"\f0143";font-family:Material Design Icons}table.attr-table th{font-weight:400;width:min-content}table.attr-table th,table.attr-table td{border-bottom-style:dashed}table.attr-table tr:last-child{border-bottom-style:hidden}table.attr-table td{overflow-wrap:anywhere}td pre{margin-bottom:0}table th.orderable a{color:var(--tblr-body-color)}html[data-bs-theme=dark] .table thead th,body[data-bs-theme=dark] html[data-bs-theme=light] .table thead th,body[data-bs-theme=dark] html[data-bs-theme=light] .markdown>table thead th,html[data-bs-theme=dark] .markdown>table thead th{background:#001423!important}.page-tabs{border-bottom:1px solid var(--tblr-border-color-translucent)}.page-tabs .nav-tabs{position:relative;border:none}.page-tabs .nav-tabs .nav-link.active,.page-tabs .nav-tabs .nav-link:active,.page-tabs .nav-tabs .nav-link:hover{border-color:var(--tblr-border-color-translucent);border-bottom-color:transparent}.page-tabs .nav-tabs .nav-link.active{color:inherit;background:var(--tblr-bg-surface-secondary);border-bottom-color:transparent}pre.change-data{border-radius:0;padding:0;margin-inline:-.75rem}pre.change-data>span{display:block;padding-inline:.5rem;max-width:100%;min-width:fit-content;border-left:.25rem solid transparent}pre.change-data>span.added{background-color:var(--tblr-green-200);border-left-color:var(--tblr-green-darken)}pre.change-data>span.removed{background-color:var(--tblr-red-200);border-left-color:var(--tblr-red-darken)}pre.change-diff{border:var(--tblr-border-width) solid transparent}pre.change-diff.change-added{background-color:var(--tblr-green-lt);border-color:var(--tblr-green)}pre.change-diff.change-removed{background-color:var(--tblr-red-lt);border-color:var(--tblr-red)}pre.block{padding:1rem;border:var(--tblr-border-width) solid #e5e7eb;border-radius:6px}.grid-stack .card-header.bg-default{background:var(--tblr-bg-surface-secondary)!important}.grid-stack .card-header a{color:inherit!important}tr[data-cable-status=connected]{background-color:#2fb34426}tr[data-cable-status=planned]{background-color:#066fd126}tr[data-cable-status=decommissioning]{background-color:#f59f0026}tr[data-mark-connected=true]{background-color:#2fb34426}tr[data-virtual=true]{background-color:#00857d26}tr[data-enabled=disabled]{background-color:#9ca3af26}tr[data-cable-status=connected] button.mark-installed{display:none}tr:not([data-cable-status=connected]) button.mark-planned{display:none}.rendered-markdown table{width:100%}.rendered-markdown table th{border-bottom:2px solid #dddddd;padding:8px}.rendered-markdown table td{border-top:1px solid #dddddd;padding:8px}.rendered-markdown table th[align=left]{text-align:left}.rendered-markdown table th[align=center]{text-align:center}.rendered-markdown table th[align=right]{text-align:right}.rendered-markdown p:last-child{margin-bottom:0}td>.rendered-markdown{max-height:200px;overflow-y:scroll}.markdown-widget .preview{border:1px solid #e5e7eb;border-radius:6px;min-height:200px}span.color-label{display:inline-block;width:5rem;height:1rem;padding:.25em .5em;border:1px solid #303030;border-radius:6px}.record-depth{display:inline;user-select:none;opacity:33%}.record-depth span:only-of-type,.record-depth span:last-of-type{margin-right:.25rem}.hide-last-child :last-child{visibility:hidden;opacity:0}.netbox-edition{letter-spacing:.15rem}.logo{height:80px}.sso-icon{height:24px}img.plugin-icon{max-width:1.4285em;height:auto}.thumbnail{max-width:200px}.thumbnail img{border:1px solid #606060}.image-preview-popover{--bs-popover-max-width: clamp(240px, 25vw, 640px)}.image-preview-popover .popover-header{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.image-preview-popover .popover-body{display:flex;justify-content:center;align-items:center}.image-preview-popover img{display:block;max-width:100%;max-height:clamp(160px,33vh,640px);height:auto}html[data-bs-theme=dark] img.plugin-icon,body[data-bs-theme=dark] html[data-bs-theme=light] img.plugin-icon{filter:grayscale(100%) invert(100%) brightness(80%)}.sticky-actions{z-index:4}.sticky-actions[data-sticky-when=always],.sticky-actions.is-sticky-active{position:sticky;bottom:.25rem}.sticky-actions[data-sticky-position=left],.sticky-actions[data-sticky-position=right]{display:flex;align-items:center;gap:.5rem;padding:.5rem;max-width:100%;width:fit-content}.sticky-actions[data-sticky-position=right]{margin-left:auto}.sticky-actions[data-sticky-position=full]{max-width:100%}.sticky-actions-footer{max-width:100%;margin-top:1.5rem;padding:1rem;padding-bottom:calc(1rem + env(safe-area-inset-bottom,0));background:var(--tblr-bg-surface-secondary);border-top:1px solid var(--tblr-border-color)}.sticky-actions-footer[data-sticky-when=always],.sticky-actions-footer.is-sticky-active{bottom:0}.sticky-actions-footer>.btn-list{justify-content:flex-end;margin-bottom:0}.object-edit--with-sticky-actions{padding-bottom:calc(1.5rem + env(safe-area-inset-bottom,0))}[data-sticky-when=selection] .bulk-action-buttons .btn:disabled,[data-sticky-when=selection] .bulk-action-buttons .btn.disabled{border-color:transparent;box-shadow:none}[data-sticky-when=selection] .bulk-action-buttons .btn.disabled{pointer-events:none}.btn-float-group-right{position:sticky;bottom:10px;z-index:4;margin-left:auto;width:fit-content}.btn-float-group-left{position:sticky;bottom:10px;z-index:4;width:fit-content}tr[data-read=True] td{background-color:var(--tblr-bg-surface-secondary);color:#6b7280}.rack-loading-container{min-height:200px;margin-left:30px} +@charset "UTF-8";:root,[data-bs-theme=light]{--tblr-black: #000000;--tblr-white: #ffffff;--tblr-gray: #4b5563;--tblr-gray-dark: #1f2937;--tblr-gray-100: #f3f4f6;--tblr-gray-200: #e5e7eb;--tblr-gray-300: #d1d5db;--tblr-gray-400: #9ca3af;--tblr-gray-500: #6b7280;--tblr-gray-600: #4b5563;--tblr-gray-700: #374151;--tblr-gray-800: #1f2937;--tblr-gray-900: #111827;--tblr-primary: #00857D;--tblr-secondary: #6b7280;--tblr-success: #2fb344;--tblr-info: #4299e1;--tblr-warning: #f59f00;--tblr-danger: #d63939;--tblr-light: #f9fafb;--tblr-dark: #1f2937;--tblr-muted: #6b7280;--tblr-blue: #066fd1;--tblr-azure: #4299e1;--tblr-indigo: #4263eb;--tblr-purple: #ae3ec9;--tblr-pink: #d6336c;--tblr-red: #d63939;--tblr-orange: #f76707;--tblr-yellow: #f59f00;--tblr-lime: #74b816;--tblr-green: #2fb344;--tblr-teal: #0ca678;--tblr-cyan: #17a2b8;--tblr-primary-rgb: 0, 133, 125;--tblr-secondary-rgb: 107, 114, 128;--tblr-success-rgb: 47, 179, 68;--tblr-info-rgb: 66, 153, 225;--tblr-warning-rgb: 245, 159, 0;--tblr-danger-rgb: 214, 57, 57;--tblr-light-rgb: 249, 250, 251;--tblr-dark-rgb: 31, 41, 55;--tblr-muted-rgb: 107, 114, 128;--tblr-blue-rgb: 6, 111, 209;--tblr-azure-rgb: 66, 153, 225;--tblr-indigo-rgb: 66, 99, 235;--tblr-purple-rgb: 174, 62, 201;--tblr-pink-rgb: 214, 51, 108;--tblr-red-rgb: 214, 57, 57;--tblr-orange-rgb: 247, 103, 7;--tblr-yellow-rgb: 245, 159, 0;--tblr-lime-rgb: 116, 184, 22;--tblr-green-rgb: 47, 179, 68;--tblr-teal-rgb: 12, 166, 120;--tblr-cyan-rgb: 23, 162, 184;--tblr-primary-text-emphasis: rgb(0, 53.2, 50);--tblr-secondary-text-emphasis: rgb(42.8, 45.6, 51.2);--tblr-success-text-emphasis: rgb(18.8, 71.6, 27.2);--tblr-info-text-emphasis: rgb(26.4, 61.2, 90);--tblr-warning-text-emphasis: rgb(98, 63.6, 0);--tblr-danger-text-emphasis: rgb(85.6, 22.8, 22.8);--tblr-light-text-emphasis: #374151;--tblr-dark-text-emphasis: #374151;--tblr-primary-bg-subtle: rgb(204, 230.6, 229);--tblr-secondary-bg-subtle: rgb(225.4, 226.8, 229.6);--tblr-success-bg-subtle: rgb(213.4, 239.8, 217.6);--tblr-info-bg-subtle: rgb(217.2, 234.6, 249);--tblr-warning-bg-subtle: rgb(253, 235.8, 204);--tblr-danger-bg-subtle: rgb(246.8, 215.4, 215.4);--tblr-light-bg-subtle: rgb(249, 249.5, 250.5);--tblr-dark-bg-subtle: #9ca3af;--tblr-primary-border-subtle: rgb(153, 206.2, 203);--tblr-secondary-border-subtle: rgb(195.8, 198.6, 204.2);--tblr-success-border-subtle: rgb(171.8, 224.6, 180.2);--tblr-info-border-subtle: rgb(179.4, 214.2, 243);--tblr-warning-border-subtle: rgb(251, 216.6, 153);--tblr-danger-border-subtle: rgb(238.6, 175.8, 175.8);--tblr-light-border-subtle: #e5e7eb;--tblr-dark-border-subtle: #6b7280;--tblr-white-rgb: 255, 255, 255;--tblr-black-rgb: 0, 0, 0;--tblr-font-sans-serif: "Inter", system-ui, sans-serif;--tblr-font-monospace: "Roboto Mono";--tblr-gradient: linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--tblr-body-font-family: var(--tblr-font-sans-serif);--tblr-body-font-size: .875rem;--tblr-body-font-weight: 400;--tblr-body-line-height: 1.4285714286;--tblr-body-color: #1f2937;--tblr-body-color-rgb: 31, 41, 55;--tblr-body-bg: #f9fafb;--tblr-body-bg-rgb: 249, 250, 251;--tblr-emphasis-color: #374151;--tblr-emphasis-color-rgb: 55, 65, 81;--tblr-secondary-color: rgba(31, 41, 55, .75);--tblr-secondary-color-rgb: 31, 41, 55;--tblr-secondary-bg: #e5e7eb;--tblr-secondary-bg-rgb: 229, 231, 235;--tblr-tertiary-color: rgba(31, 41, 55, .5);--tblr-tertiary-color-rgb: 31, 41, 55;--tblr-tertiary-bg: #f3f4f6;--tblr-tertiary-bg-rgb: 243, 244, 246;--tblr-heading-color: inherit;--tblr-link-color: #00857D;--tblr-link-color-rgb: 0, 133, 125;--tblr-link-decoration: none;--tblr-link-hover-color: rgb(0, 106.4, 100);--tblr-link-hover-color-rgb: 0, 106, 100;--tblr-link-hover-decoration: underline;--tblr-code-color: light-dark(var(--tblr-gray-600), var(--tblr-gray-400));--tblr-highlight-color: #1f2937;--tblr-highlight-bg: rgb(253, 235.8, 204);--tblr-border-width: 1px;--tblr-border-style: solid;--tblr-border-color: #e5e7eb;--tblr-border-color-translucent: rgba(4, 32, 69, .1);--tblr-border-radius: 6px;--tblr-border-radius-sm: 4px;--tblr-border-radius-lg: 8px;--tblr-border-radius-xl: 1rem;--tblr-border-radius-xxl: 2rem;--tblr-border-radius-2xl: var(--tblr-border-radius-xxl);--tblr-border-radius-pill: 100rem;--tblr-box-shadow: rgba(var(--tblr-body-color-rgb), .04) 0 2px 4px 0;--tblr-box-shadow-sm: 0 .125rem .25rem rgba(0, 0, 0, .075);--tblr-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, .175);--tblr-box-shadow-inset: 0 0 transparent;--tblr-focus-ring-width: .25rem;--tblr-focus-ring-opacity: .25;--tblr-focus-ring-color: rgba(var(--tblr-primary-rgb), .25);--tblr-form-valid-color: #2fb344;--tblr-form-valid-border-color: #2fb344;--tblr-form-invalid-color: #d63939;--tblr-form-invalid-border-color: #d63939}[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{color-scheme:dark;--tblr-body-color: #e5e7eb;--tblr-body-color-rgb: 229, 231, 235;--tblr-body-bg: #111827;--tblr-body-bg-rgb: 17, 24, 39;--tblr-emphasis-color: #ffffff;--tblr-emphasis-color-rgb: 255, 255, 255;--tblr-secondary-color: rgba(229, 231, 235, .75);--tblr-secondary-color-rgb: 229, 231, 235;--tblr-secondary-bg: #1f2937;--tblr-secondary-bg-rgb: 31, 41, 55;--tblr-tertiary-color: rgba(229, 231, 235, .5);--tblr-tertiary-color-rgb: 229, 231, 235;--tblr-tertiary-bg: rgb(24, 32.5, 47);--tblr-tertiary-bg-rgb: 24, 33, 47;--tblr-primary-text-emphasis: rgb(102, 181.8, 177);--tblr-secondary-text-emphasis: rgb(166.2, 170.4, 178.8);--tblr-success-text-emphasis: rgb(130.2, 209.4, 142.8);--tblr-info-text-emphasis: rgb(141.6, 193.8, 237);--tblr-warning-text-emphasis: rgb(249, 197.4, 102);--tblr-danger-text-emphasis: rgb(230.4, 136.2, 136.2);--tblr-light-text-emphasis: #f3f4f6;--tblr-dark-text-emphasis: #d1d5db;--tblr-primary-bg-subtle: rgb(0, 26.6, 25);--tblr-secondary-bg-subtle: rgb(21.4, 22.8, 25.6);--tblr-success-bg-subtle: rgb(9.4, 35.8, 13.6);--tblr-info-bg-subtle: rgb(13.2, 30.6, 45);--tblr-warning-bg-subtle: rgb(49, 31.8, 0);--tblr-danger-bg-subtle: rgb(42.8, 11.4, 11.4);--tblr-light-bg-subtle: #1f2937;--tblr-dark-bg-subtle: rgb(15.5, 20.5, 27.5);--tblr-primary-border-subtle: rgb(0, 79.8, 75);--tblr-secondary-border-subtle: rgb(64.2, 68.4, 76.8);--tblr-success-border-subtle: rgb(28.2, 107.4, 40.8);--tblr-info-border-subtle: rgb(39.6, 91.8, 135);--tblr-warning-border-subtle: rgb(147, 95.4, 0);--tblr-danger-border-subtle: rgb(128.4, 34.2, 34.2);--tblr-light-border-subtle: #374151;--tblr-dark-border-subtle: #1f2937;--tblr-heading-color: inherit;--tblr-link-color: rgb(102, 181.8, 177);--tblr-link-hover-color: rgb(132.6, 196.44, 192.6);--tblr-link-color-rgb: 102, 182, 177;--tblr-link-hover-color-rgb: 133, 196, 193;--tblr-code-color: var(--tblr-gray-300);--tblr-highlight-color: #e5e7eb;--tblr-highlight-bg: rgb(98, 63.6, 0);--tblr-border-color: rgb(45.7069767442, 60.4511627907, 81.0930232558);--tblr-border-color-translucent: rgba(72, 110, 149, .14);--tblr-form-valid-color: rgb(130.2, 209.4, 142.8);--tblr-form-valid-border-color: rgb(130.2, 209.4, 142.8);--tblr-form-invalid-color: rgb(230.4, 136.2, 136.2);--tblr-form-invalid-border-color: rgb(230.4, 136.2, 136.2)}*,*:before,*:after{box-sizing:border-box}@media(prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--tblr-body-font-family);font-size:var(--tblr-body-font-size);font-weight:var(--tblr-body-font-weight);line-height:var(--tblr-body-line-height);color:var(--tblr-body-color);text-align:var(--tblr-body-text-align);background-color:var(--tblr-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr,.hr{margin:2rem 0;color:inherit;border:0;border-top:var(--tblr-border-width) solid;opacity:.16}h6,.h6,h5,.h5,h4,.h4,h3,.field-group h2,.field-group .h2,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:var(--tblr-spacer);font-weight:var(--tblr-font-weight-bold);line-height:1.2;color:var(--tblr-heading-color)}h1,.h1{font-size:1.5rem}h2,.h2{font-size:1.25rem}h3,.field-group h2,.field-group .h2,.h3{font-size:1rem}h4,.h4{font-size:.875rem}h5,.h5{font-size:.75rem}h6,.h6{font-size:.625rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:600}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small,.small{font-size:.875em}mark,.mark{padding:.1875em;color:var(--tblr-highlight-color);background-color:var(--tblr-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:rgba(var(--tblr-link-color-rgb),var(--tblr-link-opacity, 1));text-decoration:none}a:hover{--tblr-link-color-rgb: var(--tblr-link-hover-color-rgb);text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:var(--tblr-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.85714285em;color:var(--tblr-light)}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.85714285em;color:var(--tblr-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.25rem .5rem;font-size:var(--tblr-font-size-h5);color:var(--tblr-text-secondary-dark);background-color:var(--tblr-code-bg);border-radius:4px}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:var(--tblr-secondary-color);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;line-height:inherit;font-size:1.5rem}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button{cursor:pointer;filter:grayscale(1)}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:.875rem;font-weight:var(--tblr-font-weight-normal)}.display-1{font-weight:300;line-height:1.2;font-size:5rem}.display-2{font-weight:300;line-height:1.2;font-size:4.5rem}.display-3{font-weight:300;line-height:1.2;font-size:4rem}.display-4{font-weight:300;line-height:1.2;font-size:3.5rem}.display-5{font-weight:300;line-height:1.2;font-size:3rem}.display-6{font-weight:300;line-height:1.2;font-size:2rem}.list-unstyled,.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:.875rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#4b5563}.blockquote-footer:before{content:"\2014\a0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--tblr-body-bg);border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-box-shadow-sm);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--tblr-secondary-color)}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto}@media(min-width:576px){.container-sm,.container{max-width:540px}}@media(min-width:768px){.container-md,.container-sm,.container{max-width:720px}}@media(min-width:992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media(min-width:1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media(min-width:1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}:root{--tblr-breakpoint-xs: 0;--tblr-breakpoint-sm: 576px;--tblr-breakpoint-md: 768px;--tblr-breakpoint-lg: 992px;--tblr-breakpoint-xl: 1200px;--tblr-breakpoint-xxl: 1400px}.row{--tblr-gutter-x: var(--tblr-page-padding);--tblr-gutter-y: 0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--tblr-gutter-y));margin-right:calc(-.5 * var(--tblr-gutter-x));margin-left:calc(-.5 * var(--tblr-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-top:var(--tblr-gutter-y)}.grid{display:grid;grid-template-rows:repeat(var(--tblr-rows, 1),1fr);grid-template-columns:repeat(var(--tblr-columns, 12),1fr);gap:var(--tblr-gap, var(--tblr-page-padding))}.grid .g-col-1{grid-column:auto/span 1}.grid .g-col-2{grid-column:auto/span 2}.grid .g-col-3{grid-column:auto/span 3}.grid .g-col-4{grid-column:auto/span 4}.grid .g-col-5{grid-column:auto/span 5}.grid .g-col-6{grid-column:auto/span 6}.grid .g-col-7{grid-column:auto/span 7}.grid .g-col-8{grid-column:auto/span 8}.grid .g-col-9{grid-column:auto/span 9}.grid .g-col-10{grid-column:auto/span 10}.grid .g-col-11{grid-column:auto/span 11}.grid .g-col-12{grid-column:auto/span 12}.grid .g-start-1{grid-column-start:1}.grid .g-start-2{grid-column-start:2}.grid .g-start-3{grid-column-start:3}.grid .g-start-4{grid-column-start:4}.grid .g-start-5{grid-column-start:5}.grid .g-start-6{grid-column-start:6}.grid .g-start-7{grid-column-start:7}.grid .g-start-8{grid-column-start:8}.grid .g-start-9{grid-column-start:9}.grid .g-start-10{grid-column-start:10}.grid .g-start-11{grid-column-start:11}@media(min-width:576px){.grid .g-col-sm-1{grid-column:auto/span 1}.grid .g-col-sm-2{grid-column:auto/span 2}.grid .g-col-sm-3{grid-column:auto/span 3}.grid .g-col-sm-4{grid-column:auto/span 4}.grid .g-col-sm-5{grid-column:auto/span 5}.grid .g-col-sm-6{grid-column:auto/span 6}.grid .g-col-sm-7{grid-column:auto/span 7}.grid .g-col-sm-8{grid-column:auto/span 8}.grid .g-col-sm-9{grid-column:auto/span 9}.grid .g-col-sm-10{grid-column:auto/span 10}.grid .g-col-sm-11{grid-column:auto/span 11}.grid .g-col-sm-12{grid-column:auto/span 12}.grid .g-start-sm-1{grid-column-start:1}.grid .g-start-sm-2{grid-column-start:2}.grid .g-start-sm-3{grid-column-start:3}.grid .g-start-sm-4{grid-column-start:4}.grid .g-start-sm-5{grid-column-start:5}.grid .g-start-sm-6{grid-column-start:6}.grid .g-start-sm-7{grid-column-start:7}.grid .g-start-sm-8{grid-column-start:8}.grid .g-start-sm-9{grid-column-start:9}.grid .g-start-sm-10{grid-column-start:10}.grid .g-start-sm-11{grid-column-start:11}}@media(min-width:768px){.grid .g-col-md-1{grid-column:auto/span 1}.grid .g-col-md-2{grid-column:auto/span 2}.grid .g-col-md-3{grid-column:auto/span 3}.grid .g-col-md-4{grid-column:auto/span 4}.grid .g-col-md-5{grid-column:auto/span 5}.grid .g-col-md-6{grid-column:auto/span 6}.grid .g-col-md-7{grid-column:auto/span 7}.grid .g-col-md-8{grid-column:auto/span 8}.grid .g-col-md-9{grid-column:auto/span 9}.grid .g-col-md-10{grid-column:auto/span 10}.grid .g-col-md-11{grid-column:auto/span 11}.grid .g-col-md-12{grid-column:auto/span 12}.grid .g-start-md-1{grid-column-start:1}.grid .g-start-md-2{grid-column-start:2}.grid .g-start-md-3{grid-column-start:3}.grid .g-start-md-4{grid-column-start:4}.grid .g-start-md-5{grid-column-start:5}.grid .g-start-md-6{grid-column-start:6}.grid .g-start-md-7{grid-column-start:7}.grid .g-start-md-8{grid-column-start:8}.grid .g-start-md-9{grid-column-start:9}.grid .g-start-md-10{grid-column-start:10}.grid .g-start-md-11{grid-column-start:11}}@media(min-width:992px){.grid .g-col-lg-1{grid-column:auto/span 1}.grid .g-col-lg-2{grid-column:auto/span 2}.grid .g-col-lg-3{grid-column:auto/span 3}.grid .g-col-lg-4{grid-column:auto/span 4}.grid .g-col-lg-5{grid-column:auto/span 5}.grid .g-col-lg-6{grid-column:auto/span 6}.grid .g-col-lg-7{grid-column:auto/span 7}.grid .g-col-lg-8{grid-column:auto/span 8}.grid .g-col-lg-9{grid-column:auto/span 9}.grid .g-col-lg-10{grid-column:auto/span 10}.grid .g-col-lg-11{grid-column:auto/span 11}.grid .g-col-lg-12{grid-column:auto/span 12}.grid .g-start-lg-1{grid-column-start:1}.grid .g-start-lg-2{grid-column-start:2}.grid .g-start-lg-3{grid-column-start:3}.grid .g-start-lg-4{grid-column-start:4}.grid .g-start-lg-5{grid-column-start:5}.grid .g-start-lg-6{grid-column-start:6}.grid .g-start-lg-7{grid-column-start:7}.grid .g-start-lg-8{grid-column-start:8}.grid .g-start-lg-9{grid-column-start:9}.grid .g-start-lg-10{grid-column-start:10}.grid .g-start-lg-11{grid-column-start:11}}@media(min-width:1200px){.grid .g-col-xl-1{grid-column:auto/span 1}.grid .g-col-xl-2{grid-column:auto/span 2}.grid .g-col-xl-3{grid-column:auto/span 3}.grid .g-col-xl-4{grid-column:auto/span 4}.grid .g-col-xl-5{grid-column:auto/span 5}.grid .g-col-xl-6{grid-column:auto/span 6}.grid .g-col-xl-7{grid-column:auto/span 7}.grid .g-col-xl-8{grid-column:auto/span 8}.grid .g-col-xl-9{grid-column:auto/span 9}.grid .g-col-xl-10{grid-column:auto/span 10}.grid .g-col-xl-11{grid-column:auto/span 11}.grid .g-col-xl-12{grid-column:auto/span 12}.grid .g-start-xl-1{grid-column-start:1}.grid .g-start-xl-2{grid-column-start:2}.grid .g-start-xl-3{grid-column-start:3}.grid .g-start-xl-4{grid-column-start:4}.grid .g-start-xl-5{grid-column-start:5}.grid .g-start-xl-6{grid-column-start:6}.grid .g-start-xl-7{grid-column-start:7}.grid .g-start-xl-8{grid-column-start:8}.grid .g-start-xl-9{grid-column-start:9}.grid .g-start-xl-10{grid-column-start:10}.grid .g-start-xl-11{grid-column-start:11}}@media(min-width:1400px){.grid .g-col-xxl-1{grid-column:auto/span 1}.grid .g-col-xxl-2{grid-column:auto/span 2}.grid .g-col-xxl-3{grid-column:auto/span 3}.grid .g-col-xxl-4{grid-column:auto/span 4}.grid .g-col-xxl-5{grid-column:auto/span 5}.grid .g-col-xxl-6{grid-column:auto/span 6}.grid .g-col-xxl-7{grid-column:auto/span 7}.grid .g-col-xxl-8{grid-column:auto/span 8}.grid .g-col-xxl-9{grid-column:auto/span 9}.grid .g-col-xxl-10{grid-column:auto/span 10}.grid .g-col-xxl-11{grid-column:auto/span 11}.grid .g-col-xxl-12{grid-column:auto/span 12}.grid .g-start-xxl-1{grid-column-start:1}.grid .g-start-xxl-2{grid-column-start:2}.grid .g-start-xxl-3{grid-column-start:3}.grid .g-start-xxl-4{grid-column-start:4}.grid .g-start-xxl-5{grid-column-start:5}.grid .g-start-xxl-6{grid-column-start:6}.grid .g-start-xxl-7{grid-column-start:7}.grid .g-start-xxl-8{grid-column-start:8}.grid .g-start-xxl-9{grid-column-start:9}.grid .g-start-xxl-10{grid-column-start:10}.grid .g-start-xxl-11{grid-column-start:11}}.col{flex:1 0 0}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.66666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--tblr-gutter-x: 0}.g-0,.gy-0{--tblr-gutter-y: 0}.g-1,.gx-1{--tblr-gutter-x: .25rem}.g-1,.gy-1{--tblr-gutter-y: .25rem}.g-2,.gx-2{--tblr-gutter-x: .5rem}.g-2,.gy-2{--tblr-gutter-y: .5rem}.g-3,.gx-3{--tblr-gutter-x: 1rem}.g-3,.gy-3{--tblr-gutter-y: 1rem}.g-4,.gx-4{--tblr-gutter-x: 1.5rem}.g-4,.gy-4{--tblr-gutter-y: 1.5rem}.g-5,.gx-5{--tblr-gutter-x: 2rem}.g-5,.gy-5{--tblr-gutter-y: 2rem}.g-6,.gx-6{--tblr-gutter-x: 2.5rem}.g-6,.gy-6{--tblr-gutter-y: 2.5rem}@media(min-width:576px){.col-sm{flex:1 0 0}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.66666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--tblr-gutter-x: 0}.g-sm-0,.gy-sm-0{--tblr-gutter-y: 0}.g-sm-1,.gx-sm-1{--tblr-gutter-x: .25rem}.g-sm-1,.gy-sm-1{--tblr-gutter-y: .25rem}.g-sm-2,.gx-sm-2{--tblr-gutter-x: .5rem}.g-sm-2,.gy-sm-2{--tblr-gutter-y: .5rem}.g-sm-3,.gx-sm-3{--tblr-gutter-x: 1rem}.g-sm-3,.gy-sm-3{--tblr-gutter-y: 1rem}.g-sm-4,.gx-sm-4{--tblr-gutter-x: 1.5rem}.g-sm-4,.gy-sm-4{--tblr-gutter-y: 1.5rem}.g-sm-5,.gx-sm-5{--tblr-gutter-x: 2rem}.g-sm-5,.gy-sm-5{--tblr-gutter-y: 2rem}.g-sm-6,.gx-sm-6{--tblr-gutter-x: 2.5rem}.g-sm-6,.gy-sm-6{--tblr-gutter-y: 2.5rem}}@media(min-width:768px){.col-md{flex:1 0 0}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.66666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--tblr-gutter-x: 0}.g-md-0,.gy-md-0{--tblr-gutter-y: 0}.g-md-1,.gx-md-1{--tblr-gutter-x: .25rem}.g-md-1,.gy-md-1{--tblr-gutter-y: .25rem}.g-md-2,.gx-md-2{--tblr-gutter-x: .5rem}.g-md-2,.gy-md-2{--tblr-gutter-y: .5rem}.g-md-3,.gx-md-3{--tblr-gutter-x: 1rem}.g-md-3,.gy-md-3{--tblr-gutter-y: 1rem}.g-md-4,.gx-md-4{--tblr-gutter-x: 1.5rem}.g-md-4,.gy-md-4{--tblr-gutter-y: 1.5rem}.g-md-5,.gx-md-5{--tblr-gutter-x: 2rem}.g-md-5,.gy-md-5{--tblr-gutter-y: 2rem}.g-md-6,.gx-md-6{--tblr-gutter-x: 2.5rem}.g-md-6,.gy-md-6{--tblr-gutter-y: 2.5rem}}@media(min-width:992px){.col-lg{flex:1 0 0}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.66666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--tblr-gutter-x: 0}.g-lg-0,.gy-lg-0{--tblr-gutter-y: 0}.g-lg-1,.gx-lg-1{--tblr-gutter-x: .25rem}.g-lg-1,.gy-lg-1{--tblr-gutter-y: .25rem}.g-lg-2,.gx-lg-2{--tblr-gutter-x: .5rem}.g-lg-2,.gy-lg-2{--tblr-gutter-y: .5rem}.g-lg-3,.gx-lg-3{--tblr-gutter-x: 1rem}.g-lg-3,.gy-lg-3{--tblr-gutter-y: 1rem}.g-lg-4,.gx-lg-4{--tblr-gutter-x: 1.5rem}.g-lg-4,.gy-lg-4{--tblr-gutter-y: 1.5rem}.g-lg-5,.gx-lg-5{--tblr-gutter-x: 2rem}.g-lg-5,.gy-lg-5{--tblr-gutter-y: 2rem}.g-lg-6,.gx-lg-6{--tblr-gutter-x: 2.5rem}.g-lg-6,.gy-lg-6{--tblr-gutter-y: 2.5rem}}@media(min-width:1200px){.col-xl{flex:1 0 0}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.66666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--tblr-gutter-x: 0}.g-xl-0,.gy-xl-0{--tblr-gutter-y: 0}.g-xl-1,.gx-xl-1{--tblr-gutter-x: .25rem}.g-xl-1,.gy-xl-1{--tblr-gutter-y: .25rem}.g-xl-2,.gx-xl-2{--tblr-gutter-x: .5rem}.g-xl-2,.gy-xl-2{--tblr-gutter-y: .5rem}.g-xl-3,.gx-xl-3{--tblr-gutter-x: 1rem}.g-xl-3,.gy-xl-3{--tblr-gutter-y: 1rem}.g-xl-4,.gx-xl-4{--tblr-gutter-x: 1.5rem}.g-xl-4,.gy-xl-4{--tblr-gutter-y: 1.5rem}.g-xl-5,.gx-xl-5{--tblr-gutter-x: 2rem}.g-xl-5,.gy-xl-5{--tblr-gutter-y: 2rem}.g-xl-6,.gx-xl-6{--tblr-gutter-x: 2.5rem}.g-xl-6,.gy-xl-6{--tblr-gutter-y: 2.5rem}}@media(min-width:1400px){.col-xxl{flex:1 0 0}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.66666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--tblr-gutter-x: 0}.g-xxl-0,.gy-xxl-0{--tblr-gutter-y: 0}.g-xxl-1,.gx-xxl-1{--tblr-gutter-x: .25rem}.g-xxl-1,.gy-xxl-1{--tblr-gutter-y: .25rem}.g-xxl-2,.gx-xxl-2{--tblr-gutter-x: .5rem}.g-xxl-2,.gy-xxl-2{--tblr-gutter-y: .5rem}.g-xxl-3,.gx-xxl-3{--tblr-gutter-x: 1rem}.g-xxl-3,.gy-xxl-3{--tblr-gutter-y: 1rem}.g-xxl-4,.gx-xxl-4{--tblr-gutter-x: 1.5rem}.g-xxl-4,.gy-xxl-4{--tblr-gutter-y: 1.5rem}.g-xxl-5,.gx-xxl-5{--tblr-gutter-x: 2rem}.g-xxl-5,.gy-xxl-5{--tblr-gutter-y: 2rem}.g-xxl-6,.gx-xxl-6{--tblr-gutter-x: 2.5rem}.g-xxl-6,.gy-xxl-6{--tblr-gutter-y: 2.5rem}}.table,.markdown>table{--tblr-table-color-type: initial;--tblr-table-bg-type: initial;--tblr-table-color-state: initial;--tblr-table-bg-state: initial;--tblr-table-color: inherit;--tblr-table-bg: transparent;--tblr-table-border-color: var(--tblr-border-color-translucent);--tblr-table-accent-bg: transparent;--tblr-table-striped-color: inherit;--tblr-table-striped-bg: var(--tblr-bg-surface-tertiary);--tblr-table-active-color: inherit;--tblr-table-active-bg: var(--tblr-active-bg);--tblr-table-hover-color: inherit;--tblr-table-hover-bg: rgba(var(--tblr-emphasis-color-rgb), .075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--tblr-table-border-color)}.table>:not(caption)>*>*,.markdown>table>:not(caption)>*>*{padding:.5rem;color:var(--tblr-table-color-state, var(--tblr-table-color-type, var(--tblr-table-color)));background-color:var(--tblr-table-bg);border-bottom-width:var(--tblr-border-width);box-shadow:inset 0 0 0 9999px var(--tblr-table-bg-state, var(--tblr-table-bg-type, var(--tblr-table-accent-bg)))}.table>tbody,.markdown>table>tbody{vertical-align:inherit}.table>thead,.markdown>table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(var(--tblr-border-width) * 2) solid var(--tblr-border-color-translucent)}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*,.markdown>table>:not(caption)>*>*{padding:.25rem}.table-bordered>:not(caption)>*,.markdown>table>:not(caption)>*{border-width:var(--tblr-border-width) 0}.table-bordered>:not(caption)>*>*,.markdown>table>:not(caption)>*>*{border-width:0 var(--tblr-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(2n)>*{--tblr-table-color-type: var(--tblr-table-striped-color);--tblr-table-bg-type: var(--tblr-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--tblr-table-color-type: var(--tblr-table-striped-color);--tblr-table-bg-type: var(--tblr-table-striped-bg)}.table-active{--tblr-table-color-state: var(--tblr-table-active-color);--tblr-table-bg-state: var(--tblr-table-active-bg)}.table-hover>tbody>tr:hover>*{--tblr-table-color-state: var(--tblr-table-hover-color);--tblr-table-bg-state: var(--tblr-table-hover-bg)}.table-primary{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(204, 230.6, 229);--tblr-table-border-color: rgb(169.4, 192.68, 194.2);--tblr-table-striped-bg: rgb(195.35, 221.12, 220.3);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(186.7, 211.64, 211.6);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(191.025, 216.38, 215.95);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-secondary{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(225.4, 226.8, 229.6);--tblr-table-border-color: rgb(186.52, 189.64, 194.68);--tblr-table-striped-bg: rgb(215.68, 217.51, 220.87);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(205.96, 208.22, 212.14);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(210.82, 212.865, 216.505);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-success{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(213.4, 239.8, 217.6);--tblr-table-border-color: rgb(176.92, 200.04, 185.08);--tblr-table-striped-bg: rgb(204.28, 229.86, 209.47);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(195.16, 219.92, 201.34);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(199.72, 224.89, 205.405);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-info{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(217.2, 234.6, 249);--tblr-table-border-color: rgb(179.96, 195.88, 210.2);--tblr-table-striped-bg: rgb(207.89, 224.92, 239.3);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(198.58, 215.24, 229.6);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(203.235, 220.08, 234.45);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-warning{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(253, 235.8, 204);--tblr-table-border-color: rgb(208.6, 196.84, 174.2);--tblr-table-striped-bg: rgb(241.9, 226.06, 196.55);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(230.8, 216.32, 189.1);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(236.35, 221.19, 192.825);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-danger{--tblr-table-color: #1f2937;--tblr-table-bg: rgb(246.8, 215.4, 215.4);--tblr-table-border-color: rgb(203.64, 180.52, 183.32);--tblr-table-striped-bg: rgb(236.01, 206.68, 207.38);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(225.22, 197.96, 199.36);--tblr-table-active-color: #f9fafb;--tblr-table-hover-bg: rgb(230.615, 202.32, 203.37);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-light{--tblr-table-color: #1f2937;--tblr-table-bg: #f9fafb;--tblr-table-border-color: rgb(205.4, 208.2, 211.8);--tblr-table-striped-bg: rgb(238.1, 239.55, 241.2);--tblr-table-striped-color: #1f2937;--tblr-table-active-bg: rgb(227.2, 229.1, 231.4);--tblr-table-active-color: #1f2937;--tblr-table-hover-bg: rgb(232.65, 234.325, 236.3);--tblr-table-hover-color: #1f2937;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-dark{--tblr-table-color: #f9fafb;--tblr-table-bg: #1f2937;--tblr-table-border-color: rgb(74.6, 82.8, 94.2);--tblr-table-striped-bg: rgb(41.9, 51.45, 64.8);--tblr-table-striped-color: #f9fafb;--tblr-table-active-bg: rgb(52.8, 61.9, 74.6);--tblr-table-active-color: #f9fafb;--tblr-table-hover-bg: rgb(47.35, 56.675, 69.7);--tblr-table-hover-color: #f9fafb;color:var(--tblr-table-color);border-color:var(--tblr-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem;font-size:.875rem;font-weight:var(--tblr-font-weight-medium)}.col-form-label{padding-top:calc(.5625rem + var(--tblr-border-width));padding-bottom:calc(.5625rem + var(--tblr-border-width));margin-bottom:0;font-size:inherit;font-weight:var(--tblr-font-weight-medium);line-height:1.25rem}.col-form-label-lg{padding-top:calc(.6875rem + var(--tblr-border-width));padding-bottom:calc(.6875rem + var(--tblr-border-width));font-size:1rem}.col-form-label-sm{padding-top:calc(.3125rem + var(--tblr-border-width));padding-bottom:calc(.3125rem + var(--tblr-border-width));font-size:.75rem}.form-text{margin-top:.25rem;font-size:.875em;color:var(--tblr-secondary-color)}.form-control{display:block;width:100%;padding:.5625rem 1rem;font-family:var(--tblr-body-font-family);font-size:.875rem;font-weight:400;line-height:1.25rem;color:var(--tblr-body-color);appearance:none;background-color:var(--tblr-bg-forms);background-clip:padding-box;border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-shadow-input);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--tblr-body-color);background-color:var(--tblr-bg-forms);border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.25rem;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--tblr-tertiary);opacity:1}.form-control:disabled{background-color:var(--tblr-bg-surface-secondary);opacity:1}.form-control::file-selector-button{padding:.5625rem 1rem;margin:-.5625rem -1rem;margin-inline-end:1rem;color:var(--tblr-body-color);background-color:var(--tblr-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--tblr-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--tblr-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.5625rem 0;margin-bottom:0;line-height:1.25rem;color:var(--tblr-body-color);background-color:transparent;border:solid transparent;border-width:var(--tblr-border-width) 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2));padding:.3125rem .5rem;font-size:.75rem;border-radius:var(--tblr-border-radius-sm)}.form-control-sm::file-selector-button{padding:.3125rem .5rem;margin:-.3125rem -.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2));padding:.6875rem 1.5rem;font-size:1rem;border-radius:var(--tblr-border-radius-lg)}.form-control-lg::file-selector-button{padding:.6875rem 1.5rem;margin:-.6875rem -1.5rem;margin-inline-end:1.5rem}textarea.form-control{min-height:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2));padding:.5625rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:var(--tblr-border-radius)}.form-control-color::-webkit-color-swatch{border:0!important;border-radius:var(--tblr-border-radius)}.form-control-color.form-control-sm{height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2))}.form-select{--tblr-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.5625rem 3rem .5625rem 1rem;font-family:var(--tblr-body-font-family);font-size:.875rem;font-weight:400;line-height:1.25rem;color:var(--tblr-body-color);appearance:none;background-color:var(--tblr-bg-forms);background-image:var(--tblr-form-select-bg-img),var(--tblr-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right 1rem center;background-size:16px 12px;border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-shadow-input);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:1rem;background-image:none}.form-select:disabled{background-color:var(--tblr-bg-surface-secondary)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--tblr-body-color)}.form-select-sm{padding-top:.3125rem;padding-bottom:.3125rem;padding-left:.5rem;font-size:.75rem;border-radius:var(--tblr-border-radius-sm)}.form-select-lg{padding-top:.6875rem;padding-bottom:.6875rem;padding-left:1.5rem;font-size:1rem;border-radius:var(--tblr-border-radius-lg)}[data-bs-theme=dark] .form-select,body[data-bs-theme=dark] [data-bs-theme=light] .form-select{--tblr-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23e5e7eb' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check{display:block;min-height:1.25rem;padding-left:2rem;margin-bottom:.75rem}.form-check .form-check-input{float:left;margin-left:-2rem}.form-check-reverse{padding-right:2rem;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-2rem;margin-left:0}.form-check-input{--tblr-form-check-bg: var(--tblr-bg-forms);flex-shrink:0;width:1.25rem;height:1.25rem;margin-top:.0892857143rem;vertical-align:top;appearance:none;background-color:var(--tblr-form-check-bg);background-image:var(--tblr-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:var(--tblr-border-radius)}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#80c2be;outline:0;box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-check-input:checked{background-color:var(--tblr-primary);border-color:var(--tblr-border-color-translucent)}.form-check-input:checked[type=checkbox]{--tblr-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--tblr-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3ccircle r='3' fill='%23ffffff' cx='8' cy='8' /%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:var(--tblr-primary);border-color:var(--tblr-primary);--tblr-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input:disabled~.form-check-label{cursor:default;opacity:.7}.form-switch{padding-left:2.5rem}.form-switch .form-check-input{--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23e5e7eb'/%3e%3c/svg%3e");width:2rem;margin-left:-2.5rem;background-image:var(--tblr-form-switch-bg);background-position:left center;border-radius:2rem;transition:background-position .15s ease-in-out}.form-switch .form-check-input:focus{--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28127.5, 194, 190%29'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5rem;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5rem;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.4}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--tblr-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.25rem;padding:0;appearance:none;background-color:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #f9fafb,0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #f9fafb,0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.375rem;appearance:none;background-color:var(--tblr-primary);border:2px var(--tblr-border-style) #ffffff;border-radius:1rem;box-shadow:0 .1rem .25rem #0000001a;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b3dad8}.form-range::-webkit-slider-runnable-track{width:100%;height:.25rem;color:transparent;cursor:pointer;background-color:var(--tblr-border-color);border-color:transparent;border-radius:1rem;box-shadow:var(--tblr-box-shadow-inset)}.form-range::-moz-range-thumb{width:1rem;height:1rem;appearance:none;background-color:var(--tblr-primary);border:2px var(--tblr-border-style) #ffffff;border-radius:1rem;box-shadow:0 .1rem .25rem #0000001a;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#b3dad8}.form-range::-moz-range-track{width:100%;height:.25rem;color:transparent;cursor:pointer;background-color:var(--tblr-border-color);border-color:transparent;border-radius:1rem;box-shadow:var(--tblr-box-shadow-inset)}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--tblr-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--tblr-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--tblr-border-width) * 2));min-height:calc(3.5rem + calc(var(--tblr-border-width) * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;max-width:100%;height:100%;padding:1rem;overflow:hidden;color:rgba(var(--tblr-body-color-rgb),.65);text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:var(--tblr-border-width) solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem}.form-floating>.form-control::placeholder,.form-floating>.form-control-plaintext::placeholder{color:transparent}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown),.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill,.form-floating>.form-control-plaintext:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem;padding-left:1rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-control-plaintext~label,.form-floating>.form-select~label{transform:scale(.85) translateY(-.5rem) translate(.15rem)}.form-floating>.form-control:-webkit-autofill~label{transform:scale(.85) translateY(-.5rem) translate(.15rem)}.form-floating>textarea:focus~label:after,.form-floating>textarea:not(:placeholder-shown)~label:after{position:absolute;inset:1rem .5rem;z-index:-1;height:1.5em;content:"";background-color:var(--tblr-bg-forms);border-radius:var(--tblr-border-radius)}.form-floating>textarea:disabled~label:after{background-color:var(--tblr-bg-surface-secondary)}.form-floating>.form-control-plaintext~label{border-width:var(--tblr-border-width) 0}.form-floating>:disabled~label,.form-floating>.form-control:disabled~label{color:#4b5563}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-floating{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus,.input-group>.form-floating:focus-within{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.5625rem 1rem;font-size:.875rem;font-weight:400;line-height:1.25rem;color:var(--tblr-gray-500);text-align:center;white-space:nowrap;background-color:var(--tblr-bg-surface-secondary);border:var(--tblr-border-width) solid var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.6875rem 1.5rem;font-size:1rem;border-radius:var(--tblr-border-radius-lg)}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.3125rem .5rem;font-size:.75rem;border-radius:var(--tblr-border-radius-sm)}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:4rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(-1 * var(--tblr-border-width));border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--tblr-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:var(--tblr-spacer-1) var(--tblr-spacer-3);margin-top:.1rem;font-size:.765625rem;color:#fff;background-color:var(--tblr-success);border-radius:var(--tblr-border-radius)}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:var(--tblr-form-valid-border-color);padding-right:2.375rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:var(--tblr-form-valid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-success-rgb),.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:2.375rem;background-position:top 1.53125rem right 1.53125rem}.was-validated .form-select:valid,.form-select.is-valid{border-color:var(--tblr-form-valid-border-color)}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{--tblr-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");padding-right:5.5rem;background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:var(--tblr-form-valid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-success-rgb),.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:5.375rem}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:var(--tblr-form-valid-border-color)}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:var(--tblr-form-valid-color)}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(var(--tblr-success-rgb),.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:var(--tblr-form-valid-color)}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):valid,.input-group>.form-control:not(:focus).is-valid,.was-validated .input-group>.form-select:not(:focus):valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.input-group>.form-floating:not(:focus-within).is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--tblr-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:var(--tblr-spacer-1) var(--tblr-spacer-3);margin-top:.1rem;font-size:.765625rem;color:#fff;background-color:var(--tblr-danger);border-radius:var(--tblr-border-radius)}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,select.tomselected.is-invalid+div.ts-wrapper~.invalid-feedback,.is-invalid~.invalid-tooltip,select.tomselected.is-invalid+div.ts-wrapper~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid,select.tomselected.is-invalid+div.form-control.ts-wrapper{border-color:var(--tblr-form-invalid-border-color);padding-right:2.375rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus,select.tomselected.is-invalid+div.form-control.ts-wrapper:focus{border-color:var(--tblr-form-invalid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-danger-rgb),.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:2.375rem;background-position:top 1.53125rem right 1.53125rem}.was-validated .form-select:invalid,.form-select.is-invalid,select.tomselected.is-invalid+div.form-select.ts-wrapper{border-color:var(--tblr-form-invalid-border-color)}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),select.tomselected.is-invalid+div.form-select.ts-wrapper:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],select.tomselected.is-invalid+div.form-select.ts-wrapper:not([multiple])[size="1"]{--tblr-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");padding-right:5.5rem;background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus,select.tomselected.is-invalid+div.form-select.ts-wrapper:focus{border-color:var(--tblr-form-invalid-border-color);box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-danger-rgb),.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid,select.tomselected.is-invalid+div.form-control-color.ts-wrapper{width:5.375rem}.was-validated .form-check-input:invalid,.form-check-input.is-invalid,select.tomselected.is-invalid+div.form-check-input.ts-wrapper{border-color:var(--tblr-form-invalid-border-color)}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked,select.tomselected.is-invalid+div.form-check-input.ts-wrapper:checked{background-color:var(--tblr-form-invalid-color)}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus,select.tomselected.is-invalid+div.form-check-input.ts-wrapper:focus{box-shadow:0 0 0 .25rem rgba(var(--tblr-danger-rgb),.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label,select.tomselected.is-invalid+div.form-check-input.ts-wrapper~.form-check-label{color:var(--tblr-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):invalid,.input-group>.form-control:not(:focus).is-invalid,.input-group>select.tomselected.is-invalid+div.form-control.ts-wrapper:not(:focus),.was-validated .input-group>.form-select:not(:focus):invalid,.input-group>.form-select:not(:focus).is-invalid,.input-group>select.tomselected.is-invalid+div.form-select.ts-wrapper:not(:focus),.was-validated .input-group>.form-floating:not(:focus-within):invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>select.tomselected.is-invalid+div.form-floating.ts-wrapper:not(:focus-within){z-index:4}.btn{--tblr-btn-padding-x: .5rem;--tblr-btn-padding-y: .25rem;--tblr-btn-font-family: var(--tblr-body-font-family);--tblr-btn-font-size: .875rem;--tblr-btn-font-weight: var(--tblr-font-weight-medium);--tblr-btn-line-height: 1.25rem;--tblr-btn-color: var(--tblr-body-color);--tblr-btn-bg: transparent;--tblr-btn-border-width: var(--tblr-border-width);--tblr-btn-border-color: transparent;--tblr-btn-border-radius: var(--tblr-border-radius);--tblr-btn-hover-border-color: transparent;--tblr-btn-box-shadow: var(--tblr-shadow-input);--tblr-btn-disabled-opacity: .4;--tblr-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--tblr-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--tblr-btn-padding-y) var(--tblr-btn-padding-x);font-family:var(--tblr-btn-font-family);font-size:var(--tblr-btn-font-size);font-weight:var(--tblr-btn-font-weight);line-height:var(--tblr-btn-line-height);color:var(--tblr-btn-color);text-align:center;vertical-align:middle;cursor:pointer;user-select:none;border:var(--tblr-btn-border-width) solid var(--tblr-btn-border-color);border-radius:var(--tblr-btn-border-radius);background-color:var(--tblr-btn-bg);box-shadow:var(--tblr-btn-box-shadow);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--tblr-btn-hover-color);text-decoration:none;background-color:var(--tblr-btn-hover-bg);border-color:var(--tblr-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--tblr-btn-color);background-color:var(--tblr-btn-bg);border-color:var(--tblr-btn-border-color)}.btn:focus-visible{color:var(--tblr-btn-hover-color);background-color:var(--tblr-btn-hover-bg);border-color:var(--tblr-btn-hover-border-color);outline:0;box-shadow:var(--tblr-btn-box-shadow),var(--tblr-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--tblr-btn-hover-border-color);outline:0;box-shadow:var(--tblr-btn-box-shadow),var(--tblr-btn-focus-box-shadow)}.btn-check:checked+.btn,:not(.btn-check)+.btn:active,.btn:first-child:active,.btn.active,.btn.show{color:var(--tblr-btn-active-color);background-color:var(--tblr-btn-active-bg);border-color:var(--tblr-btn-active-border-color);box-shadow:var(--tblr-btn-active-shadow)}.btn-check:checked+.btn:focus-visible,:not(.btn-check)+.btn:active:focus-visible,.btn:first-child:active:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible{box-shadow:var(--tblr-btn-active-shadow),var(--tblr-btn-focus-box-shadow)}.btn-check:checked:focus-visible+.btn{box-shadow:var(--tblr-btn-active-shadow),var(--tblr-btn-focus-box-shadow)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{color:var(--tblr-btn-disabled-color);pointer-events:none;background-color:var(--tblr-btn-disabled-bg);border-color:var(--tblr-btn-disabled-border-color);opacity:var(--tblr-btn-disabled-opacity);box-shadow:none}.btn-link{--tblr-btn-font-weight: 400;--tblr-btn-color: var(--tblr-link-color);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-link-hover-color);--tblr-btn-hover-border-color: transparent;--tblr-btn-active-color: var(--tblr-link-hover-color);--tblr-btn-active-border-color: transparent;--tblr-btn-disabled-color: #4b5563;--tblr-btn-disabled-border-color: transparent;--tblr-btn-box-shadow: 0 0 0 #000;--tblr-btn-focus-shadow-rgb: 37, 151, 144;text-decoration:none}.btn-link:hover,.btn-link:focus-visible{text-decoration:underline}.btn-link:focus-visible{color:var(--tblr-btn-color)}.btn-link:hover{color:var(--tblr-btn-hover-color)}.btn-lg,.btn-group-lg>.btn{--tblr-btn-padding-y: .6875rem;--tblr-btn-padding-x: 1.5rem;--tblr-btn-font-size: 1rem;--tblr-btn-border-radius: var(--tblr-border-radius-lg)}.btn-sm,.btn-group-sm>.btn{--tblr-btn-padding-y: .3125rem;--tblr-btn-padding-x: .5rem;--tblr-btn-font-size: .75rem;--tblr-btn-border-radius: var(--tblr-border-radius-sm)}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media(prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart,.dropup-center,.dropdown-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(-45deg)}.dropdown-menu{--tblr-dropdown-zindex: 1000;--tblr-dropdown-min-width: 11rem;--tblr-dropdown-padding-x: 0;--tblr-dropdown-padding-y: .25rem;--tblr-dropdown-spacer: 1px;--tblr-dropdown-font-size: .875rem;--tblr-dropdown-color: var(--tblr-body-color);--tblr-dropdown-bg: var(--tblr-bg-surface);--tblr-dropdown-border-color: var(--tblr-border-color-translucent);--tblr-dropdown-border-radius: var(--tblr-border-radius);--tblr-dropdown-border-width: var(--tblr-border-width);--tblr-dropdown-inner-border-radius: calc(var(--tblr-border-radius) - var(--tblr-border-width));--tblr-dropdown-divider-bg: var(--tblr-border-color-translucent);--tblr-dropdown-divider-margin-y: var(--tblr-spacer-2);--tblr-dropdown-box-shadow: var(--tblr-shadow-dropdown);--tblr-dropdown-link-color: inherit;--tblr-dropdown-link-hover-color: inherit;--tblr-dropdown-link-hover-bg: rgba(var(--tblr-secondary-rgb), .08);--tblr-dropdown-link-active-color: var(--tblr-primary);--tblr-dropdown-link-active-bg: var(--tblr-active-bg);--tblr-dropdown-link-disabled-color: var(--tblr-tertiary-color);--tblr-dropdown-item-padding-x: .75rem;--tblr-dropdown-item-padding-y: .5rem;--tblr-dropdown-header-color: #4b5563;--tblr-dropdown-header-padding-x: .75rem;--tblr-dropdown-header-padding-y: .25rem;position:absolute;z-index:var(--tblr-dropdown-zindex);display:none;min-width:var(--tblr-dropdown-min-width);padding:var(--tblr-dropdown-padding-y) var(--tblr-dropdown-padding-x);margin:0;font-size:var(--tblr-dropdown-font-size);color:var(--tblr-dropdown-color);text-align:left;list-style:none;background-color:var(--tblr-dropdown-bg);background-clip:padding-box;border:var(--tblr-dropdown-border-width) solid var(--tblr-dropdown-border-color);border-radius:var(--tblr-dropdown-border-radius);box-shadow:var(--tblr-dropdown-box-shadow)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--tblr-dropdown-spacer)}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width:576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width:768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width:992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width:1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width:1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--tblr-dropdown-spacer)}.dropup .dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(135deg)}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--tblr-dropdown-spacer)}.dropend .dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(-135deg)}.dropend .dropdown-toggle:after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--tblr-dropdown-spacer)}.dropstart .dropdown-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(45deg)}.dropstart .dropdown-toggle:before{vertical-align:0}.dropdown-divider{height:0;margin:var(--tblr-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--tblr-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--tblr-dropdown-item-padding-y) var(--tblr-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--tblr-dropdown-link-color);text-align:inherit;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--tblr-dropdown-item-border-radius, 0)}.dropdown-item:hover,.dropdown-item:focus{color:var(--tblr-dropdown-link-hover-color);text-decoration:none;background-color:var(--tblr-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--tblr-dropdown-link-active-color);text-decoration:none;background-color:var(--tblr-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--tblr-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--tblr-dropdown-header-padding-y) var(--tblr-dropdown-header-padding-x);margin-bottom:0;font-size:.765625rem;color:var(--tblr-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--tblr-dropdown-item-padding-y) var(--tblr-dropdown-item-padding-x);color:var(--tblr-dropdown-link-color)}.dropdown-menu-dark{--tblr-dropdown-color: #d1d5db;--tblr-dropdown-bg: #1f2937;--tblr-dropdown-border-color: var(--tblr-border-color-translucent);--tblr-dropdown-box-shadow: ;--tblr-dropdown-link-color: #d1d5db;--tblr-dropdown-link-hover-color: #ffffff;--tblr-dropdown-divider-bg: var(--tblr-border-color-translucent);--tblr-dropdown-link-hover-bg: rgba(255, 255, 255, .15);--tblr-dropdown-link-active-color: var(--tblr-primary);--tblr-dropdown-link-active-bg: var(--tblr-active-bg);--tblr-dropdown-link-disabled-color: #6b7280;--tblr-dropdown-header-color: #6b7280}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:var(--tblr-border-radius)}.btn-group>:not(.btn-check:first-child)+.btn,.btn-group>.btn-group:not(:first-child){margin-left:calc(-1 * var(--tblr-border-width))}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after,.dropend .dropdown-toggle-split:after{margin-left:0}.dropstart .dropdown-toggle-split:before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:1.125rem;padding-left:1.125rem}.btn-group.show .dropdown-toggle{box-shadow:inset 0 3px 5px #00000020}.btn-group.show .dropdown-toggle.btn-link{box-shadow:none}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:calc(-1 * var(--tblr-border-width))}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:nth-child(n+3),.btn-group-vertical>:not(.btn-check)+.btn,.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--tblr-nav-link-padding-x: .75rem;--tblr-nav-link-padding-y: .5rem;--tblr-nav-link-font-weight: ;--tblr-nav-link-color: var(--tblr-gray-500);--tblr-nav-link-hover-color: var(--tblr-link-hover-color);--tblr-nav-link-disabled-color: var(--tblr-disabled-color);display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--tblr-nav-link-padding-y) var(--tblr-nav-link-padding-x);font-size:var(--tblr-nav-link-font-size);font-weight:var(--tblr-nav-link-font-weight);color:var(--tblr-nav-link-color);background:none;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}.nav-link:hover,.nav-link:focus{color:var(--tblr-nav-link-hover-color);text-decoration:none}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.nav-link.disabled,.nav-link:disabled{color:var(--tblr-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--tblr-nav-tabs-border-width: var(--tblr-border-width);--tblr-nav-tabs-border-color: var(--tblr-border-color);--tblr-nav-tabs-border-radius: var(--tblr-border-radius);--tblr-nav-tabs-link-hover-border-color: var(--tblr-border-color) var(--tblr-border-color) var(--tblr-border-color);--tblr-nav-tabs-link-active-color: var(--tblr-body-color);--tblr-nav-tabs-link-active-bg: var(--tblr-body-bg);--tblr-nav-tabs-link-active-border-color: var(--tblr-border-color) var(--tblr-border-color) var(--tblr-border-color);border-bottom:var(--tblr-nav-tabs-border-width) solid var(--tblr-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--tblr-nav-tabs-border-width));border:var(--tblr-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--tblr-nav-tabs-border-radius);border-top-right-radius:var(--tblr-nav-tabs-border-radius)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{isolation:isolate;border-color:var(--tblr-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:var(--tblr-nav-tabs-link-active-color);background-color:var(--tblr-nav-tabs-link-active-bg);border-color:var(--tblr-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--tblr-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--tblr-nav-pills-border-radius: var(--tblr-border-radius);--tblr-nav-pills-link-active-color: var(--tblr-primary);--tblr-nav-pills-link-active-bg: rgba(var(--tblr-secondary-rgb), .15)}.nav-pills .nav-link{border-radius:var(--tblr-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--tblr-nav-pills-link-active-color);background-color:var(--tblr-nav-pills-link-active-bg)}.nav-underline{--tblr-nav-underline-gap: 1rem;--tblr-nav-underline-border-width: .125rem;--tblr-nav-underline-link-active-color: var(--tblr-emphasis-color);gap:var(--tblr-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--tblr-nav-underline-border-width) solid transparent}.nav-underline .nav-link:hover,.nav-underline .nav-link:focus{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:600;color:var(--tblr-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-grow:1;flex-basis:0;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--tblr-navbar-padding-x: 0;--tblr-navbar-padding-y: .25rem;--tblr-navbar-color: var(--tblr-secondary);--tblr-navbar-hover-color: var(--tblr-body-color);--tblr-navbar-disabled-color: var(--tblr-disabled-color);--tblr-navbar-active-color: var(--tblr-body-color);--tblr-navbar-brand-padding-y: .5rem;--tblr-navbar-brand-margin-end: 1rem;--tblr-navbar-brand-font-size: 1.25rem;--tblr-navbar-brand-color: var(--tblr-body-color);--tblr-navbar-brand-hover-color: var(--tblr-body-color);--tblr-navbar-nav-link-padding-x: .75rem;--tblr-navbar-toggler-padding-y: 0;--tblr-navbar-toggler-padding-x: 0;--tblr-navbar-toggler-font-size: 1rem;--tblr-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2831, 41, 55, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--tblr-navbar-toggler-border-color: rgba(var(--tblr-emphasis-color-rgb), .15);--tblr-navbar-toggler-border-radius: var(--tblr-border-radius);--tblr-navbar-toggler-focus-width: 0;--tblr-navbar-toggler-transition: box-shadow .15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--tblr-navbar-padding-y) var(--tblr-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-sm,.navbar>.container-md,.navbar>.container-lg,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--tblr-navbar-brand-padding-y);padding-bottom:var(--tblr-navbar-brand-padding-y);margin-right:var(--tblr-navbar-brand-margin-end);font-size:var(--tblr-navbar-brand-font-size);color:var(--tblr-navbar-brand-color);white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{color:var(--tblr-navbar-brand-hover-color);text-decoration:none}.navbar-nav{--tblr-nav-link-padding-x: 0;--tblr-nav-link-padding-y: .5rem;--tblr-nav-link-font-weight: ;--tblr-nav-link-color: var(--tblr-navbar-color);--tblr-nav-link-hover-color: var(--tblr-navbar-hover-color);--tblr-nav-link-disabled-color: var(--tblr-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--tblr-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--tblr-navbar-color)}.navbar-text a,.navbar-text a:hover,.navbar-text a:focus{color:var(--tblr-navbar-active-color)}.navbar-collapse{flex-grow:1;flex-basis:100%;align-items:center}.navbar-toggler{padding:var(--tblr-navbar-toggler-padding-y) var(--tblr-navbar-toggler-padding-x);font-size:var(--tblr-navbar-toggler-font-size);line-height:1;color:var(--tblr-navbar-color);background-color:transparent;border:var(--tblr-border-width) solid var(--tblr-navbar-toggler-border-color);border-radius:var(--tblr-navbar-toggler-border-radius);transition:var(--tblr-navbar-toggler-transition)}@media(prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--tblr-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--tblr-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--tblr-scroll-height, 75vh);overflow-y:auto}@media(min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media(min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--tblr-navbar-nav-link-padding-x);padding-left:var(--tblr-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark],body[data-bs-theme=dark] .navbar[data-bs-theme=light]{--tblr-navbar-color: rgba(255, 255, 255, .7);--tblr-navbar-hover-color: rgba(255, 255, 255, .75);--tblr-navbar-disabled-color: var(--tblr-disabled-color);--tblr-navbar-active-color: #ffffff;--tblr-navbar-brand-color: #ffffff;--tblr-navbar-brand-hover-color: #ffffff;--tblr-navbar-toggler-border-color: rgba(255, 255, 255, .1);--tblr-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.7%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon,body[data-bs-theme=dark] [data-bs-theme=light] .navbar-toggler-icon{--tblr-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.7%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--tblr-card-spacer-y: 1rem;--tblr-card-spacer-x: 1.25rem;--tblr-card-title-spacer-y: 1.25rem;--tblr-card-title-color: ;--tblr-card-subtitle-color: ;--tblr-card-border-width: var(--tblr-border-width);--tblr-card-border-color: var(--tblr-border-color-translucent);--tblr-card-border-radius: var(--tblr-border-radius-lg);--tblr-card-box-shadow: var(--tblr-shadow-card);--tblr-card-inner-border-radius: calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));--tblr-card-cap-padding-y: 1rem;--tblr-card-cap-padding-x: 1.25rem;--tblr-card-cap-bg: var(--tblr-bg-surface-tertiary);--tblr-card-cap-color: inherit;--tblr-card-height: ;--tblr-card-color: inherit;--tblr-card-bg: var(--tblr-bg-surface);--tblr-card-img-overlay-padding: 1rem;--tblr-card-group-margin: 1.5rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--tblr-card-height);color:var(--tblr-body-color);word-wrap:break-word;background-color:var(--tblr-card-bg);background-clip:border-box;border:var(--tblr-card-border-width) solid var(--tblr-card-border-color);border-radius:var(--tblr-card-border-radius);box-shadow:var(--tblr-card-box-shadow)}.card>hr,.card>.hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--tblr-card-inner-border-radius);border-top-right-radius:var(--tblr-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--tblr-card-inner-border-radius);border-bottom-left-radius:var(--tblr-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--tblr-card-spacer-y) var(--tblr-card-spacer-x);color:var(--tblr-card-color)}.card-title{margin-bottom:var(--tblr-card-title-spacer-y);color:var(--tblr-card-title-color)}.card-subtitle{margin-top:calc(-.5 * var(--tblr-card-title-spacer-y));margin-bottom:0;color:var(--tblr-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:var(--tblr-card-spacer-x)}.card-header{padding:var(--tblr-card-cap-padding-y) var(--tblr-card-cap-padding-x);margin-bottom:0;color:var(--tblr-card-cap-color);background-color:var(--tblr-card-cap-bg);border-bottom:var(--tblr-card-border-width) solid var(--tblr-card-border-color)}.card-header:first-child{border-radius:var(--tblr-card-inner-border-radius) var(--tblr-card-inner-border-radius) 0 0}.card-footer{padding:var(--tblr-card-cap-padding-y) var(--tblr-card-cap-padding-x);color:var(--tblr-card-cap-color);background-color:var(--tblr-card-cap-bg);border-top:var(--tblr-card-border-width) solid var(--tblr-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--tblr-card-inner-border-radius) var(--tblr-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--tblr-card-cap-padding-x));margin-bottom:calc(-1 * var(--tblr-card-cap-padding-y));margin-left:calc(-.5 * var(--tblr-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--tblr-card-bg);border-bottom-color:var(--tblr-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--tblr-card-cap-padding-x));margin-left:calc(-.5 * var(--tblr-card-cap-padding-x))}.card-img-overlay{position:absolute;inset:0;padding:var(--tblr-card-img-overlay-padding);border-radius:var(--tblr-card-inner-border-radius)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--tblr-card-inner-border-radius);border-top-right-radius:var(--tblr-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--tblr-card-inner-border-radius);border-bottom-left-radius:var(--tblr-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--tblr-card-group-margin)}@media(min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child)>.card-img-top,.card-group>.card:not(:last-child)>.card-header{border-top-right-radius:0}.card-group>.card:not(:last-child)>.card-img-bottom,.card-group>.card:not(:last-child)>.card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child)>.card-img-top,.card-group>.card:not(:first-child)>.card-header{border-top-left-radius:0}.card-group>.card:not(:first-child)>.card-img-bottom,.card-group>.card:not(:first-child)>.card-footer{border-bottom-left-radius:0}}.pagination{--tblr-pagination-padding-x: .25rem;--tblr-pagination-padding-y: calc(.25rem + 1px) ;--tblr-pagination-font-size: .875rem;--tblr-pagination-color: var(--tblr-body-color);--tblr-pagination-bg: transparent;--tblr-pagination-border-width: 1px;--tblr-pagination-border-color: transparent;--tblr-pagination-border-radius: var(--tblr-border-radius);--tblr-pagination-hover-color: var(--tblr-link-hover-color);--tblr-pagination-hover-bg: var(--tblr-active-bg);--tblr-pagination-hover-border-color: var(--tblr-pagination-border-color);--tblr-pagination-focus-color: var(--tblr-link-hover-color);--tblr-pagination-focus-bg: var(--tblr-secondary-bg);--tblr-pagination-focus-box-shadow: 0 0 0 .25rem rgba(var(--tblr-primary-rgb), .25);--tblr-pagination-active-color: #ffffff;--tblr-pagination-active-bg: var(--tblr-primary);--tblr-pagination-active-border-color: var(--tblr-primary);--tblr-pagination-disabled-color: var(--tblr-disabled-color);--tblr-pagination-disabled-bg: transparent;--tblr-pagination-disabled-border-color: var(--tblr-pagination-border-color);display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--tblr-pagination-padding-y) var(--tblr-pagination-padding-x);font-size:var(--tblr-pagination-font-size);color:var(--tblr-pagination-color);background-color:var(--tblr-pagination-bg);border:var(--tblr-pagination-border-width) solid var(--tblr-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--tblr-pagination-hover-color);text-decoration:none;background-color:var(--tblr-pagination-hover-bg);border-color:var(--tblr-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--tblr-pagination-focus-color);background-color:var(--tblr-pagination-focus-bg);outline:0;box-shadow:var(--tblr-pagination-focus-box-shadow)}.page-link.active,.active>.page-link{z-index:3;color:var(--tblr-pagination-active-color);background-color:var(--tblr-pagination-active-bg);border-color:var(--tblr-pagination-active-border-color)}.page-link.disabled,.disabled>.page-link{color:var(--tblr-pagination-disabled-color);pointer-events:none;background-color:var(--tblr-pagination-disabled-bg);border-color:var(--tblr-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item:first-child .page-link{border-top-left-radius:var(--tblr-pagination-border-radius);border-bottom-left-radius:var(--tblr-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--tblr-pagination-border-radius);border-bottom-right-radius:var(--tblr-pagination-border-radius)}.pagination-lg{--tblr-pagination-padding-x: 1.5rem;--tblr-pagination-padding-y: .75rem;--tblr-pagination-font-size: 1.09375rem;--tblr-pagination-border-radius: var(--tblr-border-radius-lg)}.pagination-sm{--tblr-pagination-padding-x: .5rem;--tblr-pagination-padding-y: .25rem;--tblr-pagination-font-size: .765625rem;--tblr-pagination-border-radius: var(--tblr-border-radius-sm)}@keyframes progress-bar-stripes{0%{background-position-x:var(--tblr-progress-height)}}.progress,.progress-stacked{--tblr-progress-height: .5rem;--tblr-progress-font-size: .65625rem;--tblr-progress-bg: var(--tblr-border-color);--tblr-progress-border-radius: var(--tblr-border-radius);--tblr-progress-box-shadow: var(--tblr-box-shadow-inset);--tblr-progress-bar-color: #ffffff;--tblr-progress-bar-bg: var(--tblr-primary);--tblr-progress-bar-transition: width .6s ease;display:flex;height:var(--tblr-progress-height);overflow:hidden;font-size:var(--tblr-progress-font-size);background-color:var(--tblr-progress-bg);border-radius:var(--tblr-progress-border-radius);box-shadow:var(--tblr-progress-box-shadow)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--tblr-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--tblr-progress-bar-bg);transition:var(--tblr-progress-bar-transition)}@media(prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--tblr-progress-height) var(--tblr-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--tblr-list-group-color: var(--tblr-body-color);--tblr-list-group-bg: inherit;--tblr-list-group-border-color: var(--tblr-border-color);--tblr-list-group-border-width: var(--tblr-border-width);--tblr-list-group-border-radius: var(--tblr-border-radius);--tblr-list-group-item-padding-x: 1.25rem;--tblr-list-group-item-padding-y: 1rem;--tblr-list-group-action-color: inherit;--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: rgba(var(--tblr-secondary-rgb), .08);--tblr-list-group-action-active-color: var(--tblr-body-color);--tblr-list-group-action-active-bg: var(--tblr-secondary-bg);--tblr-list-group-disabled-color: var(--tblr-secondary-color);--tblr-list-group-disabled-bg: inherit;--tblr-list-group-active-color: inherit;--tblr-list-group-active-bg: var(--tblr-active-bg);--tblr-list-group-active-border-color: var(--tblr-border-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--tblr-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item:before{content:counters(section,".") ". ";counter-increment:section}.list-group-item{position:relative;display:block;padding:var(--tblr-list-group-item-padding-y) var(--tblr-list-group-item-padding-x);color:var(--tblr-list-group-color);background-color:var(--tblr-list-group-bg);border:var(--tblr-list-group-border-width) solid var(--tblr-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--tblr-list-group-disabled-color);pointer-events:none;background-color:var(--tblr-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--tblr-list-group-active-color);background-color:var(--tblr-list-group-active-bg);border-color:var(--tblr-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--tblr-list-group-border-width));border-top-width:var(--tblr-list-group-border-width)}.list-group-item-action{width:100%;color:var(--tblr-list-group-action-color);text-align:inherit}.list-group-item-action:not(.active):hover,.list-group-item-action:not(.active):focus{z-index:1;color:var(--tblr-list-group-action-hover-color);text-decoration:none;background-color:var(--tblr-list-group-action-hover-bg)}.list-group-item-action:not(.active):active{color:var(--tblr-list-group-action-active-color);background-color:var(--tblr-list-group-action-active-bg)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}@media(min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}@media(min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--tblr-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--tblr-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--tblr-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--tblr-list-group-border-width));border-left-width:var(--tblr-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--tblr-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{--tblr-list-group-color: var(--tblr-primary-text-emphasis);--tblr-list-group-bg: var(--tblr-primary-bg-subtle);--tblr-list-group-border-color: var(--tblr-primary-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-primary-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-primary-border-subtle);--tblr-list-group-active-color: var(--tblr-primary-bg-subtle);--tblr-list-group-active-bg: var(--tblr-primary-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-primary-text-emphasis)}.list-group-item-secondary{--tblr-list-group-color: var(--tblr-secondary-text-emphasis);--tblr-list-group-bg: var(--tblr-secondary-bg-subtle);--tblr-list-group-border-color: var(--tblr-secondary-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-secondary-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-secondary-border-subtle);--tblr-list-group-active-color: var(--tblr-secondary-bg-subtle);--tblr-list-group-active-bg: var(--tblr-secondary-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-secondary-text-emphasis)}.list-group-item-success{--tblr-list-group-color: var(--tblr-success-text-emphasis);--tblr-list-group-bg: var(--tblr-success-bg-subtle);--tblr-list-group-border-color: var(--tblr-success-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-success-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-success-border-subtle);--tblr-list-group-active-color: var(--tblr-success-bg-subtle);--tblr-list-group-active-bg: var(--tblr-success-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-success-text-emphasis)}.list-group-item-info{--tblr-list-group-color: var(--tblr-info-text-emphasis);--tblr-list-group-bg: var(--tblr-info-bg-subtle);--tblr-list-group-border-color: var(--tblr-info-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-info-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-info-border-subtle);--tblr-list-group-active-color: var(--tblr-info-bg-subtle);--tblr-list-group-active-bg: var(--tblr-info-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-info-text-emphasis)}.list-group-item-warning{--tblr-list-group-color: var(--tblr-warning-text-emphasis);--tblr-list-group-bg: var(--tblr-warning-bg-subtle);--tblr-list-group-border-color: var(--tblr-warning-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-warning-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-warning-border-subtle);--tblr-list-group-active-color: var(--tblr-warning-bg-subtle);--tblr-list-group-active-bg: var(--tblr-warning-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-warning-text-emphasis)}.list-group-item-danger{--tblr-list-group-color: var(--tblr-danger-text-emphasis);--tblr-list-group-bg: var(--tblr-danger-bg-subtle);--tblr-list-group-border-color: var(--tblr-danger-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-danger-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-danger-border-subtle);--tblr-list-group-active-color: var(--tblr-danger-bg-subtle);--tblr-list-group-active-bg: var(--tblr-danger-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-danger-text-emphasis)}.list-group-item-light{--tblr-list-group-color: var(--tblr-light-text-emphasis);--tblr-list-group-bg: var(--tblr-light-bg-subtle);--tblr-list-group-border-color: var(--tblr-light-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-light-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-light-border-subtle);--tblr-list-group-active-color: var(--tblr-light-bg-subtle);--tblr-list-group-active-bg: var(--tblr-light-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-light-text-emphasis)}.list-group-item-dark{--tblr-list-group-color: var(--tblr-dark-text-emphasis);--tblr-list-group-bg: var(--tblr-dark-bg-subtle);--tblr-list-group-border-color: var(--tblr-dark-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-dark-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-dark-border-subtle);--tblr-list-group-active-color: var(--tblr-dark-bg-subtle);--tblr-list-group-active-bg: var(--tblr-dark-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-dark-text-emphasis)}.list-group-item-muted{--tblr-list-group-color: var(--tblr-muted-text-emphasis);--tblr-list-group-bg: var(--tblr-muted-bg-subtle);--tblr-list-group-border-color: var(--tblr-muted-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-muted-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-muted-border-subtle);--tblr-list-group-active-color: var(--tblr-muted-bg-subtle);--tblr-list-group-active-bg: var(--tblr-muted-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-muted-text-emphasis)}.list-group-item-blue{--tblr-list-group-color: var(--tblr-blue-text-emphasis);--tblr-list-group-bg: var(--tblr-blue-bg-subtle);--tblr-list-group-border-color: var(--tblr-blue-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-blue-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-blue-border-subtle);--tblr-list-group-active-color: var(--tblr-blue-bg-subtle);--tblr-list-group-active-bg: var(--tblr-blue-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-blue-text-emphasis)}.list-group-item-azure{--tblr-list-group-color: var(--tblr-azure-text-emphasis);--tblr-list-group-bg: var(--tblr-azure-bg-subtle);--tblr-list-group-border-color: var(--tblr-azure-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-azure-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-azure-border-subtle);--tblr-list-group-active-color: var(--tblr-azure-bg-subtle);--tblr-list-group-active-bg: var(--tblr-azure-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-azure-text-emphasis)}.list-group-item-indigo{--tblr-list-group-color: var(--tblr-indigo-text-emphasis);--tblr-list-group-bg: var(--tblr-indigo-bg-subtle);--tblr-list-group-border-color: var(--tblr-indigo-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-indigo-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-indigo-border-subtle);--tblr-list-group-active-color: var(--tblr-indigo-bg-subtle);--tblr-list-group-active-bg: var(--tblr-indigo-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-indigo-text-emphasis)}.list-group-item-purple{--tblr-list-group-color: var(--tblr-purple-text-emphasis);--tblr-list-group-bg: var(--tblr-purple-bg-subtle);--tblr-list-group-border-color: var(--tblr-purple-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-purple-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-purple-border-subtle);--tblr-list-group-active-color: var(--tblr-purple-bg-subtle);--tblr-list-group-active-bg: var(--tblr-purple-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-purple-text-emphasis)}.list-group-item-pink{--tblr-list-group-color: var(--tblr-pink-text-emphasis);--tblr-list-group-bg: var(--tblr-pink-bg-subtle);--tblr-list-group-border-color: var(--tblr-pink-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-pink-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-pink-border-subtle);--tblr-list-group-active-color: var(--tblr-pink-bg-subtle);--tblr-list-group-active-bg: var(--tblr-pink-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-pink-text-emphasis)}.list-group-item-red{--tblr-list-group-color: var(--tblr-red-text-emphasis);--tblr-list-group-bg: var(--tblr-red-bg-subtle);--tblr-list-group-border-color: var(--tblr-red-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-red-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-red-border-subtle);--tblr-list-group-active-color: var(--tblr-red-bg-subtle);--tblr-list-group-active-bg: var(--tblr-red-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-red-text-emphasis)}.list-group-item-orange{--tblr-list-group-color: var(--tblr-orange-text-emphasis);--tblr-list-group-bg: var(--tblr-orange-bg-subtle);--tblr-list-group-border-color: var(--tblr-orange-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-orange-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-orange-border-subtle);--tblr-list-group-active-color: var(--tblr-orange-bg-subtle);--tblr-list-group-active-bg: var(--tblr-orange-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-orange-text-emphasis)}.list-group-item-yellow{--tblr-list-group-color: var(--tblr-yellow-text-emphasis);--tblr-list-group-bg: var(--tblr-yellow-bg-subtle);--tblr-list-group-border-color: var(--tblr-yellow-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-yellow-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-yellow-border-subtle);--tblr-list-group-active-color: var(--tblr-yellow-bg-subtle);--tblr-list-group-active-bg: var(--tblr-yellow-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-yellow-text-emphasis)}.list-group-item-lime{--tblr-list-group-color: var(--tblr-lime-text-emphasis);--tblr-list-group-bg: var(--tblr-lime-bg-subtle);--tblr-list-group-border-color: var(--tblr-lime-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-lime-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-lime-border-subtle);--tblr-list-group-active-color: var(--tblr-lime-bg-subtle);--tblr-list-group-active-bg: var(--tblr-lime-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-lime-text-emphasis)}.list-group-item-green{--tblr-list-group-color: var(--tblr-green-text-emphasis);--tblr-list-group-bg: var(--tblr-green-bg-subtle);--tblr-list-group-border-color: var(--tblr-green-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-green-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-green-border-subtle);--tblr-list-group-active-color: var(--tblr-green-bg-subtle);--tblr-list-group-active-bg: var(--tblr-green-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-green-text-emphasis)}.list-group-item-teal{--tblr-list-group-color: var(--tblr-teal-text-emphasis);--tblr-list-group-bg: var(--tblr-teal-bg-subtle);--tblr-list-group-border-color: var(--tblr-teal-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-teal-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-teal-border-subtle);--tblr-list-group-active-color: var(--tblr-teal-bg-subtle);--tblr-list-group-active-bg: var(--tblr-teal-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-teal-text-emphasis)}.list-group-item-cyan{--tblr-list-group-color: var(--tblr-cyan-text-emphasis);--tblr-list-group-bg: var(--tblr-cyan-bg-subtle);--tblr-list-group-border-color: var(--tblr-cyan-border-subtle);--tblr-list-group-action-hover-color: var(--tblr-emphasis-color);--tblr-list-group-action-hover-bg: var(--tblr-cyan-border-subtle);--tblr-list-group-action-active-color: var(--tblr-emphasis-color);--tblr-list-group-action-active-bg: var(--tblr-cyan-border-subtle);--tblr-list-group-active-color: var(--tblr-cyan-bg-subtle);--tblr-list-group-active-bg: var(--tblr-cyan-text-emphasis);--tblr-list-group-active-border-color: var(--tblr-cyan-text-emphasis)}.toast{--tblr-toast-zindex: 1090;--tblr-toast-padding-x: .75rem;--tblr-toast-padding-y: .5rem;--tblr-toast-spacing: calc(var(--tblr-page-padding) * 2);--tblr-toast-max-width: 350px;--tblr-toast-font-size: .875rem;--tblr-toast-color: ;--tblr-toast-bg: var(--tblr-bg-surface);--tblr-toast-border-width: var(--tblr-border-width);--tblr-toast-border-color: var(--tblr-border-color);--tblr-toast-border-radius: var(--tblr-border-radius);--tblr-toast-box-shadow: var(--tblr-box-shadow);--tblr-toast-header-color: var(--tblr-gray-500);--tblr-toast-header-bg: rgba(var(--tblr-body-bg-rgb), .85);--tblr-toast-header-border-color: var(--tblr-border-color);width:var(--tblr-toast-max-width);max-width:100%;font-size:var(--tblr-toast-font-size);color:var(--tblr-toast-color);pointer-events:auto;background-color:var(--tblr-toast-bg);background-clip:padding-box;border:var(--tblr-toast-border-width) solid var(--tblr-toast-border-color);box-shadow:var(--tblr-toast-box-shadow);border-radius:var(--tblr-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--tblr-toast-zindex: 1090;position:absolute;z-index:var(--tblr-toast-zindex);width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--tblr-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--tblr-toast-padding-y) var(--tblr-toast-padding-x);color:var(--tblr-toast-header-color);background-color:var(--tblr-toast-header-bg);background-clip:padding-box;border-bottom:var(--tblr-toast-border-width) solid var(--tblr-toast-header-border-color);border-top-left-radius:calc(var(--tblr-toast-border-radius) - var(--tblr-toast-border-width));border-top-right-radius:calc(var(--tblr-toast-border-radius) - var(--tblr-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--tblr-toast-padding-x));margin-left:var(--tblr-toast-padding-x)}.toast-body{padding:var(--tblr-toast-padding-x);word-wrap:break-word}.modal{--tblr-modal-zindex: 1055;--tblr-modal-width: 540px;--tblr-modal-padding: 1.5rem;--tblr-modal-margin: .5rem;--tblr-modal-color: var(--tblr-body-color);--tblr-modal-bg: var(--tblr-bg-surface);--tblr-modal-border-color: transparent;--tblr-modal-border-width: var(--tblr-border-width);--tblr-modal-border-radius: var(--tblr-border-radius-lg);--tblr-modal-box-shadow: var(--tblr-box-shadow-sm);--tblr-modal-inner-border-radius: calc(var(--tblr-modal-border-radius) - 1px);--tblr-modal-header-padding-x: 1.5rem;--tblr-modal-header-padding-y: 1.5rem;--tblr-modal-header-padding: 1.5rem;--tblr-modal-header-border-color: var(--tblr-border-color);--tblr-modal-header-border-width: var(--tblr-border-width);--tblr-modal-title-line-height: 1.4285714286;--tblr-modal-footer-gap: .75rem;--tblr-modal-footer-bg: var(--tblr-bg-surface-tertiary);--tblr-modal-footer-border-color: var(--tblr-border-color);--tblr-modal-footer-border-width: var(--tblr-border-width);position:fixed;top:0;left:0;z-index:var(--tblr-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--tblr-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transform:translateY(-1rem);transition:transform .3s ease-out}@media(prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--tblr-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--tblr-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--tblr-modal-color);pointer-events:auto;background-color:var(--tblr-modal-bg);background-clip:padding-box;border:var(--tblr-modal-border-width) solid var(--tblr-modal-border-color);border-radius:var(--tblr-modal-border-radius);box-shadow:var(--tblr-modal-box-shadow);outline:0}.modal-backdrop{--tblr-backdrop-zindex: 1050;--tblr-backdrop-bg: var(--tblr-gray-800);--tblr-backdrop-opacity: .24;position:fixed;top:0;left:0;z-index:var(--tblr-backdrop-zindex);width:100vw;height:100vh;background-color:var(--tblr-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--tblr-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;padding:var(--tblr-modal-header-padding);border-bottom:var(--tblr-modal-header-border-width) solid var(--tblr-modal-header-border-color);border-top-left-radius:var(--tblr-modal-inner-border-radius);border-top-right-radius:var(--tblr-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--tblr-modal-header-padding-y) * .5) calc(var(--tblr-modal-header-padding-x) * .5);margin-top:calc(-.5 * var(--tblr-modal-header-padding-y));margin-right:calc(-.5 * var(--tblr-modal-header-padding-x));margin-bottom:calc(-.5 * var(--tblr-modal-header-padding-y));margin-left:auto}.modal-title{margin-bottom:0;line-height:var(--tblr-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--tblr-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--tblr-modal-padding) - var(--tblr-modal-footer-gap) * .5);background-color:var(--tblr-modal-footer-bg);border-top:var(--tblr-modal-footer-border-width) solid var(--tblr-modal-footer-border-color);border-bottom-right-radius:var(--tblr-modal-inner-border-radius);border-bottom-left-radius:var(--tblr-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--tblr-modal-footer-gap) * .5)}@media(min-width:576px){.modal{--tblr-modal-margin: 1.75rem;--tblr-modal-box-shadow: var(--tblr-box-shadow)}.modal-dialog{max-width:var(--tblr-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--tblr-modal-width: 380px}}@media(min-width:992px){.modal-lg,.modal-xl{--tblr-modal-width: 720px}}@media(min-width:1200px){.modal-xl{--tblr-modal-width: 1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header,.modal-fullscreen-sm-down .modal-footer{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header,.modal-fullscreen-md-down .modal-footer{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header,.modal-fullscreen-lg-down .modal-footer{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header,.modal-fullscreen-xl-down .modal-footer{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header,.modal-fullscreen-xxl-down .modal-footer{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--tblr-tooltip-zindex: 1080;--tblr-tooltip-max-width: 200px;--tblr-tooltip-padding-x: var(--tblr-spacer-3);--tblr-tooltip-padding-y: var(--tblr-spacer-1);--tblr-tooltip-margin: ;--tblr-tooltip-font-size: .765625rem;--tblr-tooltip-color: var(--tblr-text-inverted);--tblr-tooltip-bg: var(--tblr-bg-surface-inverted);--tblr-tooltip-border-radius: var(--tblr-border-radius);--tblr-tooltip-opacity: .9;--tblr-tooltip-arrow-width: .8rem;--tblr-tooltip-arrow-height: .4rem;z-index:var(--tblr-tooltip-zindex);display:block;margin:var(--tblr-tooltip-margin);font-family:var(--tblr-font-sans-serif);font-style:normal;font-weight:400;line-height:1.4285714286;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--tblr-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--tblr-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--tblr-tooltip-arrow-width);height:var(--tblr-tooltip-arrow-height)}.tooltip .tooltip-arrow:before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:calc(-1 * var(--tblr-tooltip-arrow-height))}.bs-tooltip-top .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow:before{top:-1px;border-width:var(--tblr-tooltip-arrow-height) calc(var(--tblr-tooltip-arrow-width) * .5) 0;border-top-color:var(--tblr-tooltip-bg)}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:calc(-1 * var(--tblr-tooltip-arrow-height));width:var(--tblr-tooltip-arrow-height);height:var(--tblr-tooltip-arrow-width)}.bs-tooltip-end .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow:before{right:-1px;border-width:calc(var(--tblr-tooltip-arrow-width) * .5) var(--tblr-tooltip-arrow-height) calc(var(--tblr-tooltip-arrow-width) * .5) 0;border-right-color:var(--tblr-tooltip-bg)}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:calc(-1 * var(--tblr-tooltip-arrow-height))}.bs-tooltip-bottom .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow:before{bottom:-1px;border-width:0 calc(var(--tblr-tooltip-arrow-width) * .5) var(--tblr-tooltip-arrow-height);border-bottom-color:var(--tblr-tooltip-bg)}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:calc(-1 * var(--tblr-tooltip-arrow-height));width:var(--tblr-tooltip-arrow-height);height:var(--tblr-tooltip-arrow-width)}.bs-tooltip-start .tooltip-arrow:before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow:before{left:-1px;border-width:calc(var(--tblr-tooltip-arrow-width) * .5) 0 calc(var(--tblr-tooltip-arrow-width) * .5) var(--tblr-tooltip-arrow-height);border-left-color:var(--tblr-tooltip-bg)}.tooltip-inner{max-width:var(--tblr-tooltip-max-width);padding:var(--tblr-tooltip-padding-y) var(--tblr-tooltip-padding-x);color:var(--tblr-tooltip-color);text-align:center;background-color:var(--tblr-tooltip-bg);border-radius:var(--tblr-tooltip-border-radius)}.popover{--tblr-popover-zindex: 1070;--tblr-popover-max-width: 276px;--tblr-popover-font-size: .765625rem;--tblr-popover-bg: var(--tblr-bg-surface);--tblr-popover-border-width: var(--tblr-border-width);--tblr-popover-border-color: var(--tblr-border-color);--tblr-popover-border-radius: var(--tblr-border-radius-lg);--tblr-popover-inner-border-radius: calc(var(--tblr-border-radius-lg) - var(--tblr-border-width));--tblr-popover-box-shadow: var(--tblr-shadow-lg);--tblr-popover-header-padding-x: 1rem;--tblr-popover-header-padding-y: .5rem;--tblr-popover-header-font-size: .875rem;--tblr-popover-header-color: inherit;--tblr-popover-header-bg: transparent;--tblr-popover-body-padding-x: .5rem;--tblr-popover-body-padding-y: .5rem;--tblr-popover-body-color: inherit;--tblr-popover-arrow-width: 1rem;--tblr-popover-arrow-height: .5rem;--tblr-popover-arrow-border: var(--tblr-popover-border-color);z-index:var(--tblr-popover-zindex);display:block;max-width:var(--tblr-popover-max-width);font-family:var(--tblr-font-sans-serif);font-style:normal;font-weight:400;line-height:1.4285714286;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--tblr-popover-font-size);word-wrap:break-word;background-color:var(--tblr-popover-bg);background-clip:padding-box;border:var(--tblr-popover-border-width) solid var(--tblr-popover-border-color);border-radius:var(--tblr-popover-border-radius);box-shadow:var(--tblr-popover-box-shadow)}.popover .popover-arrow{display:block;width:var(--tblr-popover-arrow-width);height:var(--tblr-popover-arrow-height)}.popover .popover-arrow:before,.popover .popover-arrow:after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width))}.bs-popover-top>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before,.bs-popover-top>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after{border-width:var(--tblr-popover-arrow-height) calc(var(--tblr-popover-arrow-width) * .5) 0}.bs-popover-top>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before{bottom:0;border-top-color:var(--tblr-popover-arrow-border)}.bs-popover-top>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after{bottom:var(--tblr-popover-border-width);border-top-color:var(--tblr-popover-bg)}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width));width:var(--tblr-popover-arrow-height);height:var(--tblr-popover-arrow-width)}.bs-popover-end>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before,.bs-popover-end>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after{border-width:calc(var(--tblr-popover-arrow-width) * .5) var(--tblr-popover-arrow-height) calc(var(--tblr-popover-arrow-width) * .5) 0}.bs-popover-end>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before{left:0;border-right-color:var(--tblr-popover-arrow-border)}.bs-popover-end>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after{left:var(--tblr-popover-border-width);border-right-color:var(--tblr-popover-bg)}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width))}.bs-popover-bottom>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before,.bs-popover-bottom>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after{border-width:0 calc(var(--tblr-popover-arrow-width) * .5) var(--tblr-popover-arrow-height)}.bs-popover-bottom>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before{top:0;border-bottom-color:var(--tblr-popover-arrow-border)}.bs-popover-bottom>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after{top:var(--tblr-popover-border-width);border-bottom-color:var(--tblr-popover-bg)}.bs-popover-bottom .popover-header:before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header:before{position:absolute;top:0;left:50%;display:block;width:var(--tblr-popover-arrow-width);margin-left:calc(-.5 * var(--tblr-popover-arrow-width));content:"";border-bottom:var(--tblr-popover-border-width) solid var(--tblr-popover-header-bg)}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-1 * (var(--tblr-popover-arrow-height)) - var(--tblr-popover-border-width));width:var(--tblr-popover-arrow-height);height:var(--tblr-popover-arrow-width)}.bs-popover-start>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before,.bs-popover-start>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after{border-width:calc(var(--tblr-popover-arrow-width) * .5) 0 calc(var(--tblr-popover-arrow-width) * .5) var(--tblr-popover-arrow-height)}.bs-popover-start>.popover-arrow:before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before{right:0;border-left-color:var(--tblr-popover-arrow-border)}.bs-popover-start>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after{right:var(--tblr-popover-border-width);border-left-color:var(--tblr-popover-bg)}.popover-header{padding:var(--tblr-popover-header-padding-y) var(--tblr-popover-header-padding-x);margin-bottom:0;font-size:var(--tblr-popover-header-font-size);color:var(--tblr-popover-header-color);background-color:var(--tblr-popover-header-bg);border-bottom:var(--tblr-popover-border-width) solid var(--tblr-popover-border-color);border-top-left-radius:var(--tblr-popover-inner-border-radius);border-top-right-radius:var(--tblr-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--tblr-popover-body-padding-y) var(--tblr-popover-body-padding-x);color:var(--tblr-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner:after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translate(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translate(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;filter:var(--tblr-carousel-control-icon-filter);border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion:reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:1.5rem;height:1.5rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='15 18 9 12 15 6'%3e%3c/polyline%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='9 18 15 12 9 6'%3e%3c/polyline%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:var(--tblr-carousel-indicator-active-bg);background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:var(--tblr-carousel-caption-color);text-align:center}.carousel-dark{--tblr-carousel-indicator-active-bg: #000000;--tblr-carousel-caption-color: #000000;--tblr-carousel-control-icon-filter: invert(1) grayscale(100)}:root,[data-bs-theme=light]{--tblr-carousel-indicator-active-bg: #ffffff;--tblr-carousel-caption-color: #ffffff;--tblr-carousel-control-icon-filter: }[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{--tblr-carousel-indicator-active-bg: #000000;--tblr-carousel-caption-color: #000000;--tblr-carousel-control-icon-filter: invert(1) grayscale(100)}.spinner-grow,.spinner-border{display:inline-block;flex-shrink:0;width:var(--tblr-spinner-width);height:var(--tblr-spinner-height);vertical-align:var(--tblr-spinner-vertical-align);border-radius:50%;animation:var(--tblr-spinner-animation-speed) linear infinite var(--tblr-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--tblr-spinner-width: 1.5rem;--tblr-spinner-height: 1.5rem;--tblr-spinner-vertical-align: -.125em;--tblr-spinner-border-width: 2px;--tblr-spinner-animation-speed: .75s;--tblr-spinner-animation-name: spinner-border;border:var(--tblr-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--tblr-spinner-width: 1rem;--tblr-spinner-height: 1rem;--tblr-spinner-border-width: 1px}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--tblr-spinner-width: 1.5rem;--tblr-spinner-height: 1.5rem;--tblr-spinner-vertical-align: -.125em;--tblr-spinner-animation-speed: .75s;--tblr-spinner-animation-name: spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--tblr-spinner-width: 1rem;--tblr-spinner-height: 1rem}@media(prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--tblr-spinner-animation-speed: 1.5s}}.offcanvas,.offcanvas-xxl,.offcanvas-xl,.offcanvas-lg,.offcanvas-md,.offcanvas-sm{--tblr-offcanvas-zindex: 1045;--tblr-offcanvas-width: 400px;--tblr-offcanvas-height: 30vh;--tblr-offcanvas-padding-x: 1.5rem;--tblr-offcanvas-padding-y: 1.5rem;--tblr-offcanvas-color: var(--tblr-body-color);--tblr-offcanvas-bg: var(--tblr-bg-surface);--tblr-offcanvas-border-width: var(--tblr-border-width);--tblr-offcanvas-border-color: var(--tblr-border-color);--tblr-offcanvas-box-shadow: var(--tblr-box-shadow-sm);--tblr-offcanvas-transition: transform .3s ease-in-out;--tblr-offcanvas-title-line-height: 1.4285714286}@media(max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:575.98px)and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media(max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.showing,.offcanvas-sm.show:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show{visibility:visible}}@media(min-width:576px){.offcanvas-sm{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:767.98px)and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media(max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.showing,.offcanvas-md.show:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show{visibility:visible}}@media(min-width:768px){.offcanvas-md{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:991.98px)and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media(max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.showing,.offcanvas-lg.show:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show{visibility:visible}}@media(min-width:992px){.offcanvas-lg{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:1199.98px)and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media(max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.showing,.offcanvas-xl.show:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show{visibility:visible}}@media(min-width:1200px){.offcanvas-xl{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media(max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}}@media(max-width:1399.98px)and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media(max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.showing,.offcanvas-xxl.show:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show{visibility:visible}}@media(min-width:1400px){.offcanvas-xxl{--tblr-offcanvas-height: auto;--tblr-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--tblr-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--tblr-offcanvas-color);visibility:hidden;background-color:var(--tblr-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--tblr-offcanvas-box-shadow);transition:var(--tblr-offcanvas-transition)}@media(prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--tblr-offcanvas-width);border-right:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--tblr-offcanvas-width);border-left:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translate(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-bottom:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--tblr-offcanvas-height);max-height:100%;border-top:var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);transform:translateY(100%)}.offcanvas.showing,.offcanvas.show:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:var(--tblr-gray-800)}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.24}.offcanvas-header{display:flex;align-items:center;padding:var(--tblr-offcanvas-padding-y) var(--tblr-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--tblr-offcanvas-padding-y) * .5) calc(var(--tblr-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--tblr-offcanvas-padding-y));margin-right:calc(-.5 * var(--tblr-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--tblr-offcanvas-padding-y));margin-left:auto}.offcanvas-title{margin-bottom:0;line-height:var(--tblr-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;padding:var(--tblr-offcanvas-padding-y) var(--tblr-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.2}.placeholder.btn:before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.1}}.placeholder-wave{mask-image:linear-gradient(130deg,#000 55%,#000000e6,#000 95%);mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{to{mask-position:-200% 0%}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.object-fit-contain{object-fit:contain!important}.object-fit-cover{object-fit:cover!important}.object-fit-fill{object-fit:fill!important}.object-fit-scale{object-fit:scale-down!important}.object-fit-none{object-fit:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:var(--tblr-box-shadow)!important}.shadow-sm{box-shadow:var(--tblr-box-shadow-sm)!important}.shadow-lg{box-shadow:var(--tblr-box-shadow-lg)!important}.shadow-none{box-shadow:none!important}.focus-ring-primary{--tblr-focus-ring-color: rgba(var(--tblr-primary-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-secondary{--tblr-focus-ring-color: rgba(var(--tblr-secondary-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-success{--tblr-focus-ring-color: rgba(var(--tblr-success-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-info{--tblr-focus-ring-color: rgba(var(--tblr-info-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-warning{--tblr-focus-ring-color: rgba(var(--tblr-warning-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-danger{--tblr-focus-ring-color: rgba(var(--tblr-danger-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-light{--tblr-focus-ring-color: rgba(var(--tblr-light-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-dark{--tblr-focus-ring-color: rgba(var(--tblr-dark-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-muted{--tblr-focus-ring-color: rgba(var(--tblr-muted-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-blue{--tblr-focus-ring-color: rgba(var(--tblr-blue-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-azure{--tblr-focus-ring-color: rgba(var(--tblr-azure-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-indigo{--tblr-focus-ring-color: rgba(var(--tblr-indigo-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-purple{--tblr-focus-ring-color: rgba(var(--tblr-purple-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-pink{--tblr-focus-ring-color: rgba(var(--tblr-pink-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-red{--tblr-focus-ring-color: rgba(var(--tblr-red-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-orange{--tblr-focus-ring-color: rgba(var(--tblr-orange-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-yellow{--tblr-focus-ring-color: rgba(var(--tblr-yellow-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-lime{--tblr-focus-ring-color: rgba(var(--tblr-lime-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-green{--tblr-focus-ring-color: rgba(var(--tblr-green-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-teal{--tblr-focus-ring-color: rgba(var(--tblr-teal-rgb), var(--tblr-focus-ring-opacity))}.focus-ring-cyan{--tblr-focus-ring-color: rgba(var(--tblr-cyan-rgb), var(--tblr-focus-ring-opacity))}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translate(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-wide{border:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-0{border:0!important}.border-top{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-top-wide{border-top:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-end-wide{border-right:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-bottom-wide{border-bottom:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-start-wide{border-left:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-start-0{border-left:0!important}.border-red{--tblr-border-opacity: 1;border-color:rgba(var(--tblr-red-rgb),var(--tblr-border-opacity))!important}.border-green{--tblr-border-opacity: 1;border-color:rgba(var(--tblr-green-rgb),var(--tblr-border-opacity))!important}.border-primary-subtle{border-color:var(--tblr-primary-border-subtle)!important}.border-secondary-subtle{border-color:var(--tblr-secondary-border-subtle)!important}.border-success-subtle{border-color:var(--tblr-success-border-subtle)!important}.border-info-subtle{border-color:var(--tblr-info-border-subtle)!important}.border-warning-subtle{border-color:var(--tblr-warning-border-subtle)!important}.border-danger-subtle{border-color:var(--tblr-danger-border-subtle)!important}.border-light-subtle{border-color:var(--tblr-light-border-subtle)!important}.border-dark-subtle{border-color:var(--tblr-dark-border-subtle)!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.border-opacity-10{--tblr-border-opacity: .1}.border-opacity-25{--tblr-border-opacity: .25}.border-opacity-50{--tblr-border-opacity: .5}.border-opacity-75{--tblr-border-opacity: .75}.border-opacity-100{--tblr-border-opacity: 1}.w-25{width:25%!important}.w-33{width:33.33333%!important}.w-50{width:50%!important}.w-66{width:66.66666%!important}.w-75{width:75%!important}.w-100{width:100%!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-33{height:33.33333%!important}.h-50{height:50%!important}.h-66{height:66.66666%!important}.h-75{height:75%!important}.h-100{height:100%!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:2rem!important}.m-6{margin:2.5rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:2rem!important;margin-left:2rem!important}.mx-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:2rem!important}.mt-6{margin-top:2.5rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:2rem!important}.me-6{margin-right:2.5rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:2rem!important}.mb-6{margin-bottom:2.5rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:2rem!important}.ms-6{margin-left:2.5rem!important}.ms-auto{margin-left:auto!important}.m-n1{margin:-.25rem!important}.m-n2{margin:-.5rem!important}.m-n3{margin:-1rem!important}.m-n4{margin:-1.5rem!important}.m-n5{margin:-2rem!important}.m-n6{margin:-2.5rem!important}.mx-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-n1{margin-top:-.25rem!important}.mt-n2{margin-top:-.5rem!important}.mt-n3{margin-top:-1rem!important}.mt-n4{margin-top:-1.5rem!important}.mt-n5{margin-top:-2rem!important}.mt-n6{margin-top:-2.5rem!important}.me-n1{margin-right:-.25rem!important}.me-n2{margin-right:-.5rem!important}.me-n3{margin-right:-1rem!important}.me-n4{margin-right:-1.5rem!important}.me-n5{margin-right:-2rem!important}.me-n6{margin-right:-2.5rem!important}.mb-n1{margin-bottom:-.25rem!important}.mb-n2{margin-bottom:-.5rem!important}.mb-n3{margin-bottom:-1rem!important}.mb-n4{margin-bottom:-1.5rem!important}.mb-n5{margin-bottom:-2rem!important}.mb-n6{margin-bottom:-2.5rem!important}.ms-n1{margin-left:-.25rem!important}.ms-n2{margin-left:-.5rem!important}.ms-n3{margin-left:-1rem!important}.ms-n4{margin-left:-1.5rem!important}.ms-n5{margin-left:-2rem!important}.ms-n6{margin-left:-2.5rem!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:2rem!important}.p-6{padding:2.5rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:2rem!important;padding-left:2rem!important}.px-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:2rem!important}.pt-6{padding-top:2.5rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:2rem!important}.pe-6{padding-right:2.5rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:2rem!important}.pb-6{padding-bottom:2.5rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:2rem!important}.ps-6{padding-left:2.5rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:2rem!important}.gap-6{gap:2.5rem!important}.row-gap-0{row-gap:0!important}.row-gap-1{row-gap:.25rem!important}.row-gap-2{row-gap:.5rem!important}.row-gap-3{row-gap:1rem!important}.row-gap-4{row-gap:1.5rem!important}.row-gap-5{row-gap:2rem!important}.row-gap-6{row-gap:2.5rem!important}.column-gap-0{column-gap:0!important}.column-gap-1{column-gap:.25rem!important}.column-gap-2{column-gap:.5rem!important}.column-gap-3{column-gap:1rem!important}.column-gap-4{column-gap:1.5rem!important}.column-gap-5{column-gap:2rem!important}.column-gap-6{column-gap:2.5rem!important}.font-monospace{font-family:var(--tblr-font-monospace)!important}.fs-1{font-size:1.5rem!important}.fs-2{font-size:1.25rem!important}.fs-3{font-size:1rem!important}.fs-4{font-size:.875rem!important}.fs-5{font-size:.75rem!important}.fs-6{font-size:.625rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-lighter{font-weight:lighter!important}.fw-light{font-weight:300!important}.fw-normal{font-weight:400!important}.fw-medium{font-weight:500!important}.fw-semibold,.fw-bold{font-weight:600!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.1428571429!important}.lh-base{line-height:1.4285714286!important}.lh-lg{line-height:1.7142857143!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--tblr-text-opacity: 1;color:rgba(var(--tblr-primary-rgb),var(--tblr-text-opacity))!important}.text-secondary{--tblr-text-opacity: 1;color:rgba(var(--tblr-secondary-rgb),var(--tblr-text-opacity))!important}.text-success{--tblr-text-opacity: 1;color:rgba(var(--tblr-success-rgb),var(--tblr-text-opacity))!important}.text-info{--tblr-text-opacity: 1;color:rgba(var(--tblr-info-rgb),var(--tblr-text-opacity))!important}.text-warning{--tblr-text-opacity: 1;color:rgba(var(--tblr-warning-rgb),var(--tblr-text-opacity))!important}.text-danger{--tblr-text-opacity: 1;color:rgba(var(--tblr-danger-rgb),var(--tblr-text-opacity))!important}.text-light{--tblr-text-opacity: 1;color:rgba(var(--tblr-light-rgb),var(--tblr-text-opacity))!important}.text-dark{--tblr-text-opacity: 1;color:rgba(var(--tblr-dark-rgb),var(--tblr-text-opacity))!important}.text-muted{--tblr-text-opacity: 1;color:var(--tblr-secondary-color)!important}.text-blue{--tblr-text-opacity: 1;color:rgba(var(--tblr-blue-rgb),var(--tblr-text-opacity))!important}.text-azure{--tblr-text-opacity: 1;color:rgba(var(--tblr-azure-rgb),var(--tblr-text-opacity))!important}.text-indigo{--tblr-text-opacity: 1;color:rgba(var(--tblr-indigo-rgb),var(--tblr-text-opacity))!important}.text-purple{--tblr-text-opacity: 1;color:rgba(var(--tblr-purple-rgb),var(--tblr-text-opacity))!important}.text-pink{--tblr-text-opacity: 1;color:rgba(var(--tblr-pink-rgb),var(--tblr-text-opacity))!important}.text-red{--tblr-text-opacity: 1;color:rgba(var(--tblr-red-rgb),var(--tblr-text-opacity))!important}.text-orange{--tblr-text-opacity: 1;color:rgba(var(--tblr-orange-rgb),var(--tblr-text-opacity))!important}.text-yellow{--tblr-text-opacity: 1;color:rgba(var(--tblr-yellow-rgb),var(--tblr-text-opacity))!important}.text-lime{--tblr-text-opacity: 1;color:rgba(var(--tblr-lime-rgb),var(--tblr-text-opacity))!important}.text-green{--tblr-text-opacity: 1;color:rgba(var(--tblr-green-rgb),var(--tblr-text-opacity))!important}.text-teal{--tblr-text-opacity: 1;color:rgba(var(--tblr-teal-rgb),var(--tblr-text-opacity))!important}.text-cyan{--tblr-text-opacity: 1;color:rgba(var(--tblr-cyan-rgb),var(--tblr-text-opacity))!important}.text-black{--tblr-text-opacity: 1;color:rgba(var(--tblr-black-rgb),var(--tblr-text-opacity))!important}.text-white{--tblr-text-opacity: 1;color:rgba(var(--tblr-white-rgb),var(--tblr-text-opacity))!important}.text-body{--tblr-text-opacity: 1;color:rgba(var(--tblr-body-color-rgb),var(--tblr-text-opacity))!important}.text-black-50{--tblr-text-opacity: 1;color:#00000080!important}.text-white-50{--tblr-text-opacity: 1;color:#ffffff80!important}.text-body-secondary{--tblr-text-opacity: 1;color:var(--tblr-secondary-color)!important}.text-body-tertiary{--tblr-text-opacity: 1;color:var(--tblr-tertiary-color)!important}.text-body-emphasis{--tblr-text-opacity: 1;color:var(--tblr-emphasis-color)!important}.text-reset{--tblr-text-opacity: 1;color:inherit!important}.text-opacity-25{--tblr-text-opacity: .25}.text-opacity-50{--tblr-text-opacity: .5}.text-opacity-75{--tblr-text-opacity: .75}.text-opacity-100{--tblr-text-opacity: 1}.text-primary-emphasis{color:var(--tblr-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--tblr-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--tblr-success-text-emphasis)!important}.text-info-emphasis{color:var(--tblr-info-text-emphasis)!important}.text-warning-emphasis{color:var(--tblr-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--tblr-danger-text-emphasis)!important}.text-light-emphasis{color:var(--tblr-light-text-emphasis)!important}.text-dark-emphasis{color:var(--tblr-dark-text-emphasis)!important}.link-opacity-10,.link-opacity-10-hover:hover{--tblr-link-opacity: .1}.link-opacity-25,.link-opacity-25-hover:hover{--tblr-link-opacity: .25}.link-opacity-50,.link-opacity-50-hover:hover{--tblr-link-opacity: .5}.link-opacity-75,.link-opacity-75-hover:hover{--tblr-link-opacity: .75}.link-opacity-100,.link-opacity-100-hover:hover{--tblr-link-opacity: 1}.link-offset-1,.link-offset-1-hover:hover{text-underline-offset:.125em!important}.link-offset-2,.link-offset-2-hover:hover{text-underline-offset:.25em!important}.link-offset-3,.link-offset-3-hover:hover{text-underline-offset:.375em!important}.link-underline-primary{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-primary-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-secondary{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-secondary-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-success{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-success-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-info{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-info-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-warning{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-warning-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-danger{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-danger-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-light{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-light-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-dark{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-dark-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-muted{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-muted-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-blue{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-blue-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-azure{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-azure-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-indigo{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-indigo-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-purple{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-purple-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-pink{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-pink-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-red{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-red-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-orange{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-orange-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-yellow{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-yellow-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-lime{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-lime-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-green{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-green-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-teal{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-teal-rgb),var(--tblr-link-underline-opacity))!important}.link-underline-cyan{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-cyan-rgb),var(--tblr-link-underline-opacity))!important}.link-underline{--tblr-link-underline-opacity: 1;text-decoration-color:rgba(var(--tblr-link-color-rgb),var(--tblr-link-underline-opacity, 1))!important}.link-underline-opacity-0,.link-underline-opacity-0-hover:hover{--tblr-link-underline-opacity: 0}.link-underline-opacity-10,.link-underline-opacity-10-hover:hover{--tblr-link-underline-opacity: .1}.link-underline-opacity-25,.link-underline-opacity-25-hover:hover{--tblr-link-underline-opacity: .25}.link-underline-opacity-50,.link-underline-opacity-50-hover:hover{--tblr-link-underline-opacity: .5}.link-underline-opacity-75,.link-underline-opacity-75-hover:hover{--tblr-link-underline-opacity: .75}.link-underline-opacity-100,.link-underline-opacity-100-hover:hover{--tblr-link-underline-opacity: 1}.bg-primary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-primary-rgb),var(--tblr-bg-opacity))!important}.bg-secondary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-secondary-rgb),var(--tblr-bg-opacity))!important}.bg-success{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-success-rgb),var(--tblr-bg-opacity))!important}.bg-info{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-info-rgb),var(--tblr-bg-opacity))!important}.bg-warning{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-warning-rgb),var(--tblr-bg-opacity))!important}.bg-danger{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-danger-rgb),var(--tblr-bg-opacity))!important}.bg-light{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-light-rgb),var(--tblr-bg-opacity))!important}.bg-dark{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-dark-rgb),var(--tblr-bg-opacity))!important}.bg-muted{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-muted-rgb),var(--tblr-bg-opacity))!important}.bg-blue{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-blue-rgb),var(--tblr-bg-opacity))!important}.bg-azure{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-azure-rgb),var(--tblr-bg-opacity))!important}.bg-indigo{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-indigo-rgb),var(--tblr-bg-opacity))!important}.bg-purple{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-purple-rgb),var(--tblr-bg-opacity))!important}.bg-pink{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-pink-rgb),var(--tblr-bg-opacity))!important}.bg-red{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-red-rgb),var(--tblr-bg-opacity))!important}.bg-orange{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-orange-rgb),var(--tblr-bg-opacity))!important}.bg-yellow{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-yellow-rgb),var(--tblr-bg-opacity))!important}.bg-lime{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-lime-rgb),var(--tblr-bg-opacity))!important}.bg-green{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-green-rgb),var(--tblr-bg-opacity))!important}.bg-teal{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-teal-rgb),var(--tblr-bg-opacity))!important}.bg-cyan{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-cyan-rgb),var(--tblr-bg-opacity))!important}.bg-black{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-black-rgb),var(--tblr-bg-opacity))!important}.bg-white{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-white-rgb),var(--tblr-bg-opacity))!important}.bg-body{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-body-bg-rgb),var(--tblr-bg-opacity))!important}.bg-transparent{--tblr-bg-opacity: 1;background-color:transparent!important}.bg-body-secondary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-secondary-bg-rgb),var(--tblr-bg-opacity))!important}.bg-body-tertiary{--tblr-bg-opacity: 1;background-color:rgba(var(--tblr-tertiary-bg-rgb),var(--tblr-bg-opacity))!important}.bg-opacity-10{--tblr-bg-opacity: .1}.bg-opacity-25{--tblr-bg-opacity: .25}.bg-opacity-50{--tblr-bg-opacity: .5}.bg-opacity-75{--tblr-bg-opacity: .75}.bg-opacity-100{--tblr-bg-opacity: 1}.bg-primary-subtle{background-color:var(--tblr-primary-bg-subtle)!important}.bg-secondary-subtle{background-color:var(--tblr-secondary-bg-subtle)!important}.bg-success-subtle{background-color:var(--tblr-success-bg-subtle)!important}.bg-info-subtle{background-color:var(--tblr-info-bg-subtle)!important}.bg-warning-subtle{background-color:var(--tblr-warning-bg-subtle)!important}.bg-danger-subtle{background-color:var(--tblr-danger-bg-subtle)!important}.bg-light-subtle{background-color:var(--tblr-light-bg-subtle)!important}.bg-dark-subtle{background-color:var(--tblr-dark-bg-subtle)!important}.bg-gradient{background-image:var(--tblr-gradient)!important}.user-select-all{user-select:all!important}.user-select-auto{user-select:auto!important}.user-select-none{user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--tblr-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--tblr-border-radius-sm)!important}.rounded-2{border-radius:var(--tblr-border-radius)!important}.rounded-3{border-radius:var(--tblr-border-radius-lg)!important}.rounded-4{border-radius:var(--tblr-border-radius-xl)!important}.rounded-5{border-radius:var(--tblr-border-radius-xxl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--tblr-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--tblr-border-radius)!important;border-top-right-radius:var(--tblr-border-radius)!important}.rounded-top-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-top-1{border-top-left-radius:var(--tblr-border-radius-sm)!important;border-top-right-radius:var(--tblr-border-radius-sm)!important}.rounded-top-2{border-top-left-radius:var(--tblr-border-radius)!important;border-top-right-radius:var(--tblr-border-radius)!important}.rounded-top-3{border-top-left-radius:var(--tblr-border-radius-lg)!important;border-top-right-radius:var(--tblr-border-radius-lg)!important}.rounded-top-4{border-top-left-radius:var(--tblr-border-radius-xl)!important;border-top-right-radius:var(--tblr-border-radius-xl)!important}.rounded-top-5{border-top-left-radius:var(--tblr-border-radius-xxl)!important;border-top-right-radius:var(--tblr-border-radius-xxl)!important}.rounded-top-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-top-pill{border-top-left-radius:var(--tblr-border-radius-pill)!important;border-top-right-radius:var(--tblr-border-radius-pill)!important}.rounded-end{border-top-right-radius:var(--tblr-border-radius)!important;border-bottom-right-radius:var(--tblr-border-radius)!important}.rounded-end-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-end-1{border-top-right-radius:var(--tblr-border-radius-sm)!important;border-bottom-right-radius:var(--tblr-border-radius-sm)!important}.rounded-end-2{border-top-right-radius:var(--tblr-border-radius)!important;border-bottom-right-radius:var(--tblr-border-radius)!important}.rounded-end-3{border-top-right-radius:var(--tblr-border-radius-lg)!important;border-bottom-right-radius:var(--tblr-border-radius-lg)!important}.rounded-end-4{border-top-right-radius:var(--tblr-border-radius-xl)!important;border-bottom-right-radius:var(--tblr-border-radius-xl)!important}.rounded-end-5{border-top-right-radius:var(--tblr-border-radius-xxl)!important;border-bottom-right-radius:var(--tblr-border-radius-xxl)!important}.rounded-end-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-end-pill{border-top-right-radius:var(--tblr-border-radius-pill)!important;border-bottom-right-radius:var(--tblr-border-radius-pill)!important}.rounded-bottom{border-bottom-right-radius:var(--tblr-border-radius)!important;border-bottom-left-radius:var(--tblr-border-radius)!important}.rounded-bottom-0{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-bottom-1{border-bottom-right-radius:var(--tblr-border-radius-sm)!important;border-bottom-left-radius:var(--tblr-border-radius-sm)!important}.rounded-bottom-2{border-bottom-right-radius:var(--tblr-border-radius)!important;border-bottom-left-radius:var(--tblr-border-radius)!important}.rounded-bottom-3{border-bottom-right-radius:var(--tblr-border-radius-lg)!important;border-bottom-left-radius:var(--tblr-border-radius-lg)!important}.rounded-bottom-4{border-bottom-right-radius:var(--tblr-border-radius-xl)!important;border-bottom-left-radius:var(--tblr-border-radius-xl)!important}.rounded-bottom-5{border-bottom-right-radius:var(--tblr-border-radius-xxl)!important;border-bottom-left-radius:var(--tblr-border-radius-xxl)!important}.rounded-bottom-circle{border-bottom-right-radius:50%!important;border-bottom-left-radius:50%!important}.rounded-bottom-pill{border-bottom-right-radius:var(--tblr-border-radius-pill)!important;border-bottom-left-radius:var(--tblr-border-radius-pill)!important}.rounded-start{border-bottom-left-radius:var(--tblr-border-radius)!important;border-top-left-radius:var(--tblr-border-radius)!important}.rounded-start-0{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.rounded-start-1{border-bottom-left-radius:var(--tblr-border-radius-sm)!important;border-top-left-radius:var(--tblr-border-radius-sm)!important}.rounded-start-2{border-bottom-left-radius:var(--tblr-border-radius)!important;border-top-left-radius:var(--tblr-border-radius)!important}.rounded-start-3{border-bottom-left-radius:var(--tblr-border-radius-lg)!important;border-top-left-radius:var(--tblr-border-radius-lg)!important}.rounded-start-4{border-bottom-left-radius:var(--tblr-border-radius-xl)!important;border-top-left-radius:var(--tblr-border-radius-xl)!important}.rounded-start-5{border-bottom-left-radius:var(--tblr-border-radius-xxl)!important;border-top-left-radius:var(--tblr-border-radius-xxl)!important}.rounded-start-circle{border-bottom-left-radius:50%!important;border-top-left-radius:50%!important}.rounded-start-pill{border-bottom-left-radius:var(--tblr-border-radius-pill)!important;border-top-left-radius:var(--tblr-border-radius-pill)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-n1{z-index:-1!important}.z-0{z-index:0!important}.z-1{z-index:1!important}.z-2{z-index:2!important}.z-3{z-index:3!important}.object-contain{object-fit:contain!important}.object-cover{object-fit:cover!important}.object-fill{object-fit:fill!important}.object-scale-down{object-fit:scale-down!important}.object-none{object-fit:none!important}.cursor-auto{cursor:auto!important}.cursor-pointer{cursor:pointer!important}.cursor-move{cursor:move!important}.cursor-not-allowed{cursor:not-allowed!important}.cursor-zoom-in{cursor:zoom-in!important}.cursor-zoom-out{cursor:zoom-out!important}.cursor-default{cursor:default!important}.cursor-none{cursor:none!important}.cursor-help{cursor:help!important}.cursor-progress{cursor:progress!important}.cursor-wait{cursor:wait!important}.cursor-text{cursor:text!important}.cursor-v-text{cursor:vertical-text!important}.cursor-grab{cursor:grab!important}.cursor-grabbing{cursor:grabbing!important}.cursor-crosshair{cursor:crosshair!important}.border-x{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-right:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-x-wide{border-left:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-right:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-x-0{border-left:0!important;border-right:0!important}.border-y{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-y-wide{border-top:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important;border-bottom:2px var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.border-y-0{border-top:0!important;border-bottom:0!important}.columns-2{columns:2!important}.columns-3{columns:3!important}.columns-4{columns:4!important}.bg-pattern-transparent{background:url('data:image/svg+xml;charset=UTF-8,') repeat center/16px 16px!important}.bg-gradient{background:linear-gradient(var(--tblr-gradient-direction, to right),var(--tblr-gradient-stops, var(--tblr-gradient-from, transparent), var(--tblr-gradient-to, transparent))) no-repeat!important}.bg-gradient-to-t{--tblr-gradient-direction: to top !important}.bg-gradient-to-te{--tblr-gradient-direction: to top right !important}.bg-gradient-to-e{--tblr-gradient-direction: to right !important}.bg-gradient-to-be{--tblr-gradient-direction: to bottom right !important}.bg-gradient-to-b{--tblr-gradient-direction: to bottom !important}.bg-gradient-to-bs{--tblr-gradient-direction: to bottom left !important}.bg-gradient-to-s{--tblr-gradient-direction: to left !important}.bg-gradient-to-ts{--tblr-gradient-direction: to top left !important}.table-auto{table-layout:auto!important}.table-fixed{table-layout:fixed!important}@media(min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.object-fit-sm-contain{object-fit:contain!important}.object-fit-sm-cover{object-fit:cover!important}.object-fit-sm-fill{object-fit:fill!important}.object-fit-sm-scale{object-fit:scale-down!important}.object-fit-sm-none{object-fit:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-inline-grid{display:inline-grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:2rem!important}.m-sm-6{margin:2.5rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:2rem!important;margin-left:2rem!important}.mx-sm-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-sm-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:2rem!important}.mt-sm-6{margin-top:2.5rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:2rem!important}.me-sm-6{margin-right:2.5rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:2rem!important}.mb-sm-6{margin-bottom:2.5rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:2rem!important}.ms-sm-6{margin-left:2.5rem!important}.ms-sm-auto{margin-left:auto!important}.m-sm-n1{margin:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.m-sm-n3{margin:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.m-sm-n5{margin:-2rem!important}.m-sm-n6{margin:-2.5rem!important}.mx-sm-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-sm-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-sm-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-sm-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-sm-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-sm-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-sm-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-sm-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-sm-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-sm-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-sm-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-sm-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-sm-n1{margin-top:-.25rem!important}.mt-sm-n2{margin-top:-.5rem!important}.mt-sm-n3{margin-top:-1rem!important}.mt-sm-n4{margin-top:-1.5rem!important}.mt-sm-n5{margin-top:-2rem!important}.mt-sm-n6{margin-top:-2.5rem!important}.me-sm-n1{margin-right:-.25rem!important}.me-sm-n2{margin-right:-.5rem!important}.me-sm-n3{margin-right:-1rem!important}.me-sm-n4{margin-right:-1.5rem!important}.me-sm-n5{margin-right:-2rem!important}.me-sm-n6{margin-right:-2.5rem!important}.mb-sm-n1{margin-bottom:-.25rem!important}.mb-sm-n2{margin-bottom:-.5rem!important}.mb-sm-n3{margin-bottom:-1rem!important}.mb-sm-n4{margin-bottom:-1.5rem!important}.mb-sm-n5{margin-bottom:-2rem!important}.mb-sm-n6{margin-bottom:-2.5rem!important}.ms-sm-n1{margin-left:-.25rem!important}.ms-sm-n2{margin-left:-.5rem!important}.ms-sm-n3{margin-left:-1rem!important}.ms-sm-n4{margin-left:-1.5rem!important}.ms-sm-n5{margin-left:-2rem!important}.ms-sm-n6{margin-left:-2.5rem!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:2rem!important}.p-sm-6{padding:2.5rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:2rem!important;padding-left:2rem!important}.px-sm-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-sm-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:2rem!important}.pt-sm-6{padding-top:2.5rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:2rem!important}.pe-sm-6{padding-right:2.5rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:2rem!important}.pb-sm-6{padding-bottom:2.5rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:2rem!important}.ps-sm-6{padding-left:2.5rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:2rem!important}.gap-sm-6{gap:2.5rem!important}.row-gap-sm-0{row-gap:0!important}.row-gap-sm-1{row-gap:.25rem!important}.row-gap-sm-2{row-gap:.5rem!important}.row-gap-sm-3{row-gap:1rem!important}.row-gap-sm-4{row-gap:1.5rem!important}.row-gap-sm-5{row-gap:2rem!important}.row-gap-sm-6{row-gap:2.5rem!important}.column-gap-sm-0{column-gap:0!important}.column-gap-sm-1{column-gap:.25rem!important}.column-gap-sm-2{column-gap:.5rem!important}.column-gap-sm-3{column-gap:1rem!important}.column-gap-sm-4{column-gap:1.5rem!important}.column-gap-sm-5{column-gap:2rem!important}.column-gap-sm-6{column-gap:2.5rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}.columns-sm-2{columns:2!important}.columns-sm-3{columns:3!important}.columns-sm-4{columns:4!important}}@media(min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.object-fit-md-contain{object-fit:contain!important}.object-fit-md-cover{object-fit:cover!important}.object-fit-md-fill{object-fit:fill!important}.object-fit-md-scale{object-fit:scale-down!important}.object-fit-md-none{object-fit:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-inline-grid{display:inline-grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:2rem!important}.m-md-6{margin:2.5rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:2rem!important;margin-left:2rem!important}.mx-md-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-md-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:2rem!important}.mt-md-6{margin-top:2.5rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:2rem!important}.me-md-6{margin-right:2.5rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:2rem!important}.mb-md-6{margin-bottom:2.5rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:2rem!important}.ms-md-6{margin-left:2.5rem!important}.ms-md-auto{margin-left:auto!important}.m-md-n1{margin:-.25rem!important}.m-md-n2{margin:-.5rem!important}.m-md-n3{margin:-1rem!important}.m-md-n4{margin:-1.5rem!important}.m-md-n5{margin:-2rem!important}.m-md-n6{margin:-2.5rem!important}.mx-md-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-md-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-md-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-md-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-md-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-md-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-md-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-md-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-md-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-md-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-md-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-md-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-md-n1{margin-top:-.25rem!important}.mt-md-n2{margin-top:-.5rem!important}.mt-md-n3{margin-top:-1rem!important}.mt-md-n4{margin-top:-1.5rem!important}.mt-md-n5{margin-top:-2rem!important}.mt-md-n6{margin-top:-2.5rem!important}.me-md-n1{margin-right:-.25rem!important}.me-md-n2{margin-right:-.5rem!important}.me-md-n3{margin-right:-1rem!important}.me-md-n4{margin-right:-1.5rem!important}.me-md-n5{margin-right:-2rem!important}.me-md-n6{margin-right:-2.5rem!important}.mb-md-n1{margin-bottom:-.25rem!important}.mb-md-n2{margin-bottom:-.5rem!important}.mb-md-n3{margin-bottom:-1rem!important}.mb-md-n4{margin-bottom:-1.5rem!important}.mb-md-n5{margin-bottom:-2rem!important}.mb-md-n6{margin-bottom:-2.5rem!important}.ms-md-n1{margin-left:-.25rem!important}.ms-md-n2{margin-left:-.5rem!important}.ms-md-n3{margin-left:-1rem!important}.ms-md-n4{margin-left:-1.5rem!important}.ms-md-n5{margin-left:-2rem!important}.ms-md-n6{margin-left:-2.5rem!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:2rem!important}.p-md-6{padding:2.5rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:2rem!important;padding-left:2rem!important}.px-md-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-md-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:2rem!important}.pt-md-6{padding-top:2.5rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:2rem!important}.pe-md-6{padding-right:2.5rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:2rem!important}.pb-md-6{padding-bottom:2.5rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:2rem!important}.ps-md-6{padding-left:2.5rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:2rem!important}.gap-md-6{gap:2.5rem!important}.row-gap-md-0{row-gap:0!important}.row-gap-md-1{row-gap:.25rem!important}.row-gap-md-2{row-gap:.5rem!important}.row-gap-md-3{row-gap:1rem!important}.row-gap-md-4{row-gap:1.5rem!important}.row-gap-md-5{row-gap:2rem!important}.row-gap-md-6{row-gap:2.5rem!important}.column-gap-md-0{column-gap:0!important}.column-gap-md-1{column-gap:.25rem!important}.column-gap-md-2{column-gap:.5rem!important}.column-gap-md-3{column-gap:1rem!important}.column-gap-md-4{column-gap:1.5rem!important}.column-gap-md-5{column-gap:2rem!important}.column-gap-md-6{column-gap:2.5rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}.columns-md-2{columns:2!important}.columns-md-3{columns:3!important}.columns-md-4{columns:4!important}}@media(min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.object-fit-lg-contain{object-fit:contain!important}.object-fit-lg-cover{object-fit:cover!important}.object-fit-lg-fill{object-fit:fill!important}.object-fit-lg-scale{object-fit:scale-down!important}.object-fit-lg-none{object-fit:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-inline-grid{display:inline-grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:2rem!important}.m-lg-6{margin:2.5rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:2rem!important;margin-left:2rem!important}.mx-lg-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-lg-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:2rem!important}.mt-lg-6{margin-top:2.5rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:2rem!important}.me-lg-6{margin-right:2.5rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:2rem!important}.mb-lg-6{margin-bottom:2.5rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:2rem!important}.ms-lg-6{margin-left:2.5rem!important}.ms-lg-auto{margin-left:auto!important}.m-lg-n1{margin:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.m-lg-n3{margin:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.m-lg-n5{margin:-2rem!important}.m-lg-n6{margin:-2.5rem!important}.mx-lg-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-lg-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-lg-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-lg-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-lg-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-lg-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-lg-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-lg-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-lg-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-lg-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-lg-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-lg-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-lg-n1{margin-top:-.25rem!important}.mt-lg-n2{margin-top:-.5rem!important}.mt-lg-n3{margin-top:-1rem!important}.mt-lg-n4{margin-top:-1.5rem!important}.mt-lg-n5{margin-top:-2rem!important}.mt-lg-n6{margin-top:-2.5rem!important}.me-lg-n1{margin-right:-.25rem!important}.me-lg-n2{margin-right:-.5rem!important}.me-lg-n3{margin-right:-1rem!important}.me-lg-n4{margin-right:-1.5rem!important}.me-lg-n5{margin-right:-2rem!important}.me-lg-n6{margin-right:-2.5rem!important}.mb-lg-n1{margin-bottom:-.25rem!important}.mb-lg-n2{margin-bottom:-.5rem!important}.mb-lg-n3{margin-bottom:-1rem!important}.mb-lg-n4{margin-bottom:-1.5rem!important}.mb-lg-n5{margin-bottom:-2rem!important}.mb-lg-n6{margin-bottom:-2.5rem!important}.ms-lg-n1{margin-left:-.25rem!important}.ms-lg-n2{margin-left:-.5rem!important}.ms-lg-n3{margin-left:-1rem!important}.ms-lg-n4{margin-left:-1.5rem!important}.ms-lg-n5{margin-left:-2rem!important}.ms-lg-n6{margin-left:-2.5rem!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:2rem!important}.p-lg-6{padding:2.5rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:2rem!important;padding-left:2rem!important}.px-lg-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-lg-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:2rem!important}.pt-lg-6{padding-top:2.5rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:2rem!important}.pe-lg-6{padding-right:2.5rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:2rem!important}.pb-lg-6{padding-bottom:2.5rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:2rem!important}.ps-lg-6{padding-left:2.5rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:2rem!important}.gap-lg-6{gap:2.5rem!important}.row-gap-lg-0{row-gap:0!important}.row-gap-lg-1{row-gap:.25rem!important}.row-gap-lg-2{row-gap:.5rem!important}.row-gap-lg-3{row-gap:1rem!important}.row-gap-lg-4{row-gap:1.5rem!important}.row-gap-lg-5{row-gap:2rem!important}.row-gap-lg-6{row-gap:2.5rem!important}.column-gap-lg-0{column-gap:0!important}.column-gap-lg-1{column-gap:.25rem!important}.column-gap-lg-2{column-gap:.5rem!important}.column-gap-lg-3{column-gap:1rem!important}.column-gap-lg-4{column-gap:1.5rem!important}.column-gap-lg-5{column-gap:2rem!important}.column-gap-lg-6{column-gap:2.5rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}.columns-lg-2{columns:2!important}.columns-lg-3{columns:3!important}.columns-lg-4{columns:4!important}}@media(min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.object-fit-xl-contain{object-fit:contain!important}.object-fit-xl-cover{object-fit:cover!important}.object-fit-xl-fill{object-fit:fill!important}.object-fit-xl-scale{object-fit:scale-down!important}.object-fit-xl-none{object-fit:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-inline-grid{display:inline-grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:2rem!important}.m-xl-6{margin:2.5rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:2rem!important;margin-left:2rem!important}.mx-xl-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-xl-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:2rem!important}.mt-xl-6{margin-top:2.5rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:2rem!important}.me-xl-6{margin-right:2.5rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:2rem!important}.mb-xl-6{margin-bottom:2.5rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:2rem!important}.ms-xl-6{margin-left:2.5rem!important}.ms-xl-auto{margin-left:auto!important}.m-xl-n1{margin:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.m-xl-n3{margin:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.m-xl-n5{margin:-2rem!important}.m-xl-n6{margin:-2.5rem!important}.mx-xl-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-xl-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-xl-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-xl-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-xl-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-xl-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-xl-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-xl-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-xl-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-xl-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-xl-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-xl-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-xl-n1{margin-top:-.25rem!important}.mt-xl-n2{margin-top:-.5rem!important}.mt-xl-n3{margin-top:-1rem!important}.mt-xl-n4{margin-top:-1.5rem!important}.mt-xl-n5{margin-top:-2rem!important}.mt-xl-n6{margin-top:-2.5rem!important}.me-xl-n1{margin-right:-.25rem!important}.me-xl-n2{margin-right:-.5rem!important}.me-xl-n3{margin-right:-1rem!important}.me-xl-n4{margin-right:-1.5rem!important}.me-xl-n5{margin-right:-2rem!important}.me-xl-n6{margin-right:-2.5rem!important}.mb-xl-n1{margin-bottom:-.25rem!important}.mb-xl-n2{margin-bottom:-.5rem!important}.mb-xl-n3{margin-bottom:-1rem!important}.mb-xl-n4{margin-bottom:-1.5rem!important}.mb-xl-n5{margin-bottom:-2rem!important}.mb-xl-n6{margin-bottom:-2.5rem!important}.ms-xl-n1{margin-left:-.25rem!important}.ms-xl-n2{margin-left:-.5rem!important}.ms-xl-n3{margin-left:-1rem!important}.ms-xl-n4{margin-left:-1.5rem!important}.ms-xl-n5{margin-left:-2rem!important}.ms-xl-n6{margin-left:-2.5rem!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:2rem!important}.p-xl-6{padding:2.5rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:2rem!important;padding-left:2rem!important}.px-xl-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-xl-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:2rem!important}.pt-xl-6{padding-top:2.5rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:2rem!important}.pe-xl-6{padding-right:2.5rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:2rem!important}.pb-xl-6{padding-bottom:2.5rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:2rem!important}.ps-xl-6{padding-left:2.5rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:2rem!important}.gap-xl-6{gap:2.5rem!important}.row-gap-xl-0{row-gap:0!important}.row-gap-xl-1{row-gap:.25rem!important}.row-gap-xl-2{row-gap:.5rem!important}.row-gap-xl-3{row-gap:1rem!important}.row-gap-xl-4{row-gap:1.5rem!important}.row-gap-xl-5{row-gap:2rem!important}.row-gap-xl-6{row-gap:2.5rem!important}.column-gap-xl-0{column-gap:0!important}.column-gap-xl-1{column-gap:.25rem!important}.column-gap-xl-2{column-gap:.5rem!important}.column-gap-xl-3{column-gap:1rem!important}.column-gap-xl-4{column-gap:1.5rem!important}.column-gap-xl-5{column-gap:2rem!important}.column-gap-xl-6{column-gap:2.5rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}.columns-xl-2{columns:2!important}.columns-xl-3{columns:3!important}.columns-xl-4{columns:4!important}}@media(min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.object-fit-xxl-contain{object-fit:contain!important}.object-fit-xxl-cover{object-fit:cover!important}.object-fit-xxl-fill{object-fit:fill!important}.object-fit-xxl-scale{object-fit:scale-down!important}.object-fit-xxl-none{object-fit:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-inline-grid{display:inline-grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:2rem!important}.m-xxl-6{margin:2.5rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:2rem!important;margin-left:2rem!important}.mx-xxl-6{margin-right:2.5rem!important;margin-left:2.5rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:2rem!important;margin-bottom:2rem!important}.my-xxl-6{margin-top:2.5rem!important;margin-bottom:2.5rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:2rem!important}.mt-xxl-6{margin-top:2.5rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:2rem!important}.me-xxl-6{margin-right:2.5rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:2rem!important}.mb-xxl-6{margin-bottom:2.5rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:2rem!important}.ms-xxl-6{margin-left:2.5rem!important}.ms-xxl-auto{margin-left:auto!important}.m-xxl-n1{margin:-.25rem!important}.m-xxl-n2{margin:-.5rem!important}.m-xxl-n3{margin:-1rem!important}.m-xxl-n4{margin:-1.5rem!important}.m-xxl-n5{margin:-2rem!important}.m-xxl-n6{margin:-2.5rem!important}.mx-xxl-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-xxl-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-xxl-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-xxl-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-xxl-n5{margin-right:-2rem!important;margin-left:-2rem!important}.mx-xxl-n6{margin-right:-2.5rem!important;margin-left:-2.5rem!important}.my-xxl-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-xxl-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-xxl-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-xxl-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-xxl-n5{margin-top:-2rem!important;margin-bottom:-2rem!important}.my-xxl-n6{margin-top:-2.5rem!important;margin-bottom:-2.5rem!important}.mt-xxl-n1{margin-top:-.25rem!important}.mt-xxl-n2{margin-top:-.5rem!important}.mt-xxl-n3{margin-top:-1rem!important}.mt-xxl-n4{margin-top:-1.5rem!important}.mt-xxl-n5{margin-top:-2rem!important}.mt-xxl-n6{margin-top:-2.5rem!important}.me-xxl-n1{margin-right:-.25rem!important}.me-xxl-n2{margin-right:-.5rem!important}.me-xxl-n3{margin-right:-1rem!important}.me-xxl-n4{margin-right:-1.5rem!important}.me-xxl-n5{margin-right:-2rem!important}.me-xxl-n6{margin-right:-2.5rem!important}.mb-xxl-n1{margin-bottom:-.25rem!important}.mb-xxl-n2{margin-bottom:-.5rem!important}.mb-xxl-n3{margin-bottom:-1rem!important}.mb-xxl-n4{margin-bottom:-1.5rem!important}.mb-xxl-n5{margin-bottom:-2rem!important}.mb-xxl-n6{margin-bottom:-2.5rem!important}.ms-xxl-n1{margin-left:-.25rem!important}.ms-xxl-n2{margin-left:-.5rem!important}.ms-xxl-n3{margin-left:-1rem!important}.ms-xxl-n4{margin-left:-1.5rem!important}.ms-xxl-n5{margin-left:-2rem!important}.ms-xxl-n6{margin-left:-2.5rem!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:2rem!important}.p-xxl-6{padding:2.5rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:2rem!important;padding-left:2rem!important}.px-xxl-6{padding-right:2.5rem!important;padding-left:2.5rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:2rem!important;padding-bottom:2rem!important}.py-xxl-6{padding-top:2.5rem!important;padding-bottom:2.5rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:2rem!important}.pt-xxl-6{padding-top:2.5rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:2rem!important}.pe-xxl-6{padding-right:2.5rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:2rem!important}.pb-xxl-6{padding-bottom:2.5rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:2rem!important}.ps-xxl-6{padding-left:2.5rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:2rem!important}.gap-xxl-6{gap:2.5rem!important}.row-gap-xxl-0{row-gap:0!important}.row-gap-xxl-1{row-gap:.25rem!important}.row-gap-xxl-2{row-gap:.5rem!important}.row-gap-xxl-3{row-gap:1rem!important}.row-gap-xxl-4{row-gap:1.5rem!important}.row-gap-xxl-5{row-gap:2rem!important}.row-gap-xxl-6{row-gap:2.5rem!important}.column-gap-xxl-0{column-gap:0!important}.column-gap-xxl-1{column-gap:.25rem!important}.column-gap-xxl-2{column-gap:.5rem!important}.column-gap-xxl-3{column-gap:1rem!important}.column-gap-xxl-4{column-gap:1.5rem!important}.column-gap-xxl-5{column-gap:2rem!important}.column-gap-xxl-6{column-gap:2.5rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}.columns-xxl-2{columns:2!important}.columns-xxl-3{columns:3!important}.columns-xxl-4{columns:4!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-inline-grid{display:inline-grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}}:root,:host{--tblr-font-monospace: Roboto Mono;--tblr-font-sans-serif: Inter, system-ui, sans-serif;--tblr-font-serif: Georgia, Times New Roman, times, serif;--tblr-font-comic: Comic Sans MS, Comic Sans, Chalkboard SE, Comic Neue, sans-serif, cursive;--tblr-gray-50: #f9fafb;--tblr-gray-100: #f3f4f6;--tblr-gray-200: #e5e7eb;--tblr-gray-300: #d1d5db;--tblr-gray-400: #9ca3af;--tblr-gray-500: #6b7280;--tblr-gray-600: #4b5563;--tblr-gray-700: #374151;--tblr-gray-800: #1f2937;--tblr-gray-900: #111827;--tblr-gray-950: #030712;--tblr-white: #ffffff;--tblr-black: #000000;--tblr-brand: #00857D;--tblr-primary: #00857D;--tblr-primary-rgb: 0, 133, 125;--tblr-primary-fg: var(--tblr-light);--tblr-primary-darken: rgb(0, 119.7, 112.5);--tblr-primary-darken: color-mix(in oklab, var(--tblr-primary), transparent 20%);--tblr-primary-lt: rgb(229.5, 242.8, 242);--tblr-primary-lt: color-mix(in oklab, var(--tblr-primary) 10%, transparent);--tblr-primary-200: color-mix(in oklab, var(--tblr-primary) 20%, transparent);--tblr-primary-lt-rgb: 230, 243, 242;--tblr-secondary: #6b7280;--tblr-secondary-rgb: 107, 114, 128;--tblr-secondary-fg: var(--tblr-light);--tblr-secondary-darken: rgb(96.3, 102.6, 115.2);--tblr-secondary-darken: color-mix(in oklab, var(--tblr-secondary), transparent 20%);--tblr-secondary-lt: rgb(240.2, 240.9, 242.3);--tblr-secondary-lt: color-mix(in oklab, var(--tblr-secondary) 10%, transparent);--tblr-secondary-200: color-mix(in oklab, var(--tblr-secondary) 20%, transparent);--tblr-secondary-lt-rgb: 240, 241, 242;--tblr-success: #2fb344;--tblr-success-rgb: 47, 179, 68;--tblr-success-fg: var(--tblr-light);--tblr-success-darken: rgb(42.3, 161.1, 61.2);--tblr-success-darken: color-mix(in oklab, var(--tblr-success), transparent 20%);--tblr-success-lt: rgb(234.2, 247.4, 236.3);--tblr-success-lt: color-mix(in oklab, var(--tblr-success) 10%, transparent);--tblr-success-200: color-mix(in oklab, var(--tblr-success) 20%, transparent);--tblr-success-lt-rgb: 234, 247, 236;--tblr-info: #4299e1;--tblr-info-rgb: 66, 153, 225;--tblr-info-fg: var(--tblr-light);--tblr-info-darken: rgb(59.4, 137.7, 202.5);--tblr-info-darken: color-mix(in oklab, var(--tblr-info), transparent 20%);--tblr-info-lt: rgb(236.1, 244.8, 252);--tblr-info-lt: color-mix(in oklab, var(--tblr-info) 10%, transparent);--tblr-info-200: color-mix(in oklab, var(--tblr-info) 20%, transparent);--tblr-info-lt-rgb: 236, 245, 252;--tblr-warning: #f59f00;--tblr-warning-rgb: 245, 159, 0;--tblr-warning-fg: var(--tblr-light);--tblr-warning-darken: rgb(220.5, 143.1, 0);--tblr-warning-darken: color-mix(in oklab, var(--tblr-warning), transparent 20%);--tblr-warning-lt: rgb(254, 245.4, 229.5);--tblr-warning-lt: color-mix(in oklab, var(--tblr-warning) 10%, transparent);--tblr-warning-200: color-mix(in oklab, var(--tblr-warning) 20%, transparent);--tblr-warning-lt-rgb: 254, 245, 230;--tblr-danger: #d63939;--tblr-danger-rgb: 214, 57, 57;--tblr-danger-fg: var(--tblr-light);--tblr-danger-darken: rgb(192.6, 51.3, 51.3);--tblr-danger-darken: color-mix(in oklab, var(--tblr-danger), transparent 20%);--tblr-danger-lt: rgb(250.9, 235.2, 235.2);--tblr-danger-lt: color-mix(in oklab, var(--tblr-danger) 10%, transparent);--tblr-danger-200: color-mix(in oklab, var(--tblr-danger) 20%, transparent);--tblr-danger-lt-rgb: 251, 235, 235;--tblr-light: #f9fafb;--tblr-light-rgb: 249, 250, 251;--tblr-light-fg: var(--tblr-dark);--tblr-light-darken: rgb(224.1, 225, 225.9);--tblr-light-darken: color-mix(in oklab, var(--tblr-light), transparent 20%);--tblr-light-lt: rgb(254.4, 254.5, 254.6);--tblr-light-lt: color-mix(in oklab, var(--tblr-light) 10%, transparent);--tblr-light-200: color-mix(in oklab, var(--tblr-light) 20%, transparent);--tblr-light-lt-rgb: 254, 255, 255;--tblr-dark: #1f2937;--tblr-dark-rgb: 31, 41, 55;--tblr-dark-fg: var(--tblr-light);--tblr-dark-darken: rgb(27.9, 36.9, 49.5);--tblr-dark-darken: color-mix(in oklab, var(--tblr-dark), transparent 20%);--tblr-dark-lt: rgb(232.6, 233.6, 235);--tblr-dark-lt: color-mix(in oklab, var(--tblr-dark) 10%, transparent);--tblr-dark-200: color-mix(in oklab, var(--tblr-dark) 20%, transparent);--tblr-dark-lt-rgb: 233, 234, 235;--tblr-muted: #6b7280;--tblr-muted-rgb: 107, 114, 128;--tblr-muted-fg: var(--tblr-light);--tblr-muted-darken: rgb(96.3, 102.6, 115.2);--tblr-muted-darken: color-mix(in oklab, var(--tblr-muted), transparent 20%);--tblr-muted-lt: rgb(240.2, 240.9, 242.3);--tblr-muted-lt: color-mix(in oklab, var(--tblr-muted) 10%, transparent);--tblr-muted-200: color-mix(in oklab, var(--tblr-muted) 20%, transparent);--tblr-muted-lt-rgb: 240, 241, 242;--tblr-blue: #066fd1;--tblr-blue-rgb: 6, 111, 209;--tblr-blue-fg: var(--tblr-light);--tblr-blue-darken: rgb(5.4, 99.9, 188.1);--tblr-blue-darken: color-mix(in oklab, var(--tblr-blue), transparent 20%);--tblr-blue-lt: rgb(230.1, 240.6, 250.4);--tblr-blue-lt: color-mix(in oklab, var(--tblr-blue) 10%, transparent);--tblr-blue-200: color-mix(in oklab, var(--tblr-blue) 20%, transparent);--tblr-blue-lt-rgb: 230, 241, 250;--tblr-azure: #4299e1;--tblr-azure-rgb: 66, 153, 225;--tblr-azure-fg: var(--tblr-light);--tblr-azure-darken: rgb(59.4, 137.7, 202.5);--tblr-azure-darken: color-mix(in oklab, var(--tblr-azure), transparent 20%);--tblr-azure-lt: rgb(236.1, 244.8, 252);--tblr-azure-lt: color-mix(in oklab, var(--tblr-azure) 10%, transparent);--tblr-azure-200: color-mix(in oklab, var(--tblr-azure) 20%, transparent);--tblr-azure-lt-rgb: 236, 245, 252;--tblr-indigo: #4263eb;--tblr-indigo-rgb: 66, 99, 235;--tblr-indigo-fg: var(--tblr-light);--tblr-indigo-darken: rgb(59.4, 89.1, 211.5);--tblr-indigo-darken: color-mix(in oklab, var(--tblr-indigo), transparent 20%);--tblr-indigo-lt: rgb(236.1, 239.4, 253);--tblr-indigo-lt: color-mix(in oklab, var(--tblr-indigo) 10%, transparent);--tblr-indigo-200: color-mix(in oklab, var(--tblr-indigo) 20%, transparent);--tblr-indigo-lt-rgb: 236, 239, 253;--tblr-purple: #ae3ec9;--tblr-purple-rgb: 174, 62, 201;--tblr-purple-fg: var(--tblr-light);--tblr-purple-darken: rgb(156.6, 55.8, 180.9);--tblr-purple-darken: color-mix(in oklab, var(--tblr-purple), transparent 20%);--tblr-purple-lt: rgb(246.9, 235.7, 249.6);--tblr-purple-lt: color-mix(in oklab, var(--tblr-purple) 10%, transparent);--tblr-purple-200: color-mix(in oklab, var(--tblr-purple) 20%, transparent);--tblr-purple-lt-rgb: 247, 236, 250;--tblr-pink: #d6336c;--tblr-pink-rgb: 214, 51, 108;--tblr-pink-fg: var(--tblr-light);--tblr-pink-darken: rgb(192.6, 45.9, 97.2);--tblr-pink-darken: color-mix(in oklab, var(--tblr-pink), transparent 20%);--tblr-pink-lt: rgb(250.9, 234.6, 240.3);--tblr-pink-lt: color-mix(in oklab, var(--tblr-pink) 10%, transparent);--tblr-pink-200: color-mix(in oklab, var(--tblr-pink) 20%, transparent);--tblr-pink-lt-rgb: 251, 235, 240;--tblr-red: #d63939;--tblr-red-rgb: 214, 57, 57;--tblr-red-fg: var(--tblr-light);--tblr-red-darken: rgb(192.6, 51.3, 51.3);--tblr-red-darken: color-mix(in oklab, var(--tblr-red), transparent 20%);--tblr-red-lt: rgb(250.9, 235.2, 235.2);--tblr-red-lt: color-mix(in oklab, var(--tblr-red) 10%, transparent);--tblr-red-200: color-mix(in oklab, var(--tblr-red) 20%, transparent);--tblr-red-lt-rgb: 251, 235, 235;--tblr-orange: #f76707;--tblr-orange-rgb: 247, 103, 7;--tblr-orange-fg: var(--tblr-light);--tblr-orange-darken: rgb(222.3, 92.7, 6.3);--tblr-orange-darken: color-mix(in oklab, var(--tblr-orange), transparent 20%);--tblr-orange-lt: rgb(254.2, 239.8, 230.2);--tblr-orange-lt: color-mix(in oklab, var(--tblr-orange) 10%, transparent);--tblr-orange-200: color-mix(in oklab, var(--tblr-orange) 20%, transparent);--tblr-orange-lt-rgb: 254, 240, 230;--tblr-yellow: #f59f00;--tblr-yellow-rgb: 245, 159, 0;--tblr-yellow-fg: var(--tblr-light);--tblr-yellow-darken: rgb(220.5, 143.1, 0);--tblr-yellow-darken: color-mix(in oklab, var(--tblr-yellow), transparent 20%);--tblr-yellow-lt: rgb(254, 245.4, 229.5);--tblr-yellow-lt: color-mix(in oklab, var(--tblr-yellow) 10%, transparent);--tblr-yellow-200: color-mix(in oklab, var(--tblr-yellow) 20%, transparent);--tblr-yellow-lt-rgb: 254, 245, 230;--tblr-lime: #74b816;--tblr-lime-rgb: 116, 184, 22;--tblr-lime-fg: var(--tblr-light);--tblr-lime-darken: rgb(104.4, 165.6, 19.8);--tblr-lime-darken: color-mix(in oklab, var(--tblr-lime), transparent 20%);--tblr-lime-lt: rgb(241.1, 247.9, 231.7);--tblr-lime-lt: color-mix(in oklab, var(--tblr-lime) 10%, transparent);--tblr-lime-200: color-mix(in oklab, var(--tblr-lime) 20%, transparent);--tblr-lime-lt-rgb: 241, 248, 232;--tblr-green: #2fb344;--tblr-green-rgb: 47, 179, 68;--tblr-green-fg: var(--tblr-light);--tblr-green-darken: rgb(42.3, 161.1, 61.2);--tblr-green-darken: color-mix(in oklab, var(--tblr-green), transparent 20%);--tblr-green-lt: rgb(234.2, 247.4, 236.3);--tblr-green-lt: color-mix(in oklab, var(--tblr-green) 10%, transparent);--tblr-green-200: color-mix(in oklab, var(--tblr-green) 20%, transparent);--tblr-green-lt-rgb: 234, 247, 236;--tblr-teal: #0ca678;--tblr-teal-rgb: 12, 166, 120;--tblr-teal-fg: var(--tblr-light);--tblr-teal-darken: rgb(10.8, 149.4, 108);--tblr-teal-darken: color-mix(in oklab, var(--tblr-teal), transparent 20%);--tblr-teal-lt: rgb(230.7, 246.1, 241.5);--tblr-teal-lt: color-mix(in oklab, var(--tblr-teal) 10%, transparent);--tblr-teal-200: color-mix(in oklab, var(--tblr-teal) 20%, transparent);--tblr-teal-lt-rgb: 231, 246, 242;--tblr-cyan: #17a2b8;--tblr-cyan-rgb: 23, 162, 184;--tblr-cyan-fg: var(--tblr-light);--tblr-cyan-darken: rgb(20.7, 145.8, 165.6);--tblr-cyan-darken: color-mix(in oklab, var(--tblr-cyan), transparent 20%);--tblr-cyan-lt: rgb(231.8, 245.7, 247.9);--tblr-cyan-lt: color-mix(in oklab, var(--tblr-cyan) 10%, transparent);--tblr-cyan-200: color-mix(in oklab, var(--tblr-cyan) 20%, transparent);--tblr-cyan-lt-rgb: 232, 246, 248;--tblr-x: #000000;--tblr-x-rgb: 0, 0, 0;--tblr-x-fg: var(--tblr-light);--tblr-x-darken: black;--tblr-x-darken: color-mix(in oklab, var(--tblr-x), transparent 20%);--tblr-x-lt: rgb(229.5, 229.5, 229.5);--tblr-x-lt: color-mix(in oklab, var(--tblr-x) 10%, transparent);--tblr-x-200: color-mix(in oklab, var(--tblr-x) 20%, transparent);--tblr-x-lt-rgb: 230, 230, 230;--tblr-facebook: #1877f2;--tblr-facebook-rgb: 24, 119, 242;--tblr-facebook-fg: var(--tblr-light);--tblr-facebook-darken: rgb(21.6, 107.1, 217.8);--tblr-facebook-darken: color-mix(in oklab, var(--tblr-facebook), transparent 20%);--tblr-facebook-lt: rgb(231.9, 241.4, 253.7);--tblr-facebook-lt: color-mix(in oklab, var(--tblr-facebook) 10%, transparent);--tblr-facebook-200: color-mix(in oklab, var(--tblr-facebook) 20%, transparent);--tblr-facebook-lt-rgb: 232, 241, 254;--tblr-twitter: #1da1f2;--tblr-twitter-rgb: 29, 161, 242;--tblr-twitter-fg: var(--tblr-light);--tblr-twitter-darken: rgb(26.1, 144.9, 217.8);--tblr-twitter-darken: color-mix(in oklab, var(--tblr-twitter), transparent 20%);--tblr-twitter-lt: rgb(232.4, 245.6, 253.7);--tblr-twitter-lt: color-mix(in oklab, var(--tblr-twitter) 10%, transparent);--tblr-twitter-200: color-mix(in oklab, var(--tblr-twitter) 20%, transparent);--tblr-twitter-lt-rgb: 232, 246, 254;--tblr-linkedin: #0a66c2;--tblr-linkedin-rgb: 10, 102, 194;--tblr-linkedin-fg: var(--tblr-light);--tblr-linkedin-darken: rgb(9, 91.8, 174.6);--tblr-linkedin-darken: color-mix(in oklab, var(--tblr-linkedin), transparent 20%);--tblr-linkedin-lt: rgb(230.5, 239.7, 248.9);--tblr-linkedin-lt: color-mix(in oklab, var(--tblr-linkedin) 10%, transparent);--tblr-linkedin-200: color-mix(in oklab, var(--tblr-linkedin) 20%, transparent);--tblr-linkedin-lt-rgb: 231, 240, 249;--tblr-google: #dc4e41;--tblr-google-rgb: 220, 78, 65;--tblr-google-fg: var(--tblr-light);--tblr-google-darken: rgb(198, 70.2, 58.5);--tblr-google-darken: color-mix(in oklab, var(--tblr-google), transparent 20%);--tblr-google-lt: rgb(251.5, 237.3, 236);--tblr-google-lt: color-mix(in oklab, var(--tblr-google) 10%, transparent);--tblr-google-200: color-mix(in oklab, var(--tblr-google) 20%, transparent);--tblr-google-lt-rgb: 252, 237, 236;--tblr-youtube: #ff0000;--tblr-youtube-rgb: 255, 0, 0;--tblr-youtube-fg: var(--tblr-light);--tblr-youtube-darken: rgb(229.5, 0, 0);--tblr-youtube-darken: color-mix(in oklab, var(--tblr-youtube), transparent 20%);--tblr-youtube-lt: rgb(255, 229.5, 229.5);--tblr-youtube-lt: color-mix(in oklab, var(--tblr-youtube) 10%, transparent);--tblr-youtube-200: color-mix(in oklab, var(--tblr-youtube) 20%, transparent);--tblr-youtube-lt-rgb: 255, 230, 230;--tblr-vimeo: #1ab7ea;--tblr-vimeo-rgb: 26, 183, 234;--tblr-vimeo-fg: var(--tblr-light);--tblr-vimeo-darken: rgb(23.4, 164.7, 210.6);--tblr-vimeo-darken: color-mix(in oklab, var(--tblr-vimeo), transparent 20%);--tblr-vimeo-lt: rgb(232.1, 247.8, 252.9);--tblr-vimeo-lt: color-mix(in oklab, var(--tblr-vimeo) 10%, transparent);--tblr-vimeo-200: color-mix(in oklab, var(--tblr-vimeo) 20%, transparent);--tblr-vimeo-lt-rgb: 232, 248, 253;--tblr-dribbble: #ea4c89;--tblr-dribbble-rgb: 234, 76, 137;--tblr-dribbble-fg: var(--tblr-light);--tblr-dribbble-darken: rgb(210.6, 68.4, 123.3);--tblr-dribbble-darken: color-mix(in oklab, var(--tblr-dribbble), transparent 20%);--tblr-dribbble-lt: rgb(252.9, 237.1, 243.2);--tblr-dribbble-lt: color-mix(in oklab, var(--tblr-dribbble) 10%, transparent);--tblr-dribbble-200: color-mix(in oklab, var(--tblr-dribbble) 20%, transparent);--tblr-dribbble-lt-rgb: 253, 237, 243;--tblr-github: #181717;--tblr-github-rgb: 24, 23, 23;--tblr-github-fg: var(--tblr-light);--tblr-github-darken: rgb(21.6, 20.7, 20.7);--tblr-github-darken: color-mix(in oklab, var(--tblr-github), transparent 20%);--tblr-github-lt: rgb(231.9, 231.8, 231.8);--tblr-github-lt: color-mix(in oklab, var(--tblr-github) 10%, transparent);--tblr-github-200: color-mix(in oklab, var(--tblr-github) 20%, transparent);--tblr-github-lt-rgb: 232, 232, 232;--tblr-instagram: #e4405f;--tblr-instagram-rgb: 228, 64, 95;--tblr-instagram-fg: var(--tblr-light);--tblr-instagram-darken: rgb(205.2, 57.6, 85.5);--tblr-instagram-darken: color-mix(in oklab, var(--tblr-instagram), transparent 20%);--tblr-instagram-lt: rgb(252.3, 235.9, 239);--tblr-instagram-lt: color-mix(in oklab, var(--tblr-instagram) 10%, transparent);--tblr-instagram-200: color-mix(in oklab, var(--tblr-instagram) 20%, transparent);--tblr-instagram-lt-rgb: 252, 236, 239;--tblr-pinterest: #bd081c;--tblr-pinterest-rgb: 189, 8, 28;--tblr-pinterest-fg: var(--tblr-light);--tblr-pinterest-darken: rgb(170.1, 7.2, 25.2);--tblr-pinterest-darken: color-mix(in oklab, var(--tblr-pinterest), transparent 20%);--tblr-pinterest-lt: rgb(248.4, 230.3, 232.3);--tblr-pinterest-lt: color-mix(in oklab, var(--tblr-pinterest) 10%, transparent);--tblr-pinterest-200: color-mix(in oklab, var(--tblr-pinterest) 20%, transparent);--tblr-pinterest-lt-rgb: 248, 230, 232;--tblr-vk: #6383a8;--tblr-vk-rgb: 99, 131, 168;--tblr-vk-fg: var(--tblr-light);--tblr-vk-darken: rgb(89.1, 117.9, 151.2);--tblr-vk-darken: color-mix(in oklab, var(--tblr-vk), transparent 20%);--tblr-vk-lt: rgb(239.4, 242.6, 246.3);--tblr-vk-lt: color-mix(in oklab, var(--tblr-vk) 10%, transparent);--tblr-vk-200: color-mix(in oklab, var(--tblr-vk) 20%, transparent);--tblr-vk-lt-rgb: 239, 243, 246;--tblr-rss: #ffa500;--tblr-rss-rgb: 255, 165, 0;--tblr-rss-fg: var(--tblr-light);--tblr-rss-darken: rgb(229.5, 148.5, 0);--tblr-rss-darken: color-mix(in oklab, var(--tblr-rss), transparent 20%);--tblr-rss-lt: rgb(255, 246, 229.5);--tblr-rss-lt: color-mix(in oklab, var(--tblr-rss) 10%, transparent);--tblr-rss-200: color-mix(in oklab, var(--tblr-rss) 20%, transparent);--tblr-rss-lt-rgb: 255, 246, 230;--tblr-flickr: #0063dc;--tblr-flickr-rgb: 0, 99, 220;--tblr-flickr-fg: var(--tblr-light);--tblr-flickr-darken: rgb(0, 89.1, 198);--tblr-flickr-darken: color-mix(in oklab, var(--tblr-flickr), transparent 20%);--tblr-flickr-lt: rgb(229.5, 239.4, 251.5);--tblr-flickr-lt: color-mix(in oklab, var(--tblr-flickr) 10%, transparent);--tblr-flickr-200: color-mix(in oklab, var(--tblr-flickr) 20%, transparent);--tblr-flickr-lt-rgb: 230, 239, 252;--tblr-bitbucket: #0052cc;--tblr-bitbucket-rgb: 0, 82, 204;--tblr-bitbucket-fg: var(--tblr-light);--tblr-bitbucket-darken: rgb(0, 73.8, 183.6);--tblr-bitbucket-darken: color-mix(in oklab, var(--tblr-bitbucket), transparent 20%);--tblr-bitbucket-lt: rgb(229.5, 237.7, 249.9);--tblr-bitbucket-lt: color-mix(in oklab, var(--tblr-bitbucket) 10%, transparent);--tblr-bitbucket-200: color-mix(in oklab, var(--tblr-bitbucket) 20%, transparent);--tblr-bitbucket-lt-rgb: 230, 238, 250;--tblr-tabler: #066fd1;--tblr-tabler-rgb: 6, 111, 209;--tblr-tabler-fg: var(--tblr-light);--tblr-tabler-darken: rgb(5.4, 99.9, 188.1);--tblr-tabler-darken: color-mix(in oklab, var(--tblr-tabler), transparent 20%);--tblr-tabler-lt: rgb(230.1, 240.6, 250.4);--tblr-tabler-lt: color-mix(in oklab, var(--tblr-tabler) 10%, transparent);--tblr-tabler-200: color-mix(in oklab, var(--tblr-tabler) 20%, transparent);--tblr-tabler-lt-rgb: 230, 241, 250;--tblr-gray-50-fg: var(--tblr-body-color);--tblr-gray-100-fg: var(--tblr-body-color);--tblr-gray-200-fg: var(--tblr-body-color);--tblr-gray-300-fg: var(--tblr-body-color);--tblr-gray-400-fg: var(--tblr-white);--tblr-gray-500-fg: var(--tblr-white);--tblr-gray-600-fg: var(--tblr-white);--tblr-gray-700-fg: var(--tblr-white);--tblr-gray-800-fg: var(--tblr-white);--tblr-gray-900-fg: var(--tblr-white);--tblr-gray-950-fg: var(--tblr-white);--tblr-spacer-0: 0;--tblr-spacer-1: .25rem;--tblr-spacer-2: .5rem;--tblr-spacer-3: 1rem;--tblr-spacer-4: 1.5rem;--tblr-spacer-5: 2rem;--tblr-spacer-6: 2.5rem;--tblr-font-weight-light: 300;--tblr-font-weight-normal: 400;--tblr-font-weight-medium: 500;--tblr-font-weight-bold: 600;--tblr-font-weight-black: 700;--tblr-font-weight-headings: var(--tblr-font-weight-bold);--tblr-font-size-h1: 1.5rem;--tblr-font-size-h2: 1.25rem;--tblr-font-size-h3: 1rem;--tblr-font-size-h4: .875rem;--tblr-font-size-h5: .75rem;--tblr-font-size-h6: .625rem;--tblr-line-height-h1: 2rem;--tblr-line-height-h2: 1.75rem;--tblr-line-height-h3: 1.5rem;--tblr-line-height-h4: 1.25rem;--tblr-line-height-h5: 1rem;--tblr-line-height-h6: 1rem;--tblr-shadow: rgba(var(--tblr-body-color-rgb), .04) 0 2px 4px 0;--tblr-shadow-border: inset 0 0 0 1px var(--tblr-border-color-translucent);--tblr-shadow-transparent: 0 0 0 0 transparent;--tblr-shadow-input: 0 1px 1px rgba(var(--tblr-body-color-rgb), .06);--tblr-shadow-card: 0 0 4px rgba(var(--tblr-body-color-rgb), .04);--tblr-shadow-card-hover: rgba(var(--tblr-body-color-rgb), .16) 0 2px 16px 0;--tblr-shadow-dropdown: 0 16px 24px 2px rgba(0, 0, 0, .07), 0 6px 30px 5px rgba(0, 0, 0, .06), 0 8px 10px -5px rgba(0, 0, 0, .1);--tblr-border-radius-scale: 1;--tblr-border-radius-0: calc(0 * var(--tblr-border-radius-scale, 1));--tblr-border-radius-sm: calc(4px * var(--tblr-border-radius-scale, 1));--tblr-border-radius-md: calc(6px * var(--tblr-border-radius-scale, 1));--tblr-border-radius-lg: calc(8px * var(--tblr-border-radius-scale, 1));--tblr-border-radius-pill: calc(100rem * var(--tblr-border-radius-scale, 1));--tblr-border-radius: var(--tblr-border-radius-md);--tblr-backdrop-opacity: 24%;--tblr-backdrop-bg: var(--tblr-bg-surface-dark);--tblr-backdrop-bg-dark: color-mix(in srgb, var(--tblr-color-dark), transparent var(--tblr-backdrop-opacity));--tblr-backdrop-bg-light: color-mix(in srgb, var(--tblr-color-light), transparent var(--tblr-backdrop-opacity));--tblr-backdrop-blur: 4px;--tblr-backdrop-filter: blur(var(--tblr-backdrop-blur))}:root,:host{font-size:16px;height:100%}@media(min-width:992px){:root,:host{margin-left:calc(100vw - 100%);margin-right:0}}:root,:host,[data-bs-theme=light]{color-scheme:light;--tblr-spacer: var(--tblr-spacer-2);--tblr-bg-surface: var(--tblr-bg-surface-primary);--tblr-bg-surface-primary: var(--tblr-white);--tblr-bg-surface-secondary: var(--tblr-gray-50);--tblr-bg-surface-tertiary: var(--tblr-gray-50);--tblr-bg-surface-dark: var(--tblr-gray-900);--tblr-bg-surface-inverted: var(--tblr-gray-900);--tblr-bg-forms: var(--tblr-bg-surface);--tblr-text-inverted: var(--tblr-gray-100);--tblr-body-color: var(--tblr-gray-700);--tblr-body-bg: var(--tblr-bg-surface-secondary);--tblr-link-color: var(--tblr-primary);--tblr-link-hover-color: color-mix(in srgb, var(--tblr-primary), #000 20%);--tblr-secondary: var(--tblr-gray-500);--tblr-tertiary: var(--tblr-gray-400);--tblr-border-color: #e5e7eb;--tblr-border-color-translucent: rgba(4, 32, 69, .1);--tblr-border-dark-color: #9ca3af;--tblr-border-dark-color-translucent: rgba(4, 32, 69, .27);--tblr-border-active-color: rgb(169.16, 173.22, 181.34);--tblr-icon-color: var(--tblr-gray-400);--tblr-active-bg: rgba(var(--tblr-primary-rgb), .04);--tblr-disabled-bg: var(--tblr-bg-surface-secondary);--tblr-disabled-color: color-mix(in srgb, var(--tblr-body-color) 40%, transparent);--tblr-code-color: light-dark(var(--tblr-gray-600), var(--tblr-gray-400));--tblr-code-bg: light-dark(var(--tblr-gray-100), var(--tblr-gray-900));--tblr-dark-mode-border-color: rgb(45.7069767442, 60.4511627907, 81.0930232558);--tblr-dark-mode-border-color-translucent: rgba(72, 110, 149, .14);--tblr-dark-mode-border-active-color: rgb(53.0604651163, 70.176744186, 94.1395348837);--tblr-dark-mode-border-dark-color: rgb(38.3534883721, 50.7255813953, 68.0465116279);--tblr-page-padding: var(--tblr-spacer-3);--tblr-page-padding-y: var(--tblr-spacer-4)}@media(max-width:991.98px){:root,:host,[data-bs-theme=light]{--tblr-page-padding: var(--tblr-spacer-2)}}@keyframes pulse{0%{transform:scale(1)}14%{transform:scale(1.25)}28%{transform:scale(1)}42%{transform:scale(1.25)}70%{transform:scale(1)}}@keyframes tada{0%{transform:scaleZ(1)}10%,5%{transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-5deg)}15%,25%,35%,45%{transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,5deg)}20%,30%,40%{transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-5deg)}50%{transform:scaleZ(1)}}@keyframes rotate-360{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes blink{0%{opacity:0}50%{opacity:1}to{opacity:0}}@keyframes shake{0%{transform:scaleX(1)}20%{transform:scale3d(.9,.9,.9) rotate(-5deg)}50%,70%,90%{transform:scale3d(1.25,1.25,1.25) rotate(5deg)}60%,80%{transform:scale3d(1.25,1.25,1.25) rotate(-5deg)}to{transform:scaleX(1)}}body{letter-spacing:0;touch-action:manipulation;text-rendering:optimizeLegibility;font-feature-settings:"liga" 0,"cv03","cv04","cv11";position:relative;min-height:100%;height:100%;padding:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media print{body{background:transparent}}*{scrollbar-color:color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent) transparent}*::-webkit-scrollbar{width:1rem;height:1rem;transition:background .3s}@media(prefers-reduced-motion:reduce){*::-webkit-scrollbar{transition:none}}*::-webkit-scrollbar-thumb{border-radius:1rem;border:5px solid transparent;box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent)}*::-webkit-scrollbar-track{background:transparent}*:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 40%,transparent)}*::-webkit-scrollbar-corner{background:transparent}.layout-fluid .container,.layout-fluid [class^=container-],.layout-fluid [class*=" container-"]{max-width:100%}.layout-boxed{--tblr-theme-boxed-border-radius: 0;--tblr-theme-boxed-width: 1320px}@media(min-width:768px){.layout-boxed{background:#1f2937 linear-gradient(to right,rgba(255,255,255,.1),transparent) fixed;padding:1rem;--tblr-theme-boxed-border-radius: 6px}}.layout-boxed .page{margin:0 auto;max-width:var(--tblr-theme-boxed-width);border-radius:var(--tblr-theme-boxed-border-radius);color:var(--tblr-body-color)}@media(min-width:768px){.layout-boxed .page{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);background:var(--tblr-body-bg)}}.layout-boxed .page>.navbar:first-child{border-top-left-radius:var(--tblr-theme-boxed-border-radius);border-top-right-radius:var(--tblr-theme-boxed-border-radius)}.navbar{--tblr-navbar-bg: var(--tblr-bg-surface);--tblr-navbar-border-width: var(--tblr-border-width);--tblr-navbar-active-border-color: #00857D;--tblr-navbar-active-bg: rgba(0, 0, 0, .2);--tblr-navbar-border-color: var(--tblr-border-color);--tblr-navbar-hover-color: var(--tblr-body-color);align-items:stretch;min-height:3.5rem;box-shadow:inset 0 calc(-1 * var(--tblr-navbar-border-width)) 0 0 var(--tblr-navbar-border-color);background:var(--tblr-navbar-bg);color:var(--tblr-navbar-color)}.navbar-collapse .navbar{flex-grow:1}.navbar.collapsing{min-height:0}.navbar .dropdown-menu{position:absolute;z-index:1030}.navbar .navbar-nav{min-height:3rem}.navbar .navbar-nav .nav-link{position:relative;min-width:2.5rem;min-height:2.5rem;justify-content:center;border-radius:var(--tblr-border-radius)}.navbar .navbar-nav .nav-link .badge{position:absolute;top:.375rem;right:.375rem;transform:translate(50%,-50%)}@media(max-width:575.98px){.navbar-expand-sm .navbar-collapse{flex-direction:column}.navbar-expand-sm .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-sm .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-sm .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-sm .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-sm .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-sm .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-sm .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:576px){.navbar-expand-sm .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-sm .nav-item.active{position:relative}.navbar-expand-sm .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-sm .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-sm.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-sm.navbar-vertical.navbar-right,.navbar-expand-sm.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-sm.navbar-vertical~.navbar,.navbar-expand-sm.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-sm.navbar-vertical.navbar-right~.navbar,.navbar-expand-sm.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-sm.navbar-vertical.navbar-end~.navbar,.navbar-expand-sm.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:767.98px){.navbar-expand-md .navbar-collapse{flex-direction:column}.navbar-expand-md .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-md .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-md .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-md .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-md .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-md .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-md .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:768px){.navbar-expand-md .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-md .nav-item.active{position:relative}.navbar-expand-md .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-md .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-md.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-md.navbar-vertical.navbar-right,.navbar-expand-md.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-md.navbar-vertical~.navbar,.navbar-expand-md.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-md.navbar-vertical.navbar-right~.navbar,.navbar-expand-md.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-md.navbar-vertical.navbar-end~.navbar,.navbar-expand-md.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:991.98px){.navbar-expand-lg .navbar-collapse{flex-direction:column}.navbar-expand-lg .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-lg .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-lg .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-lg .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-lg .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-lg .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-lg .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:992px){.navbar-expand-lg .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-lg .nav-item.active{position:relative}.navbar-expand-lg .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-lg .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-lg.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-lg.navbar-vertical.navbar-right,.navbar-expand-lg.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-lg.navbar-vertical~.navbar,.navbar-expand-lg.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-lg.navbar-vertical.navbar-right~.navbar,.navbar-expand-lg.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-lg.navbar-vertical.navbar-end~.navbar,.navbar-expand-lg.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:1199.98px){.navbar-expand-xl .navbar-collapse{flex-direction:column}.navbar-expand-xl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-xl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-xl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-xl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-xl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-xl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-xl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1200px){.navbar-expand-xl .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-xl .nav-item.active{position:relative}.navbar-expand-xl .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-xl .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-xl.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xl.navbar-vertical.navbar-right,.navbar-expand-xl.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xl.navbar-vertical~.navbar,.navbar-expand-xl.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-xl.navbar-vertical.navbar-right~.navbar,.navbar-expand-xl.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-xl.navbar-vertical.navbar-end~.navbar,.navbar-expand-xl.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}@media(max-width:1399.98px){.navbar-expand-xxl .navbar-collapse{flex-direction:column}.navbar-expand-xxl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand-xxl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand-xxl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand-xxl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand-xxl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand-xxl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand-xxl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1400px){.navbar-expand-xxl .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand-xxl .nav-item.active{position:relative}.navbar-expand-xxl .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand-xxl .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand-xxl.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xxl.navbar-vertical.navbar-right,.navbar-expand-xxl.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand-xxl.navbar-vertical~.navbar,.navbar-expand-xxl.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand-xxl.navbar-vertical.navbar-right~.navbar,.navbar-expand-xxl.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand-xxl.navbar-vertical.navbar-end~.navbar,.navbar-expand-xxl.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}}.navbar-expand .navbar-collapse{flex-direction:column}.navbar-expand .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-expand .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-expand .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-expand .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-expand .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-expand .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-expand .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}.navbar-expand .navbar-collapse{width:auto;flex:1 1 auto}.navbar-expand .nav-item.active{position:relative}.navbar-expand .nav-item.active .nav-link{color:var(--tblr-navbar-active-color)}.navbar-expand .nav-item.active:after{content:"";position:absolute;left:0;right:0;bottom:-.25rem;border:0 var(--tblr-border-style) var(--tblr-navbar-active-border-color);border-bottom-width:2px}.navbar-expand.navbar-vertical{box-shadow:inset calc(-1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand.navbar-vertical.navbar-right,.navbar-expand.navbar-vertical.navbar-end{box-shadow:inset calc(1 * var(--tblr-navbar-border-width)) 0 0 0 var(--tblr-navbar-border-color)}.navbar-expand.navbar-vertical~.navbar,.navbar-expand.navbar-vertical~.page-wrapper{margin-left:18rem}.navbar-expand.navbar-vertical.navbar-right~.navbar,.navbar-expand.navbar-vertical.navbar-right~.page-wrapper,.navbar-expand.navbar-vertical.navbar-end~.navbar,.navbar-expand.navbar-vertical.navbar-end~.page-wrapper{margin-left:0;margin-right:18rem}.navbar-brand{display:inline-flex;align-items:center;font-weight:var(--tblr-font-weight-bold);margin:0;line-height:1;gap:.5rem}.navbar-brand-image{height:2rem;width:auto}.navbar-toggler{border:0;width:2rem;height:2rem;position:relative;display:flex;align-items:center;justify-content:center}.navbar-toggler-icon{height:2px;width:1.25em;background:currentColor;border-radius:10px;transition:top .2s .2s,bottom .2s .2s,transform .2s,opacity 0s .2s}@media(prefers-reduced-motion:reduce){.navbar-toggler-icon{transition:none}}.navbar-toggler-icon{position:relative}.navbar-toggler-icon:before,.navbar-toggler-icon:after{content:"";display:block;height:inherit;width:inherit;border-radius:inherit;background:inherit;position:absolute;left:0;transition:inherit}@media(prefers-reduced-motion:reduce){.navbar-toggler-icon:before,.navbar-toggler-icon:after{transition:none}}.navbar-toggler-icon:before{top:-.45em}.navbar-toggler-icon:after{bottom:-.45em}.navbar-toggler[aria-expanded=true] .navbar-toggler-icon{transform:rotate(45deg);transition:top .3s,bottom .3s,transform .3s .3s,opacity 0s .3s}@media(prefers-reduced-motion:reduce){.navbar-toggler[aria-expanded=true] .navbar-toggler-icon{transition:none}}.navbar-toggler[aria-expanded=true] .navbar-toggler-icon:before{top:0;transform:rotate(-90deg)}.navbar-toggler[aria-expanded=true] .navbar-toggler-icon:after{bottom:0;opacity:0}.navbar-transparent{--tblr-navbar-border-color: transparent !important;background:transparent!important}.navbar-nav{--tblr-nav-link-hover-bg: color-mix(in srgb, var(--tblr-nav-link-color) 4%, transparent);margin:0;padding:0;align-items:stretch}.navbar-nav .nav-item{display:flex;flex-direction:column;justify-content:center}.navbar-side{margin:0;display:flex;flex-direction:row;align-items:center;justify-content:space-around}@media(min-width:576px){.navbar-vertical.navbar-expand-sm{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:576px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-sm{transition:none}}@media(min-width:576px){.navbar-vertical.navbar-expand-sm.navbar-right,.navbar-vertical.navbar-expand-sm.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-sm .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-sm .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-sm .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-sm .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-sm>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-sm~.page{padding-left:18rem}.navbar-vertical.navbar-expand-sm~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-sm.navbar-right~.page,.navbar-vertical.navbar-expand-sm.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-sm .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-sm .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-sm .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-sm .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-sm .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-sm .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:768px){.navbar-vertical.navbar-expand-md{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:768px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-md{transition:none}}@media(min-width:768px){.navbar-vertical.navbar-expand-md.navbar-right,.navbar-vertical.navbar-expand-md.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-md .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-md .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-md .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-md .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-md>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-md~.page{padding-left:18rem}.navbar-vertical.navbar-expand-md~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-md.navbar-right~.page,.navbar-vertical.navbar-expand-md.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-md .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-md .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-md .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-md .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-md .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-md .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:992px){.navbar-vertical.navbar-expand-lg{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:992px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-lg{transition:none}}@media(min-width:992px){.navbar-vertical.navbar-expand-lg.navbar-right,.navbar-vertical.navbar-expand-lg.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-lg .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-lg .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-lg .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-lg .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-lg>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-lg~.page{padding-left:18rem}.navbar-vertical.navbar-expand-lg~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-lg.navbar-right~.page,.navbar-vertical.navbar-expand-lg.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-lg .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-lg .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-lg .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1200px){.navbar-vertical.navbar-expand-xl{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:1200px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-xl{transition:none}}@media(min-width:1200px){.navbar-vertical.navbar-expand-xl.navbar-right,.navbar-vertical.navbar-expand-xl.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-xl .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-xl .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-xl .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-xl .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-xl>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-xl~.page{padding-left:18rem}.navbar-vertical.navbar-expand-xl~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-xl.navbar-right~.page,.navbar-vertical.navbar-expand-xl.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-xl .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-xl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-xl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-xl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-xl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-xl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}@media(min-width:1400px){.navbar-vertical.navbar-expand-xxl{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s;overflow-y:scroll;padding:0}}@media(min-width:1400px)and (prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand-xxl{transition:none}}@media(min-width:1400px){.navbar-vertical.navbar-expand-xxl.navbar-right,.navbar-vertical.navbar-expand-xxl.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand-xxl .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand-xxl .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand-xxl .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand-xxl .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand-xxl>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand-xxl~.page{padding-left:18rem}.navbar-vertical.navbar-expand-xxl~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand-xxl.navbar-right~.page,.navbar-vertical.navbar-expand-xxl.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand-xxl .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand-xxl .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand-xxl .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand-xxl .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand-xxl .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand-xxl .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}}.navbar-vertical.navbar-expand{width:18rem;position:fixed;top:0;left:0;bottom:0;z-index:1030;align-items:flex-start;transition:transform .3s}@media(prefers-reduced-motion:reduce){.navbar-vertical.navbar-expand{transition:none}}.navbar-vertical.navbar-expand{overflow-y:scroll;padding:0}.navbar-vertical.navbar-expand.navbar-right,.navbar-vertical.navbar-expand.navbar-end{left:auto;right:0}.navbar-vertical.navbar-expand .navbar-brand{padding:.75rem 0;justify-content:center}.navbar-vertical.navbar-expand .navbar-collapse{align-items:stretch}.navbar-vertical.navbar-expand .navbar-nav{flex-direction:column;flex-grow:1;min-height:auto}.navbar-vertical.navbar-expand .navbar-nav .nav-link{padding-top:.5rem;padding-bottom:.5rem}.navbar-vertical.navbar-expand>[class^=container]{flex-direction:column;align-items:stretch;min-height:100%;justify-content:flex-start;padding:0}.navbar-vertical.navbar-expand~.page{padding-left:18rem}.navbar-vertical.navbar-expand~.page [class^=container]{padding-left:1.5rem;padding-right:1.5rem}.navbar-vertical.navbar-expand.navbar-right~.page,.navbar-vertical.navbar-expand.navbar-end~.page{padding-left:0;padding-right:18rem}.navbar-vertical.navbar-expand .navbar-collapse{flex-direction:column}.navbar-vertical.navbar-expand .navbar-collapse [class^=container]{flex-direction:column;align-items:stretch;padding:0}.navbar-vertical.navbar-expand .navbar-collapse .navbar-nav{margin-left:0;margin-right:0}.navbar-vertical.navbar-expand .navbar-collapse .navbar-nav .nav-link{padding:.5rem calc(calc(var(--tblr-page-padding) * 2) / 2);justify-content:flex-start}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu-columns{flex-direction:column}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu{padding:0;background:transparent;position:static;color:inherit;box-shadow:none;border:none;min-width:0;margin:0}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item{min-width:0;display:flex;width:auto;padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 1.75rem);color:inherit}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.disabled{color:var(--tblr-disabled-color);pointer-events:none;background-color:transparent}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item.active,.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-item:active{background:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 3.25rem)}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-menu .dropdown-menu .dropdown-menu .dropdown-item{padding-left:calc(calc(calc(var(--tblr-page-padding) * 2) / 2) + 4.75rem)}.navbar-vertical.navbar-expand .navbar-collapse .dropdown-toggle:after{margin-left:auto}.navbar-vertical.navbar-expand .navbar-collapse .nav-item.active:after{border-bottom-width:0;border-left-width:3px;right:auto;top:0;bottom:0}.navbar-overlap:after{content:"";height:9rem;position:absolute;top:100%;left:0;right:0;background:inherit;z-index:-1;box-shadow:inherit}.page{display:flex;flex-direction:column;position:relative;min-height:100%}.page-center{justify-content:center}.page-wrapper{flex:1;display:flex;flex-direction:column}@media print{.page-wrapper{margin:0!important}}.page-wrapper-full .page-body:first-child{margin:0;border-top:0}.page-body{margin-top:var(--tblr-page-padding-y);margin-bottom:var(--tblr-page-padding-y);display:flex;flex-direction:column;flex:1}.page-body-card{background:var(--tblr-bg-surface);border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);padding:var(--tblr-page-padding) 0;margin-bottom:0;flex:1}.page-body~.page-body-card{margin-top:0}.page-cover{background:no-repeat center/cover;min-height:9rem}@media(min-width:768px){.page-cover{min-height:12rem}}@media(min-width:992px){.page-cover{min-height:15rem}}.page-cover-overlay{position:relative}.page-cover-overlay:after{content:"";position:absolute;inset:0;background-image:linear-gradient(180deg,#0000,#0009)}.page-header{display:flex;flex-wrap:wrap;min-height:2.25rem;flex-direction:column;justify-content:center;max-width:100%}.page-wrapper .page-header{margin:var(--tblr-page-padding-y) 0 0}.page-header-border{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);padding:var(--tblr-page-padding-y) 0;margin:0!important;background-color:var(--tblr-bg-surface)}.page-pretitle{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary)}.page-title{margin:0;font-size:var(--tblr-font-size-h2);line-height:var(--tblr-line-height-h2);font-weight:var(--tblr-font-weight-headings);color:inherit;display:flex;align-items:center}.page-title svg{width:1.5rem;height:1.5rem;margin-right:.25rem}.page-title-lg{font-size:1.5rem;line-height:2rem}.page-subtitle{margin-top:.25rem;color:var(--tblr-secondary)}.page-cover{--tblr-page-cover-blur: 20px;--tblr-page-cover-padding: 1rem;min-height:6rem;padding:var(--tblr-page-cover-padding) 0;position:relative;overflow:hidden}.page-cover-img{position:absolute;top:calc(-2 * var(--tblr-page-cover-blur, 0));left:calc(-2 * var(--tblr-page-cover-blur, 0));right:calc(-2 * var(--tblr-page-cover-blur, 0));bottom:calc(-2 * var(--tblr-page-cover-blur, 0));pointer-events:none;filter:blur(var(--tblr-page-cover-blur));object-fit:cover;background-size:cover;background-position:center;z-index:-1}.page-tabs{margin-top:.5rem;position:relative}.page-header-tabs .nav-bordered{border:0}.page-header-tabs+.page-body-card{margin-top:0}.footer{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);background-color:var(--tblr-bg-surface);padding:2rem 0;color:var(--tblr-gray-500);margin-top:auto}.footer-transparent{background-color:transparent;border-top:0}:root:not(.theme-dark):not([data-bs-theme=dark]) .hide-theme-light{display:none!important}:root:not(.theme-dark):not([data-bs-theme=dark]) .img-dark{display:none!important}:root.theme-dark .hide-theme-dark,:root[data-bs-theme=dark] .hide-theme-dark,body[data-bs-theme=dark] [data-bs-theme=light]:root .hide-theme-dark{display:none!important}:root.theme-dark .img-light,:root[data-bs-theme=dark] .img-light,body[data-bs-theme=dark] [data-bs-theme=light]:root .img-light{display:none!important}[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{color-scheme:dark;--tblr-body-color: var(--tblr-gray-200);--tblr-secondary: var(--tblr-gray-400);--tblr-body-bg: var(--tblr-gray-900);--tblr-emphasis-color: #ffffff;--tblr-emphasis-color-rgb: 255, 255, 255;--tblr-bg-forms: var(--tblr-gray-900);--tblr-bg-surface: var(--tblr-gray-800);--tblr-bg-surface-inverted: var(--tblr-gray-100);--tblr-bg-surface-secondary: var(--tblr-gray-900);--tblr-bg-surface-tertiary: var(--tblr-gray-800);--tblr-text-inverted: var(--tblr-gray-800);--tblr-link-color: var(--tblr-primary);--tblr-link-hover-color: color-mix(in srgb, var(--tblr-primary), black 20%);--tblr-active-bg: rgb(34.676744186, 45.8627906977, 61.523255814);--tblr-disabled-color: color-mix(in srgb, var(--tblr-body-color) 40%, transparent);--tblr-border-color: var(--tblr-gray-700);--tblr-border-color-translucent: var( --tblr-dark-mode-border-color-translucent );--tblr-border-dark-color: var(--tblr-dark-mode-border-dark-color);--tblr-border-active-color: var( --tblr-dark-mode-border-active-color );--tblr-btn-color: rgb(27.323255814, 36.1372093023, 48.476744186)}[data-bs-theme=dark] .navbar-brand-autodark .navbar-brand-image{filter:brightness(0) invert(1)}.accordion{--tblr-accordion-color: var(--tblr-body-color);--tblr-accordion-border-color: var(--tblr-border-color);--tblr-accordion-border-radius: var(--tblr-border-radius);--tblr-accordion-inner-border-radius: calc(var(--tblr-border-radius) - (var(--tblr-border-width)));--tblr-accordion-padding-x: 1.25rem;--tblr-accordion-gap: 0;--tblr-accordion-active-color: inherit;--tblr-accordion-btn-color: var(--tblr-accordion-color);--tblr-accordion-btn-bg: transparent;--tblr-accordion-btn-toggle-width: 1.25rem;--tblr-accordion-btn-padding-x: var(--tblr-accordion-padding-x);--tblr-accordion-btn-padding-y: 1rem;--tblr-accordion-btn-font-weight: var(--tblr-font-weight-medium);--tblr-accordion-body-padding-x: var(--tblr-accordion-padding-x);--tblr-accordion-body-padding-y: 1rem;display:flex;flex-direction:column;gap:var(--tblr-accordion-gap)}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--tblr-accordion-btn-padding-y) var(--tblr-accordion-padding-x);color:inherit;text-align:inherit;background-color:transparent;border:0;font-size:inherit;font-weight:var(--tblr-accordion-btn-font-weight);gap:.75rem}.accordion-button:not(.collapsed){border-bottom-color:transparent;box-shadow:none;color:var(--tblr-accordion-active-color)}.accordion-header{margin:0;position:relative;display:flex;gap:1rem;align-items:center;width:100%;color:var(--tblr-accordion-btn-color);text-align:left;background-color:transparent;border:0;overflow-anchor:none;transition:transform .3s}.accordion-header:hover{z-index:2}.accordion-header:focus{z-index:3;outline:0;box-shadow:var(--tblr-accordion-btn-focus-box-shadow)}.accordion-header:focus:not(:focus-visible){outline:none;box-shadow:none}.accordion-button-icon{color:var(--tblr-secondary)}.accordion-button-toggle{display:flex;line-height:1;transition:.3s transform;margin-left:auto;margin-right:0;color:var(--tblr-secondary);width:var(--tblr-accordion-btn-toggle-width);height:var(--tblr-accordion-btn-toggle-width)}.accordion-button:not(.collapsed) .accordion-button-toggle{transform:rotate(-180deg);color:var(--tblr-accordion-active-color)}.accordion-button-toggle path{transition:.3s opacity}.accordion-button:not(.collapsed) .accordion-button-toggle-plus path:first-child{opacity:0}.accordion-item{color:var(--tblr-accordion-color);border:var(--tblr-border-width) solid var(--tblr-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--tblr-accordion-border-radius);border-top-right-radius:var(--tblr-accordion-border-radius)}.accordion-item:first-of-type>.accordion-header{border-top-left-radius:var(--tblr-accordion-inner-border-radius);border-top-right-radius:var(--tblr-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--tblr-accordion-border-radius);border-bottom-left-radius:var(--tblr-accordion-border-radius)}.accordion-item:last-of-type>.accordion-header.collapsed{border-bottom-right-radius:var(--tblr-accordion-inner-border-radius);border-bottom-left-radius:var(--tblr-accordion-inner-border-radius)}.accordion-item:last-of-type>.accordion-collapse{border-bottom-right-radius:var(--tblr-accordion-border-radius);border-bottom-left-radius:var(--tblr-accordion-border-radius)}.accordion-body{color:var(--tblr-secondary);padding:0 var(--tblr-accordion-body-padding-x) var(--tblr-accordion-body-padding-y)}.accordion-flush>.accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush>.accordion-item:first-child{border-top:0}.accordion-flush>.accordion-item:last-child{border-bottom:0}.accordion-flush>.accordion-item>.accordion-collapse,.accordion-flush>.accordion-item>.accordion-header .accordion-button,.accordion-flush>.accordion-item>.accordion-header .accordion-button.collapsed{border-radius:0}.accordion-tabs{--tblr-accordion-gap: .75rem}.accordion-tabs>.accordion-item{border:var(--tblr-border-width) solid var(--tblr-accordion-border-color);border-radius:var(--tblr-accordion-border-radius)}.accordion-inverted .accordion-button-toggle{order:-1;margin-left:0}.alert{--tblr-alert-color: var(--tblr-body-color);--tblr-alert-bg: color-mix(in srgb, var(--tblr-alert-color) 10%, transparent);--tblr-alert-padding-x: 1rem;--tblr-alert-padding-y: .75rem;--tblr-alert-margin-bottom: 1rem;--tblr-alert-border-color: color-mix(in srgb, var(--tblr-alert-color) 20%, transparent);--tblr-alert-border: var(--tblr-border-width) solid var(--tblr-alert-border-color);--tblr-alert-border-radius: var(--tblr-border-radius);--tblr-alert-link-color: inherit;--tblr-alert-heading-font-weight: var(--tblr-font-weight-medium);position:relative;padding:var(--tblr-alert-padding-y) var(--tblr-alert-padding-x);margin-bottom:var(--tblr-alert-margin-bottom);background-color:color-mix(in srgb,var(--tblr-alert-bg),var(--tblr-bg-surface));border-radius:var(--tblr-alert-border-radius);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-alert-border-color);display:flex;flex-direction:row;gap:1rem}.alert-heading{color:inherit;margin-bottom:.25rem;font-weight:var(--tblr-alert-heading-font-weight)}.alert-description{color:var(--tblr-secondary)}.alert-icon{color:var(--tblr-alert-color);width:1.25rem!important;height:1.25rem!important}.alert-action{color:var(--tblr-alert-color);text-decoration:underline}.alert-action:hover{text-decoration:none}.alert-list{margin:0}.alert-link{font-weight:var(--tblr-font-weight-bold);color:var(--tblr-alert-link-color)}.alert-link,.alert-link:hover{color:var(--tblr-alert-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:calc(var(--tblr-alert-padding-x) / 2 - 1px);right:calc(var(--tblr-alert-padding-y) / 2 - 1px);z-index:1;padding:calc(var(--tblr-alert-padding-y) * 1.25) var(--tblr-alert-padding-x)}.alert-important{border-color:var(--tblr-alert-color);background-color:var(--tblr-alert-color);color:var(--tblr-white)}.alert-important .alert-description,.alert-important .alert-icon{color:inherit}.alert-minor{background:transparent;border-color:var(--tblr-border-color)}.alert-primary{--tblr-alert-color: var(--tblr-primary)}.alert-secondary{--tblr-alert-color: var(--tblr-secondary)}.alert-success{--tblr-alert-color: var(--tblr-success)}.alert-info{--tblr-alert-color: var(--tblr-info)}.alert-warning{--tblr-alert-color: var(--tblr-warning)}.alert-danger{--tblr-alert-color: var(--tblr-danger)}.alert-light{--tblr-alert-color: var(--tblr-light)}.alert-dark{--tblr-alert-color: var(--tblr-dark)}.alert-muted{--tblr-alert-color: var(--tblr-muted)}.alert-blue{--tblr-alert-color: var(--tblr-blue)}.alert-azure{--tblr-alert-color: var(--tblr-azure)}.alert-indigo{--tblr-alert-color: var(--tblr-indigo)}.alert-purple{--tblr-alert-color: var(--tblr-purple)}.alert-pink{--tblr-alert-color: var(--tblr-pink)}.alert-red{--tblr-alert-color: var(--tblr-red)}.alert-orange{--tblr-alert-color: var(--tblr-orange)}.alert-yellow{--tblr-alert-color: var(--tblr-yellow)}.alert-lime{--tblr-alert-color: var(--tblr-lime)}.alert-green{--tblr-alert-color: var(--tblr-green)}.alert-teal{--tblr-alert-color: var(--tblr-teal)}.alert-cyan{--tblr-alert-color: var(--tblr-cyan)}.avatar{--tblr-avatar-size: var(--tblr-avatar-list-size, 2.5rem);--tblr-avatar-status-size: .75rem;--tblr-avatar-bg: var(--tblr-bg-surface-secondary);--tblr-avatar-box-shadow-color: var(--tblr-border-color-translucent);--tblr-avatar-box-shadow: inset 0 0 0 1px var(--tblr-avatar-box-shadow-color);--tblr-avatar-font-size: 1rem;--tblr-avatar-icon-size: 1.5rem;--tblr-avatar-brand-size: 1.25rem;position:relative;width:var(--tblr-avatar-size);height:var(--tblr-avatar-size);font-size:var(--tblr-avatar-font-size);font-weight:var(--tblr-font-weight-medium);line-height:1;display:inline-flex;align-items:center;justify-content:center;color:var(--tblr-secondary);text-align:center;text-transform:uppercase;vertical-align:bottom;user-select:none;background:var(--tblr-avatar-bg) no-repeat center/cover;border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-avatar-box-shadow);transition:color .3s,background-color .3s,box-shadow .3s}.avatar .icon{width:var(--tblr-avatar-icon-size);height:var(--tblr-avatar-icon-size)}.avatar .badge{position:absolute;right:0;bottom:0;border-radius:100rem;box-shadow:0 0 0 calc(var(--tblr-avatar-status-size) / 4) var(--tblr-bg-surface)}a.avatar{cursor:pointer}a.avatar:hover{color:var(--tblr-primary);--tblr-avatar-box-shadow-color: var(--tblr-primary)}.avatar-rounded{border-radius:100rem}.avatar-xxs{--tblr-avatar-size: 1rem;--tblr-avatar-status-size: .25rem;--tblr-avatar-font-size: .5rem;--tblr-avatar-icon-size: .5rem;--tblr-avatar-brand-size: .5rem}.avatar-xxs .badge:empty{width:.25rem;height:.25rem}.avatar-xs{--tblr-avatar-size: 1.25rem;--tblr-avatar-status-size: .375rem;--tblr-avatar-font-size: .625rem;--tblr-avatar-icon-size: .75rem;--tblr-avatar-brand-size: .75rem}.avatar-xs .badge:empty{width:.375rem;height:.375rem}.avatar-sm{--tblr-avatar-size: 2rem;--tblr-avatar-status-size: .5rem;--tblr-avatar-font-size: .75rem;--tblr-avatar-icon-size: 1.5rem;--tblr-avatar-brand-size: 1rem}.avatar-sm .badge:empty{width:.5rem;height:.5rem}.avatar-md{--tblr-avatar-size: 2.5rem;--tblr-avatar-status-size: .75rem;--tblr-avatar-font-size: .875rem;--tblr-avatar-icon-size: 1.5rem;--tblr-avatar-brand-size: 1.25rem}.avatar-md .badge:empty{width:.75rem;height:.75rem}.avatar-lg{--tblr-avatar-size: 3rem;--tblr-avatar-status-size: .75rem;--tblr-avatar-font-size: 1.25rem;--tblr-avatar-icon-size: 2rem;--tblr-avatar-brand-size: 1.25rem}.avatar-lg .badge:empty{width:.75rem;height:.75rem}.avatar-xl{--tblr-avatar-size: 5rem;--tblr-avatar-status-size: 1rem;--tblr-avatar-font-size: 2rem;--tblr-avatar-icon-size: 3rem;--tblr-avatar-brand-size: 1.25rem}.avatar-xl .badge:empty{width:1rem;height:1rem}.avatar-2xl{--tblr-avatar-size: 7rem;--tblr-avatar-status-size: 1rem;--tblr-avatar-font-size: 3rem;--tblr-avatar-icon-size: 5rem;--tblr-avatar-brand-size: 2rem}.avatar-2xl .badge:empty{width:1rem;height:1rem}.avatar-list{--tblr-avatar-list-size: 2.5rem;--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.avatar-list a.avatar:hover{z-index:1}.avatar-list-stacked{display:block;--tblr-list-gap: 0}.avatar-list-stacked .avatar{margin-right:calc(-.5 * var(--tblr-avatar-size))!important;box-shadow:var(--tblr-avatar-box-shadow),0 0 0 2px var(--tblr-card-bg, var(--tblr-bg-surface))}.avatar-list-xxs{--tblr-avatar-list-size: 1rem}.avatar-list-xs{--tblr-avatar-list-size: 1.25rem}.avatar-list-sm{--tblr-avatar-list-size: 2rem}.avatar-list-md{--tblr-avatar-list-size: 2.5rem}.avatar-list-lg{--tblr-avatar-list-size: 3rem}.avatar-list-xl{--tblr-avatar-list-size: 5rem}.avatar-list-2xl{--tblr-avatar-list-size: 7rem}.avatar-upload{border:var(--tblr-border-width) dashed var(--tblr-border-color);background:var(--tblr-bg-forms);box-shadow:none;flex-direction:column;transition:color .3s,background-color .3s}@media(prefers-reduced-motion:reduce){.avatar-upload{transition:none}}.avatar-upload svg{width:1.5rem;height:1.5rem;stroke-width:1}.avatar-upload:hover{border-color:var(--tblr-primary);color:var(--tblr-primary);text-decoration:none}.avatar-upload-text{font-size:.625rem;line-height:1;margin-top:.25rem}.avatar-cover{margin-top:calc(-.5 * var(--tblr-avatar-size));box-shadow:0 0 0 .25rem var(--tblr-card-bg, var(--tblr-body-bg))}.avatar-brand{width:var(--tblr-avatar-brand-size);height:var(--tblr-avatar-brand-size);position:absolute;right:-2px;bottom:-2px;z-index:1000;background:var(--tblr-bg-surface);border-radius:var(--tblr-border-radius);border:1px solid var(--tblr-border-color)}.badge{--tblr-badge-padding-x: .5em;--tblr-badge-padding-y: .25em;--tblr-badge-font-size: .85714285em;--tblr-badge-font-weight: var(--tblr-font-weight-medium);--tblr-badge-color: var(--tblr-secondary);--tblr-badge-border-radius: var(--tblr-border-radius);--tblr-badge-icon-size: 1em;--tblr-badge-line-height: 1;display:inline-flex;padding:var(--tblr-badge-padding-y) var(--tblr-badge-padding-x);font-weight:var(--tblr-badge-font-weight);font-size:var(--tblr-badge-font-size);color:var(--tblr-badge-color);text-align:center;white-space:nowrap;justify-content:center;align-items:center;gap:.25rem;background:var(--tblr-bg-surface-secondary);overflow:hidden;user-select:none;border:var(--tblr-border-width) var(--tblr-border-style) transparent;border-radius:var(--tblr-badge-border-radius);min-width:calc(1em + var(--tblr-badge-padding-y) * 2 + 2px);letter-spacing:.04em;vertical-align:bottom;line-height:var(--tblr-badge-line-height)}a.badge{background:var(--tblr-bg-surface-secondary)}.badge .icon{width:1em;height:1em;font-size:var(--tblr-badge-icon-size);stroke-width:2}.badge:empty,.badge-dot{display:inline-block;width:10px;height:10px;min-width:0;min-height:auto;padding:0;border-radius:100rem;vertical-align:baseline}.badge-outline{background-color:transparent;border:var(--tblr-border-width) var(--tblr-border-style) currentColor}.badge-pill{border-radius:100rem}.badges-list{--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.badge-notification{position:absolute!important;top:0!important;right:0!important;transform:translate(50%,-50%);z-index:1}.badge-blink{animation:blink 2s infinite}.badge-sm{--tblr-badge-font-size: .71428571em;--tblr-badge-icon-size: 1em;--tblr-badge-padding-y: 2px;--tblr-badge-padding-x: .25rem}.badge-lg{--tblr-badge-font-size: 1em;--tblr-badge-icon-size: 1em;--tblr-badge-padding-y: .25rem;--tblr-badge-padding-x: .5rem}.badge-icononly{--tblr-badge-padding-x: 0}.breadcrumb{--tblr-breadcrumb-padding-x: 0;--tblr-breadcrumb-padding-y: 0;--tblr-breadcrumb-margin-bottom: 1rem;--tblr-breadcrumb-font-size: ;--tblr-breadcrumb-bg: ;--tblr-breadcrumb-border-radius: ;--tblr-breadcrumb-divider-color: var(--tblr-gray-500);--tblr-breadcrumb-item-padding-x: .5rem;--tblr-breadcrumb-item-active-color: inherit;--tblr-breadcrumb-item-active-font-weight: var(--tblr-font-weight-bold);--tblr-breadcrumb-item-disabled-color: var(--tblr-disabled-color);--tblr-breadcrumb-link-color: var(--tblr-link-color);display:flex;flex-wrap:wrap;font-size:var(--tblr-breadcrumb-font-size);list-style:none;background-color:var(--tblr-breadcrumb-bg);border-radius:var(--tblr-breadcrumb-border-radius);padding:0;margin:0;background:transparent}.breadcrumb a{color:var(--tblr-breadcrumb-link-color)}.breadcrumb a:hover{text-decoration:underline}.breadcrumb-muted{--tblr-breadcrumb-link-color: var(--tblr-secondary)}.breadcrumb-item.active{color:var(--tblr-breadcrumb-item-active-color);font-weight:var(--tblr-breadcrumb-item-active-font-weight)}.breadcrumb-item.active a{color:inherit;pointer-events:none}.breadcrumb-item.disabled{color:var(--tblr-breadcrumb-item-disabled-color)}.breadcrumb-item.disabled:before{color:inherit}.breadcrumb-item.disabled a{color:inherit;pointer-events:none}.breadcrumb-item+.breadcrumb-item{padding-left:var(--tblr-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item:before{float:left;padding-right:var(--tblr-breadcrumb-item-padding-x);color:var(--tblr-breadcrumb-divider-color);content:var(--tblr-breadcrumb-divider, "/")}.breadcrumb-dots{--tblr-breadcrumb-divider: "\b7"}.breadcrumb-arrows{--tblr-breadcrumb-divider: "\203a"}.breadcrumb-bullets{--tblr-breadcrumb-divider: "\2022"}.btn{--tblr-btn-icon-size: 1.25rem;--tblr-btn-icon-color: inherit;--tblr-btn-bg: var(--tblr-bg-surface);--tblr-btn-color: var(--tblr-body-color);--tblr-btn-border-color: var(--tblr-border-color);--tblr-btn-hover-bg: var(--tblr-btn-bg);--tblr-btn-hover-border-color: var(--tblr-border-active-color);--tblr-btn-active-color: var(--tblr-primary);--tblr-btn-active-bg: rgba(var(--tblr-primary-rgb), .04);--tblr-btn-active-border-color: var(--tblr-primary);display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;box-shadow:var(--tblr-btn-box-shadow);position:relative;min-width:calc(var(--tblr-btn-line-height) * 1 + var(--tblr-btn-padding-y) * 2 + var(--tblr-btn-border-width) * 2);min-height:calc(var(--tblr-btn-line-height) * 1 + var(--tblr-btn-padding-y) * 2 + var(--tblr-btn-border-width) * 2)}.btn .icon{width:var(--tblr-btn-icon-size);height:var(--tblr-btn-icon-size);min-width:var(--tblr-btn-icon-size);font-size:var(--tblr-btn-icon-size);margin:0 calc(var(--tblr-btn-padding-x) / 2) 0 calc(var(--tblr-btn-padding-x) / -4);vertical-align:bottom;color:var(--tblr-btn-icon-color)}.btn .avatar{width:var(--tblr-btn-icon-size);height:var(--tblr-btn-icon-size);margin:0 calc(var(--tblr-btn-padding-x) / 2) 0 calc(var(--tblr-btn-padding-x) / -4)}.btn .icon-right,.btn .icon-end{margin:0 calc(var(--tblr-btn-padding-x) / -4) 0 calc(var(--tblr-btn-padding-x) / 2)}.btn .badge{top:auto}.btn-check+.btn:hover{color:var(--tblr-btn-hover-color);background-color:var(--tblr-btn-hover-bg);border-color:var(--tblr-btn-hover-border-color)}.btn-link{color:#009f95;background-color:transparent;border-color:transparent;box-shadow:none}.btn-link .icon{color:inherit}.btn-link:hover{color:#006a64;border-color:transparent}.btn-primary{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-primary-fg, #ffffff);--tblr-btn-bg: var(--tblr-primary);--tblr-btn-hover-color: var(--tblr-primary-fg);--tblr-btn-hover-bg: var(--tblr-primary-darken);--tblr-btn-active-color: var(--tblr-primary-fg);--tblr-btn-active-bg: var(--tblr-primary-darken);--tblr-btn-disabled-bg: var(--tblr-primary);--tblr-btn-disabled-color: var(--tblr-primary-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-primary,.btn-outline.btn-primary{--tblr-btn-color: var(--tblr-primary);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-primary);--tblr-btn-hover-color: var(--tblr-primary-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-primary);--tblr-btn-active-color: var(--tblr-primary-fg);--tblr-btn-active-bg: var(--tblr-primary);--tblr-btn-active-border-color: var(--tblr-primary);--tblr-btn-disabled-color: var(--tblr-primary);--tblr-btn-disabled-border-color: var(--tblr-primary)}.btn-ghost-primary,.btn-ghost.btn-primary{--tblr-btn-color: var(--tblr-primary);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-primary-fg);--tblr-btn-hover-bg: var(--tblr-primary);--tblr-btn-hover-border-color: var(--tblr-primary);--tblr-btn-active-color: var(--tblr-primary-fg);--tblr-btn-active-bg: var(--tblr-primary);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-primary);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-secondary,.btn-grey,.btn-gray{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-secondary-fg, #ffffff);--tblr-btn-bg: var(--tblr-secondary);--tblr-btn-hover-color: var(--tblr-secondary-fg);--tblr-btn-hover-bg: var(--tblr-secondary-darken);--tblr-btn-active-color: var(--tblr-secondary-fg);--tblr-btn-active-bg: var(--tblr-secondary-darken);--tblr-btn-disabled-bg: var(--tblr-secondary);--tblr-btn-disabled-color: var(--tblr-secondary-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-secondary,.btn-outline.btn-secondary,.btn-outline.btn-grey,.btn-outline.btn-gray{--tblr-btn-color: var(--tblr-secondary);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-secondary);--tblr-btn-hover-color: var(--tblr-secondary-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-secondary);--tblr-btn-active-color: var(--tblr-secondary-fg);--tblr-btn-active-bg: var(--tblr-secondary);--tblr-btn-active-border-color: var(--tblr-secondary);--tblr-btn-disabled-color: var(--tblr-secondary);--tblr-btn-disabled-border-color: var(--tblr-secondary)}.btn-ghost-secondary,.btn-ghost.btn-secondary,.btn-ghost.btn-grey,.btn-ghost.btn-gray{--tblr-btn-color: var(--tblr-secondary);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-secondary-fg);--tblr-btn-hover-bg: var(--tblr-secondary);--tblr-btn-hover-border-color: var(--tblr-secondary);--tblr-btn-active-color: var(--tblr-secondary-fg);--tblr-btn-active-bg: var(--tblr-secondary);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-secondary);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-success{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-success-fg, #ffffff);--tblr-btn-bg: var(--tblr-success);--tblr-btn-hover-color: var(--tblr-success-fg);--tblr-btn-hover-bg: var(--tblr-success-darken);--tblr-btn-active-color: var(--tblr-success-fg);--tblr-btn-active-bg: var(--tblr-success-darken);--tblr-btn-disabled-bg: var(--tblr-success);--tblr-btn-disabled-color: var(--tblr-success-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-success,.btn-outline.btn-success{--tblr-btn-color: var(--tblr-success);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-success);--tblr-btn-hover-color: var(--tblr-success-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-success);--tblr-btn-active-color: var(--tblr-success-fg);--tblr-btn-active-bg: var(--tblr-success);--tblr-btn-active-border-color: var(--tblr-success);--tblr-btn-disabled-color: var(--tblr-success);--tblr-btn-disabled-border-color: var(--tblr-success)}.btn-ghost-success,.btn-ghost.btn-success{--tblr-btn-color: var(--tblr-success);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-success-fg);--tblr-btn-hover-bg: var(--tblr-success);--tblr-btn-hover-border-color: var(--tblr-success);--tblr-btn-active-color: var(--tblr-success-fg);--tblr-btn-active-bg: var(--tblr-success);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-success);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-info{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-info-fg, #ffffff);--tblr-btn-bg: var(--tblr-info);--tblr-btn-hover-color: var(--tblr-info-fg);--tblr-btn-hover-bg: var(--tblr-info-darken);--tblr-btn-active-color: var(--tblr-info-fg);--tblr-btn-active-bg: var(--tblr-info-darken);--tblr-btn-disabled-bg: var(--tblr-info);--tblr-btn-disabled-color: var(--tblr-info-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-info,.btn-outline.btn-info{--tblr-btn-color: var(--tblr-info);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-info);--tblr-btn-hover-color: var(--tblr-info-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-info);--tblr-btn-active-color: var(--tblr-info-fg);--tblr-btn-active-bg: var(--tblr-info);--tblr-btn-active-border-color: var(--tblr-info);--tblr-btn-disabled-color: var(--tblr-info);--tblr-btn-disabled-border-color: var(--tblr-info)}.btn-ghost-info,.btn-ghost.btn-info{--tblr-btn-color: var(--tblr-info);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-info-fg);--tblr-btn-hover-bg: var(--tblr-info);--tblr-btn-hover-border-color: var(--tblr-info);--tblr-btn-active-color: var(--tblr-info-fg);--tblr-btn-active-bg: var(--tblr-info);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-info);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-warning{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-warning-fg, #ffffff);--tblr-btn-bg: var(--tblr-warning);--tblr-btn-hover-color: var(--tblr-warning-fg);--tblr-btn-hover-bg: var(--tblr-warning-darken);--tblr-btn-active-color: var(--tblr-warning-fg);--tblr-btn-active-bg: var(--tblr-warning-darken);--tblr-btn-disabled-bg: var(--tblr-warning);--tblr-btn-disabled-color: var(--tblr-warning-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-warning,.btn-outline.btn-warning{--tblr-btn-color: var(--tblr-warning);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-warning);--tblr-btn-hover-color: var(--tblr-warning-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-warning);--tblr-btn-active-color: var(--tblr-warning-fg);--tblr-btn-active-bg: var(--tblr-warning);--tblr-btn-active-border-color: var(--tblr-warning);--tblr-btn-disabled-color: var(--tblr-warning);--tblr-btn-disabled-border-color: var(--tblr-warning)}.btn-ghost-warning,.btn-ghost.btn-warning{--tblr-btn-color: var(--tblr-warning);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-warning-fg);--tblr-btn-hover-bg: var(--tblr-warning);--tblr-btn-hover-border-color: var(--tblr-warning);--tblr-btn-active-color: var(--tblr-warning-fg);--tblr-btn-active-bg: var(--tblr-warning);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-warning);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-danger{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-danger-fg, #ffffff);--tblr-btn-bg: var(--tblr-danger);--tblr-btn-hover-color: var(--tblr-danger-fg);--tblr-btn-hover-bg: var(--tblr-danger-darken);--tblr-btn-active-color: var(--tblr-danger-fg);--tblr-btn-active-bg: var(--tblr-danger-darken);--tblr-btn-disabled-bg: var(--tblr-danger);--tblr-btn-disabled-color: var(--tblr-danger-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-danger,.btn-outline.btn-danger{--tblr-btn-color: var(--tblr-danger);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-danger);--tblr-btn-hover-color: var(--tblr-danger-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-danger);--tblr-btn-active-color: var(--tblr-danger-fg);--tblr-btn-active-bg: var(--tblr-danger);--tblr-btn-active-border-color: var(--tblr-danger);--tblr-btn-disabled-color: var(--tblr-danger);--tblr-btn-disabled-border-color: var(--tblr-danger)}.btn-ghost-danger,.btn-ghost.btn-danger{--tblr-btn-color: var(--tblr-danger);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-danger-fg);--tblr-btn-hover-bg: var(--tblr-danger);--tblr-btn-hover-border-color: var(--tblr-danger);--tblr-btn-active-color: var(--tblr-danger-fg);--tblr-btn-active-bg: var(--tblr-danger);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-danger);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-light,.btn-white{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-light-fg, #ffffff);--tblr-btn-bg: var(--tblr-light);--tblr-btn-hover-color: var(--tblr-light-fg);--tblr-btn-hover-bg: var(--tblr-light-darken);--tblr-btn-active-color: var(--tblr-light-fg);--tblr-btn-active-bg: var(--tblr-light-darken);--tblr-btn-disabled-bg: var(--tblr-light);--tblr-btn-disabled-color: var(--tblr-light-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-light,.btn-outline.btn-light,.btn-outline.btn-white{--tblr-btn-color: var(--tblr-light);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-light);--tblr-btn-hover-color: var(--tblr-light-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-light);--tblr-btn-active-color: var(--tblr-light-fg);--tblr-btn-active-bg: var(--tblr-light);--tblr-btn-active-border-color: var(--tblr-light);--tblr-btn-disabled-color: var(--tblr-light);--tblr-btn-disabled-border-color: var(--tblr-light)}.btn-ghost-light,.btn-ghost.btn-light,.btn-ghost.btn-white{--tblr-btn-color: var(--tblr-light);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-light-fg);--tblr-btn-hover-bg: var(--tblr-light);--tblr-btn-hover-border-color: var(--tblr-light);--tblr-btn-active-color: var(--tblr-light-fg);--tblr-btn-active-bg: var(--tblr-light);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-light);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-dark,.btn-black{--tblr-btn-border-color: var(--tblr-dark-mode-border-color);--tblr-btn-hover-border-color: var(--tblr-dark-mode-border-active-color);--tblr-btn-active-border-color: var(--tblr-dark-mode-border-active-color);--tblr-btn-color: var(--tblr-dark-fg, #ffffff);--tblr-btn-bg: var(--tblr-dark);--tblr-btn-hover-color: var(--tblr-dark-fg);--tblr-btn-hover-bg: var(--tblr-dark-darken);--tblr-btn-active-color: var(--tblr-dark-fg);--tblr-btn-active-bg: var(--tblr-dark-darken);--tblr-btn-disabled-bg: var(--tblr-dark);--tblr-btn-disabled-color: var(--tblr-dark-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-dark,.btn-outline.btn-dark,.btn-outline.btn-black{--tblr-btn-color: var(--tblr-dark);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-dark);--tblr-btn-hover-color: var(--tblr-dark-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-dark);--tblr-btn-active-color: var(--tblr-dark-fg);--tblr-btn-active-bg: var(--tblr-dark);--tblr-btn-active-border-color: var(--tblr-dark);--tblr-btn-disabled-color: var(--tblr-dark);--tblr-btn-disabled-border-color: var(--tblr-dark)}.btn-ghost-dark,.btn-ghost.btn-dark,.btn-ghost.btn-black{--tblr-btn-color: var(--tblr-dark);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-dark-fg);--tblr-btn-hover-bg: var(--tblr-dark);--tblr-btn-hover-border-color: var(--tblr-dark);--tblr-btn-active-color: var(--tblr-dark-fg);--tblr-btn-active-bg: var(--tblr-dark);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-dark);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-muted{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-muted-fg, #ffffff);--tblr-btn-bg: var(--tblr-muted);--tblr-btn-hover-color: var(--tblr-muted-fg);--tblr-btn-hover-bg: var(--tblr-muted-darken);--tblr-btn-active-color: var(--tblr-muted-fg);--tblr-btn-active-bg: var(--tblr-muted-darken);--tblr-btn-disabled-bg: var(--tblr-muted);--tblr-btn-disabled-color: var(--tblr-muted-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-muted,.btn-outline.btn-muted{--tblr-btn-color: var(--tblr-muted);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-muted);--tblr-btn-hover-color: var(--tblr-muted-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-muted);--tblr-btn-active-color: var(--tblr-muted-fg);--tblr-btn-active-bg: var(--tblr-muted);--tblr-btn-active-border-color: var(--tblr-muted);--tblr-btn-disabled-color: var(--tblr-muted);--tblr-btn-disabled-border-color: var(--tblr-muted)}.btn-ghost-muted,.btn-ghost.btn-muted{--tblr-btn-color: var(--tblr-muted);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-muted-fg);--tblr-btn-hover-bg: var(--tblr-muted);--tblr-btn-hover-border-color: var(--tblr-muted);--tblr-btn-active-color: var(--tblr-muted-fg);--tblr-btn-active-bg: var(--tblr-muted);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-muted);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-blue{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-blue-fg, #ffffff);--tblr-btn-bg: var(--tblr-blue);--tblr-btn-hover-color: var(--tblr-blue-fg);--tblr-btn-hover-bg: var(--tblr-blue-darken);--tblr-btn-active-color: var(--tblr-blue-fg);--tblr-btn-active-bg: var(--tblr-blue-darken);--tblr-btn-disabled-bg: var(--tblr-blue);--tblr-btn-disabled-color: var(--tblr-blue-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-blue,.btn-outline.btn-blue{--tblr-btn-color: var(--tblr-blue);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-blue);--tblr-btn-hover-color: var(--tblr-blue-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-blue);--tblr-btn-active-color: var(--tblr-blue-fg);--tblr-btn-active-bg: var(--tblr-blue);--tblr-btn-active-border-color: var(--tblr-blue);--tblr-btn-disabled-color: var(--tblr-blue);--tblr-btn-disabled-border-color: var(--tblr-blue)}.btn-ghost-blue,.btn-ghost.btn-blue{--tblr-btn-color: var(--tblr-blue);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-blue-fg);--tblr-btn-hover-bg: var(--tblr-blue);--tblr-btn-hover-border-color: var(--tblr-blue);--tblr-btn-active-color: var(--tblr-blue-fg);--tblr-btn-active-bg: var(--tblr-blue);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-blue);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-azure{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-azure-fg, #ffffff);--tblr-btn-bg: var(--tblr-azure);--tblr-btn-hover-color: var(--tblr-azure-fg);--tblr-btn-hover-bg: var(--tblr-azure-darken);--tblr-btn-active-color: var(--tblr-azure-fg);--tblr-btn-active-bg: var(--tblr-azure-darken);--tblr-btn-disabled-bg: var(--tblr-azure);--tblr-btn-disabled-color: var(--tblr-azure-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-azure,.btn-outline.btn-azure{--tblr-btn-color: var(--tblr-azure);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-azure);--tblr-btn-hover-color: var(--tblr-azure-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-azure);--tblr-btn-active-color: var(--tblr-azure-fg);--tblr-btn-active-bg: var(--tblr-azure);--tblr-btn-active-border-color: var(--tblr-azure);--tblr-btn-disabled-color: var(--tblr-azure);--tblr-btn-disabled-border-color: var(--tblr-azure)}.btn-ghost-azure,.btn-ghost.btn-azure{--tblr-btn-color: var(--tblr-azure);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-azure-fg);--tblr-btn-hover-bg: var(--tblr-azure);--tblr-btn-hover-border-color: var(--tblr-azure);--tblr-btn-active-color: var(--tblr-azure-fg);--tblr-btn-active-bg: var(--tblr-azure);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-azure);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-indigo{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-indigo-fg, #ffffff);--tblr-btn-bg: var(--tblr-indigo);--tblr-btn-hover-color: var(--tblr-indigo-fg);--tblr-btn-hover-bg: var(--tblr-indigo-darken);--tblr-btn-active-color: var(--tblr-indigo-fg);--tblr-btn-active-bg: var(--tblr-indigo-darken);--tblr-btn-disabled-bg: var(--tblr-indigo);--tblr-btn-disabled-color: var(--tblr-indigo-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-indigo,.btn-outline.btn-indigo{--tblr-btn-color: var(--tblr-indigo);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-indigo);--tblr-btn-hover-color: var(--tblr-indigo-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-indigo);--tblr-btn-active-color: var(--tblr-indigo-fg);--tblr-btn-active-bg: var(--tblr-indigo);--tblr-btn-active-border-color: var(--tblr-indigo);--tblr-btn-disabled-color: var(--tblr-indigo);--tblr-btn-disabled-border-color: var(--tblr-indigo)}.btn-ghost-indigo,.btn-ghost.btn-indigo{--tblr-btn-color: var(--tblr-indigo);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-indigo-fg);--tblr-btn-hover-bg: var(--tblr-indigo);--tblr-btn-hover-border-color: var(--tblr-indigo);--tblr-btn-active-color: var(--tblr-indigo-fg);--tblr-btn-active-bg: var(--tblr-indigo);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-indigo);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-purple{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-purple-fg, #ffffff);--tblr-btn-bg: var(--tblr-purple);--tblr-btn-hover-color: var(--tblr-purple-fg);--tblr-btn-hover-bg: var(--tblr-purple-darken);--tblr-btn-active-color: var(--tblr-purple-fg);--tblr-btn-active-bg: var(--tblr-purple-darken);--tblr-btn-disabled-bg: var(--tblr-purple);--tblr-btn-disabled-color: var(--tblr-purple-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-purple,.btn-outline.btn-purple{--tblr-btn-color: var(--tblr-purple);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-purple);--tblr-btn-hover-color: var(--tblr-purple-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-purple);--tblr-btn-active-color: var(--tblr-purple-fg);--tblr-btn-active-bg: var(--tblr-purple);--tblr-btn-active-border-color: var(--tblr-purple);--tblr-btn-disabled-color: var(--tblr-purple);--tblr-btn-disabled-border-color: var(--tblr-purple)}.btn-ghost-purple,.btn-ghost.btn-purple{--tblr-btn-color: var(--tblr-purple);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-purple-fg);--tblr-btn-hover-bg: var(--tblr-purple);--tblr-btn-hover-border-color: var(--tblr-purple);--tblr-btn-active-color: var(--tblr-purple-fg);--tblr-btn-active-bg: var(--tblr-purple);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-purple);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-pink{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-pink-fg, #ffffff);--tblr-btn-bg: var(--tblr-pink);--tblr-btn-hover-color: var(--tblr-pink-fg);--tblr-btn-hover-bg: var(--tblr-pink-darken);--tblr-btn-active-color: var(--tblr-pink-fg);--tblr-btn-active-bg: var(--tblr-pink-darken);--tblr-btn-disabled-bg: var(--tblr-pink);--tblr-btn-disabled-color: var(--tblr-pink-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-pink,.btn-outline.btn-pink{--tblr-btn-color: var(--tblr-pink);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-pink);--tblr-btn-hover-color: var(--tblr-pink-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-pink);--tblr-btn-active-color: var(--tblr-pink-fg);--tblr-btn-active-bg: var(--tblr-pink);--tblr-btn-active-border-color: var(--tblr-pink);--tblr-btn-disabled-color: var(--tblr-pink);--tblr-btn-disabled-border-color: var(--tblr-pink)}.btn-ghost-pink,.btn-ghost.btn-pink{--tblr-btn-color: var(--tblr-pink);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-pink-fg);--tblr-btn-hover-bg: var(--tblr-pink);--tblr-btn-hover-border-color: var(--tblr-pink);--tblr-btn-active-color: var(--tblr-pink-fg);--tblr-btn-active-bg: var(--tblr-pink);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-pink);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-red{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-red-fg, #ffffff);--tblr-btn-bg: var(--tblr-red);--tblr-btn-hover-color: var(--tblr-red-fg);--tblr-btn-hover-bg: var(--tblr-red-darken);--tblr-btn-active-color: var(--tblr-red-fg);--tblr-btn-active-bg: var(--tblr-red-darken);--tblr-btn-disabled-bg: var(--tblr-red);--tblr-btn-disabled-color: var(--tblr-red-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-red,.btn-outline.btn-red{--tblr-btn-color: var(--tblr-red);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-red);--tblr-btn-hover-color: var(--tblr-red-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-red);--tblr-btn-active-color: var(--tblr-red-fg);--tblr-btn-active-bg: var(--tblr-red);--tblr-btn-active-border-color: var(--tblr-red);--tblr-btn-disabled-color: var(--tblr-red);--tblr-btn-disabled-border-color: var(--tblr-red)}.btn-ghost-red,.btn-ghost.btn-red{--tblr-btn-color: var(--tblr-red);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-red-fg);--tblr-btn-hover-bg: var(--tblr-red);--tblr-btn-hover-border-color: var(--tblr-red);--tblr-btn-active-color: var(--tblr-red-fg);--tblr-btn-active-bg: var(--tblr-red);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-red);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-orange{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-orange-fg, #ffffff);--tblr-btn-bg: var(--tblr-orange);--tblr-btn-hover-color: var(--tblr-orange-fg);--tblr-btn-hover-bg: var(--tblr-orange-darken);--tblr-btn-active-color: var(--tblr-orange-fg);--tblr-btn-active-bg: var(--tblr-orange-darken);--tblr-btn-disabled-bg: var(--tblr-orange);--tblr-btn-disabled-color: var(--tblr-orange-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-orange,.btn-outline.btn-orange{--tblr-btn-color: var(--tblr-orange);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-orange);--tblr-btn-hover-color: var(--tblr-orange-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-orange);--tblr-btn-active-color: var(--tblr-orange-fg);--tblr-btn-active-bg: var(--tblr-orange);--tblr-btn-active-border-color: var(--tblr-orange);--tblr-btn-disabled-color: var(--tblr-orange);--tblr-btn-disabled-border-color: var(--tblr-orange)}.btn-ghost-orange,.btn-ghost.btn-orange{--tblr-btn-color: var(--tblr-orange);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-orange-fg);--tblr-btn-hover-bg: var(--tblr-orange);--tblr-btn-hover-border-color: var(--tblr-orange);--tblr-btn-active-color: var(--tblr-orange-fg);--tblr-btn-active-bg: var(--tblr-orange);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-orange);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-yellow{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-yellow-fg, #ffffff);--tblr-btn-bg: var(--tblr-yellow);--tblr-btn-hover-color: var(--tblr-yellow-fg);--tblr-btn-hover-bg: var(--tblr-yellow-darken);--tblr-btn-active-color: var(--tblr-yellow-fg);--tblr-btn-active-bg: var(--tblr-yellow-darken);--tblr-btn-disabled-bg: var(--tblr-yellow);--tblr-btn-disabled-color: var(--tblr-yellow-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-yellow,.btn-outline.btn-yellow{--tblr-btn-color: var(--tblr-yellow);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-yellow);--tblr-btn-hover-color: var(--tblr-yellow-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-yellow);--tblr-btn-active-color: var(--tblr-yellow-fg);--tblr-btn-active-bg: var(--tblr-yellow);--tblr-btn-active-border-color: var(--tblr-yellow);--tblr-btn-disabled-color: var(--tblr-yellow);--tblr-btn-disabled-border-color: var(--tblr-yellow)}.btn-ghost-yellow,.btn-ghost.btn-yellow{--tblr-btn-color: var(--tblr-yellow);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-yellow-fg);--tblr-btn-hover-bg: var(--tblr-yellow);--tblr-btn-hover-border-color: var(--tblr-yellow);--tblr-btn-active-color: var(--tblr-yellow-fg);--tblr-btn-active-bg: var(--tblr-yellow);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-yellow);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-lime{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-lime-fg, #ffffff);--tblr-btn-bg: var(--tblr-lime);--tblr-btn-hover-color: var(--tblr-lime-fg);--tblr-btn-hover-bg: var(--tblr-lime-darken);--tblr-btn-active-color: var(--tblr-lime-fg);--tblr-btn-active-bg: var(--tblr-lime-darken);--tblr-btn-disabled-bg: var(--tblr-lime);--tblr-btn-disabled-color: var(--tblr-lime-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-lime,.btn-outline.btn-lime{--tblr-btn-color: var(--tblr-lime);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-lime);--tblr-btn-hover-color: var(--tblr-lime-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-lime);--tblr-btn-active-color: var(--tblr-lime-fg);--tblr-btn-active-bg: var(--tblr-lime);--tblr-btn-active-border-color: var(--tblr-lime);--tblr-btn-disabled-color: var(--tblr-lime);--tblr-btn-disabled-border-color: var(--tblr-lime)}.btn-ghost-lime,.btn-ghost.btn-lime{--tblr-btn-color: var(--tblr-lime);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-lime-fg);--tblr-btn-hover-bg: var(--tblr-lime);--tblr-btn-hover-border-color: var(--tblr-lime);--tblr-btn-active-color: var(--tblr-lime-fg);--tblr-btn-active-bg: var(--tblr-lime);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-lime);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-green{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-green-fg, #ffffff);--tblr-btn-bg: var(--tblr-green);--tblr-btn-hover-color: var(--tblr-green-fg);--tblr-btn-hover-bg: var(--tblr-green-darken);--tblr-btn-active-color: var(--tblr-green-fg);--tblr-btn-active-bg: var(--tblr-green-darken);--tblr-btn-disabled-bg: var(--tblr-green);--tblr-btn-disabled-color: var(--tblr-green-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-green,.btn-outline.btn-green{--tblr-btn-color: var(--tblr-green);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-green);--tblr-btn-hover-color: var(--tblr-green-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-green);--tblr-btn-active-color: var(--tblr-green-fg);--tblr-btn-active-bg: var(--tblr-green);--tblr-btn-active-border-color: var(--tblr-green);--tblr-btn-disabled-color: var(--tblr-green);--tblr-btn-disabled-border-color: var(--tblr-green)}.btn-ghost-green,.btn-ghost.btn-green{--tblr-btn-color: var(--tblr-green);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-green-fg);--tblr-btn-hover-bg: var(--tblr-green);--tblr-btn-hover-border-color: var(--tblr-green);--tblr-btn-active-color: var(--tblr-green-fg);--tblr-btn-active-bg: var(--tblr-green);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-green);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-teal{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-teal-fg, #ffffff);--tblr-btn-bg: var(--tblr-teal);--tblr-btn-hover-color: var(--tblr-teal-fg);--tblr-btn-hover-bg: var(--tblr-teal-darken);--tblr-btn-active-color: var(--tblr-teal-fg);--tblr-btn-active-bg: var(--tblr-teal-darken);--tblr-btn-disabled-bg: var(--tblr-teal);--tblr-btn-disabled-color: var(--tblr-teal-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-teal,.btn-outline.btn-teal{--tblr-btn-color: var(--tblr-teal);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-teal);--tblr-btn-hover-color: var(--tblr-teal-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-teal);--tblr-btn-active-color: var(--tblr-teal-fg);--tblr-btn-active-bg: var(--tblr-teal);--tblr-btn-active-border-color: var(--tblr-teal);--tblr-btn-disabled-color: var(--tblr-teal);--tblr-btn-disabled-border-color: var(--tblr-teal)}.btn-ghost-teal,.btn-ghost.btn-teal{--tblr-btn-color: var(--tblr-teal);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-teal-fg);--tblr-btn-hover-bg: var(--tblr-teal);--tblr-btn-hover-border-color: var(--tblr-teal);--tblr-btn-active-color: var(--tblr-teal-fg);--tblr-btn-active-bg: var(--tblr-teal);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-teal);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-cyan{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-cyan-fg, #ffffff);--tblr-btn-bg: var(--tblr-cyan);--tblr-btn-hover-color: var(--tblr-cyan-fg);--tblr-btn-hover-bg: var(--tblr-cyan-darken);--tblr-btn-active-color: var(--tblr-cyan-fg);--tblr-btn-active-bg: var(--tblr-cyan-darken);--tblr-btn-disabled-bg: var(--tblr-cyan);--tblr-btn-disabled-color: var(--tblr-cyan-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-cyan,.btn-outline.btn-cyan{--tblr-btn-color: var(--tblr-cyan);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-cyan);--tblr-btn-hover-color: var(--tblr-cyan-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-cyan);--tblr-btn-active-color: var(--tblr-cyan-fg);--tblr-btn-active-bg: var(--tblr-cyan);--tblr-btn-active-border-color: var(--tblr-cyan);--tblr-btn-disabled-color: var(--tblr-cyan);--tblr-btn-disabled-border-color: var(--tblr-cyan)}.btn-ghost-cyan,.btn-ghost.btn-cyan{--tblr-btn-color: var(--tblr-cyan);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-cyan-fg);--tblr-btn-hover-bg: var(--tblr-cyan);--tblr-btn-hover-border-color: var(--tblr-cyan);--tblr-btn-active-color: var(--tblr-cyan-fg);--tblr-btn-active-bg: var(--tblr-cyan);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-cyan);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-x{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-x-fg, #ffffff);--tblr-btn-bg: var(--tblr-x);--tblr-btn-hover-color: var(--tblr-x-fg);--tblr-btn-hover-bg: var(--tblr-x-darken);--tblr-btn-active-color: var(--tblr-x-fg);--tblr-btn-active-bg: var(--tblr-x-darken);--tblr-btn-disabled-bg: var(--tblr-x);--tblr-btn-disabled-color: var(--tblr-x-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-x,.btn-outline.btn-x{--tblr-btn-color: var(--tblr-x);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-x);--tblr-btn-hover-color: var(--tblr-x-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-x);--tblr-btn-active-color: var(--tblr-x-fg);--tblr-btn-active-bg: var(--tblr-x);--tblr-btn-active-border-color: var(--tblr-x);--tblr-btn-disabled-color: var(--tblr-x);--tblr-btn-disabled-border-color: var(--tblr-x)}.btn-ghost-x,.btn-ghost.btn-x{--tblr-btn-color: var(--tblr-x);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-x-fg);--tblr-btn-hover-bg: var(--tblr-x);--tblr-btn-hover-border-color: var(--tblr-x);--tblr-btn-active-color: var(--tblr-x-fg);--tblr-btn-active-bg: var(--tblr-x);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-x);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-facebook{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-facebook-fg, #ffffff);--tblr-btn-bg: var(--tblr-facebook);--tblr-btn-hover-color: var(--tblr-facebook-fg);--tblr-btn-hover-bg: var(--tblr-facebook-darken);--tblr-btn-active-color: var(--tblr-facebook-fg);--tblr-btn-active-bg: var(--tblr-facebook-darken);--tblr-btn-disabled-bg: var(--tblr-facebook);--tblr-btn-disabled-color: var(--tblr-facebook-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-facebook,.btn-outline.btn-facebook{--tblr-btn-color: var(--tblr-facebook);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-facebook);--tblr-btn-hover-color: var(--tblr-facebook-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-facebook);--tblr-btn-active-color: var(--tblr-facebook-fg);--tblr-btn-active-bg: var(--tblr-facebook);--tblr-btn-active-border-color: var(--tblr-facebook);--tblr-btn-disabled-color: var(--tblr-facebook);--tblr-btn-disabled-border-color: var(--tblr-facebook)}.btn-ghost-facebook,.btn-ghost.btn-facebook{--tblr-btn-color: var(--tblr-facebook);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-facebook-fg);--tblr-btn-hover-bg: var(--tblr-facebook);--tblr-btn-hover-border-color: var(--tblr-facebook);--tblr-btn-active-color: var(--tblr-facebook-fg);--tblr-btn-active-bg: var(--tblr-facebook);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-facebook);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-twitter{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-twitter-fg, #ffffff);--tblr-btn-bg: var(--tblr-twitter);--tblr-btn-hover-color: var(--tblr-twitter-fg);--tblr-btn-hover-bg: var(--tblr-twitter-darken);--tblr-btn-active-color: var(--tblr-twitter-fg);--tblr-btn-active-bg: var(--tblr-twitter-darken);--tblr-btn-disabled-bg: var(--tblr-twitter);--tblr-btn-disabled-color: var(--tblr-twitter-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-twitter,.btn-outline.btn-twitter{--tblr-btn-color: var(--tblr-twitter);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-twitter);--tblr-btn-hover-color: var(--tblr-twitter-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-twitter);--tblr-btn-active-color: var(--tblr-twitter-fg);--tblr-btn-active-bg: var(--tblr-twitter);--tblr-btn-active-border-color: var(--tblr-twitter);--tblr-btn-disabled-color: var(--tblr-twitter);--tblr-btn-disabled-border-color: var(--tblr-twitter)}.btn-ghost-twitter,.btn-ghost.btn-twitter{--tblr-btn-color: var(--tblr-twitter);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-twitter-fg);--tblr-btn-hover-bg: var(--tblr-twitter);--tblr-btn-hover-border-color: var(--tblr-twitter);--tblr-btn-active-color: var(--tblr-twitter-fg);--tblr-btn-active-bg: var(--tblr-twitter);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-twitter);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-linkedin{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-linkedin-fg, #ffffff);--tblr-btn-bg: var(--tblr-linkedin);--tblr-btn-hover-color: var(--tblr-linkedin-fg);--tblr-btn-hover-bg: var(--tblr-linkedin-darken);--tblr-btn-active-color: var(--tblr-linkedin-fg);--tblr-btn-active-bg: var(--tblr-linkedin-darken);--tblr-btn-disabled-bg: var(--tblr-linkedin);--tblr-btn-disabled-color: var(--tblr-linkedin-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-linkedin,.btn-outline.btn-linkedin{--tblr-btn-color: var(--tblr-linkedin);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-linkedin);--tblr-btn-hover-color: var(--tblr-linkedin-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-linkedin);--tblr-btn-active-color: var(--tblr-linkedin-fg);--tblr-btn-active-bg: var(--tblr-linkedin);--tblr-btn-active-border-color: var(--tblr-linkedin);--tblr-btn-disabled-color: var(--tblr-linkedin);--tblr-btn-disabled-border-color: var(--tblr-linkedin)}.btn-ghost-linkedin,.btn-ghost.btn-linkedin{--tblr-btn-color: var(--tblr-linkedin);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-linkedin-fg);--tblr-btn-hover-bg: var(--tblr-linkedin);--tblr-btn-hover-border-color: var(--tblr-linkedin);--tblr-btn-active-color: var(--tblr-linkedin-fg);--tblr-btn-active-bg: var(--tblr-linkedin);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-linkedin);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-google{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-google-fg, #ffffff);--tblr-btn-bg: var(--tblr-google);--tblr-btn-hover-color: var(--tblr-google-fg);--tblr-btn-hover-bg: var(--tblr-google-darken);--tblr-btn-active-color: var(--tblr-google-fg);--tblr-btn-active-bg: var(--tblr-google-darken);--tblr-btn-disabled-bg: var(--tblr-google);--tblr-btn-disabled-color: var(--tblr-google-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-google,.btn-outline.btn-google{--tblr-btn-color: var(--tblr-google);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-google);--tblr-btn-hover-color: var(--tblr-google-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-google);--tblr-btn-active-color: var(--tblr-google-fg);--tblr-btn-active-bg: var(--tblr-google);--tblr-btn-active-border-color: var(--tblr-google);--tblr-btn-disabled-color: var(--tblr-google);--tblr-btn-disabled-border-color: var(--tblr-google)}.btn-ghost-google,.btn-ghost.btn-google{--tblr-btn-color: var(--tblr-google);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-google-fg);--tblr-btn-hover-bg: var(--tblr-google);--tblr-btn-hover-border-color: var(--tblr-google);--tblr-btn-active-color: var(--tblr-google-fg);--tblr-btn-active-bg: var(--tblr-google);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-google);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-youtube{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-youtube-fg, #ffffff);--tblr-btn-bg: var(--tblr-youtube);--tblr-btn-hover-color: var(--tblr-youtube-fg);--tblr-btn-hover-bg: var(--tblr-youtube-darken);--tblr-btn-active-color: var(--tblr-youtube-fg);--tblr-btn-active-bg: var(--tblr-youtube-darken);--tblr-btn-disabled-bg: var(--tblr-youtube);--tblr-btn-disabled-color: var(--tblr-youtube-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-youtube,.btn-outline.btn-youtube{--tblr-btn-color: var(--tblr-youtube);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-youtube);--tblr-btn-hover-color: var(--tblr-youtube-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-youtube);--tblr-btn-active-color: var(--tblr-youtube-fg);--tblr-btn-active-bg: var(--tblr-youtube);--tblr-btn-active-border-color: var(--tblr-youtube);--tblr-btn-disabled-color: var(--tblr-youtube);--tblr-btn-disabled-border-color: var(--tblr-youtube)}.btn-ghost-youtube,.btn-ghost.btn-youtube{--tblr-btn-color: var(--tblr-youtube);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-youtube-fg);--tblr-btn-hover-bg: var(--tblr-youtube);--tblr-btn-hover-border-color: var(--tblr-youtube);--tblr-btn-active-color: var(--tblr-youtube-fg);--tblr-btn-active-bg: var(--tblr-youtube);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-youtube);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-vimeo{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-vimeo-fg, #ffffff);--tblr-btn-bg: var(--tblr-vimeo);--tblr-btn-hover-color: var(--tblr-vimeo-fg);--tblr-btn-hover-bg: var(--tblr-vimeo-darken);--tblr-btn-active-color: var(--tblr-vimeo-fg);--tblr-btn-active-bg: var(--tblr-vimeo-darken);--tblr-btn-disabled-bg: var(--tblr-vimeo);--tblr-btn-disabled-color: var(--tblr-vimeo-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-vimeo,.btn-outline.btn-vimeo{--tblr-btn-color: var(--tblr-vimeo);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-vimeo);--tblr-btn-hover-color: var(--tblr-vimeo-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-vimeo);--tblr-btn-active-color: var(--tblr-vimeo-fg);--tblr-btn-active-bg: var(--tblr-vimeo);--tblr-btn-active-border-color: var(--tblr-vimeo);--tblr-btn-disabled-color: var(--tblr-vimeo);--tblr-btn-disabled-border-color: var(--tblr-vimeo)}.btn-ghost-vimeo,.btn-ghost.btn-vimeo{--tblr-btn-color: var(--tblr-vimeo);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-vimeo-fg);--tblr-btn-hover-bg: var(--tblr-vimeo);--tblr-btn-hover-border-color: var(--tblr-vimeo);--tblr-btn-active-color: var(--tblr-vimeo-fg);--tblr-btn-active-bg: var(--tblr-vimeo);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-vimeo);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-dribbble{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-dribbble-fg, #ffffff);--tblr-btn-bg: var(--tblr-dribbble);--tblr-btn-hover-color: var(--tblr-dribbble-fg);--tblr-btn-hover-bg: var(--tblr-dribbble-darken);--tblr-btn-active-color: var(--tblr-dribbble-fg);--tblr-btn-active-bg: var(--tblr-dribbble-darken);--tblr-btn-disabled-bg: var(--tblr-dribbble);--tblr-btn-disabled-color: var(--tblr-dribbble-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-dribbble,.btn-outline.btn-dribbble{--tblr-btn-color: var(--tblr-dribbble);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-dribbble);--tblr-btn-hover-color: var(--tblr-dribbble-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-dribbble);--tblr-btn-active-color: var(--tblr-dribbble-fg);--tblr-btn-active-bg: var(--tblr-dribbble);--tblr-btn-active-border-color: var(--tblr-dribbble);--tblr-btn-disabled-color: var(--tblr-dribbble);--tblr-btn-disabled-border-color: var(--tblr-dribbble)}.btn-ghost-dribbble,.btn-ghost.btn-dribbble{--tblr-btn-color: var(--tblr-dribbble);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-dribbble-fg);--tblr-btn-hover-bg: var(--tblr-dribbble);--tblr-btn-hover-border-color: var(--tblr-dribbble);--tblr-btn-active-color: var(--tblr-dribbble-fg);--tblr-btn-active-bg: var(--tblr-dribbble);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-dribbble);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-github{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-github-fg, #ffffff);--tblr-btn-bg: var(--tblr-github);--tblr-btn-hover-color: var(--tblr-github-fg);--tblr-btn-hover-bg: var(--tblr-github-darken);--tblr-btn-active-color: var(--tblr-github-fg);--tblr-btn-active-bg: var(--tblr-github-darken);--tblr-btn-disabled-bg: var(--tblr-github);--tblr-btn-disabled-color: var(--tblr-github-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-github,.btn-outline.btn-github{--tblr-btn-color: var(--tblr-github);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-github);--tblr-btn-hover-color: var(--tblr-github-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-github);--tblr-btn-active-color: var(--tblr-github-fg);--tblr-btn-active-bg: var(--tblr-github);--tblr-btn-active-border-color: var(--tblr-github);--tblr-btn-disabled-color: var(--tblr-github);--tblr-btn-disabled-border-color: var(--tblr-github)}.btn-ghost-github,.btn-ghost.btn-github{--tblr-btn-color: var(--tblr-github);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-github-fg);--tblr-btn-hover-bg: var(--tblr-github);--tblr-btn-hover-border-color: var(--tblr-github);--tblr-btn-active-color: var(--tblr-github-fg);--tblr-btn-active-bg: var(--tblr-github);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-github);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-instagram{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-instagram-fg, #ffffff);--tblr-btn-bg: var(--tblr-instagram);--tblr-btn-hover-color: var(--tblr-instagram-fg);--tblr-btn-hover-bg: var(--tblr-instagram-darken);--tblr-btn-active-color: var(--tblr-instagram-fg);--tblr-btn-active-bg: var(--tblr-instagram-darken);--tblr-btn-disabled-bg: var(--tblr-instagram);--tblr-btn-disabled-color: var(--tblr-instagram-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-instagram,.btn-outline.btn-instagram{--tblr-btn-color: var(--tblr-instagram);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-instagram);--tblr-btn-hover-color: var(--tblr-instagram-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-instagram);--tblr-btn-active-color: var(--tblr-instagram-fg);--tblr-btn-active-bg: var(--tblr-instagram);--tblr-btn-active-border-color: var(--tblr-instagram);--tblr-btn-disabled-color: var(--tblr-instagram);--tblr-btn-disabled-border-color: var(--tblr-instagram)}.btn-ghost-instagram,.btn-ghost.btn-instagram{--tblr-btn-color: var(--tblr-instagram);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-instagram-fg);--tblr-btn-hover-bg: var(--tblr-instagram);--tblr-btn-hover-border-color: var(--tblr-instagram);--tblr-btn-active-color: var(--tblr-instagram-fg);--tblr-btn-active-bg: var(--tblr-instagram);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-instagram);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-pinterest{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-pinterest-fg, #ffffff);--tblr-btn-bg: var(--tblr-pinterest);--tblr-btn-hover-color: var(--tblr-pinterest-fg);--tblr-btn-hover-bg: var(--tblr-pinterest-darken);--tblr-btn-active-color: var(--tblr-pinterest-fg);--tblr-btn-active-bg: var(--tblr-pinterest-darken);--tblr-btn-disabled-bg: var(--tblr-pinterest);--tblr-btn-disabled-color: var(--tblr-pinterest-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-pinterest,.btn-outline.btn-pinterest{--tblr-btn-color: var(--tblr-pinterest);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-pinterest);--tblr-btn-hover-color: var(--tblr-pinterest-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-pinterest);--tblr-btn-active-color: var(--tblr-pinterest-fg);--tblr-btn-active-bg: var(--tblr-pinterest);--tblr-btn-active-border-color: var(--tblr-pinterest);--tblr-btn-disabled-color: var(--tblr-pinterest);--tblr-btn-disabled-border-color: var(--tblr-pinterest)}.btn-ghost-pinterest,.btn-ghost.btn-pinterest{--tblr-btn-color: var(--tblr-pinterest);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-pinterest-fg);--tblr-btn-hover-bg: var(--tblr-pinterest);--tblr-btn-hover-border-color: var(--tblr-pinterest);--tblr-btn-active-color: var(--tblr-pinterest-fg);--tblr-btn-active-bg: var(--tblr-pinterest);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-pinterest);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-vk{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-vk-fg, #ffffff);--tblr-btn-bg: var(--tblr-vk);--tblr-btn-hover-color: var(--tblr-vk-fg);--tblr-btn-hover-bg: var(--tblr-vk-darken);--tblr-btn-active-color: var(--tblr-vk-fg);--tblr-btn-active-bg: var(--tblr-vk-darken);--tblr-btn-disabled-bg: var(--tblr-vk);--tblr-btn-disabled-color: var(--tblr-vk-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-vk,.btn-outline.btn-vk{--tblr-btn-color: var(--tblr-vk);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-vk);--tblr-btn-hover-color: var(--tblr-vk-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-vk);--tblr-btn-active-color: var(--tblr-vk-fg);--tblr-btn-active-bg: var(--tblr-vk);--tblr-btn-active-border-color: var(--tblr-vk);--tblr-btn-disabled-color: var(--tblr-vk);--tblr-btn-disabled-border-color: var(--tblr-vk)}.btn-ghost-vk,.btn-ghost.btn-vk{--tblr-btn-color: var(--tblr-vk);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-vk-fg);--tblr-btn-hover-bg: var(--tblr-vk);--tblr-btn-hover-border-color: var(--tblr-vk);--tblr-btn-active-color: var(--tblr-vk-fg);--tblr-btn-active-bg: var(--tblr-vk);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-vk);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-rss{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-rss-fg, #ffffff);--tblr-btn-bg: var(--tblr-rss);--tblr-btn-hover-color: var(--tblr-rss-fg);--tblr-btn-hover-bg: var(--tblr-rss-darken);--tblr-btn-active-color: var(--tblr-rss-fg);--tblr-btn-active-bg: var(--tblr-rss-darken);--tblr-btn-disabled-bg: var(--tblr-rss);--tblr-btn-disabled-color: var(--tblr-rss-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-rss,.btn-outline.btn-rss{--tblr-btn-color: var(--tblr-rss);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-rss);--tblr-btn-hover-color: var(--tblr-rss-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-rss);--tblr-btn-active-color: var(--tblr-rss-fg);--tblr-btn-active-bg: var(--tblr-rss);--tblr-btn-active-border-color: var(--tblr-rss);--tblr-btn-disabled-color: var(--tblr-rss);--tblr-btn-disabled-border-color: var(--tblr-rss)}.btn-ghost-rss,.btn-ghost.btn-rss{--tblr-btn-color: var(--tblr-rss);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-rss-fg);--tblr-btn-hover-bg: var(--tblr-rss);--tblr-btn-hover-border-color: var(--tblr-rss);--tblr-btn-active-color: var(--tblr-rss-fg);--tblr-btn-active-bg: var(--tblr-rss);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-rss);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-flickr{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-flickr-fg, #ffffff);--tblr-btn-bg: var(--tblr-flickr);--tblr-btn-hover-color: var(--tblr-flickr-fg);--tblr-btn-hover-bg: var(--tblr-flickr-darken);--tblr-btn-active-color: var(--tblr-flickr-fg);--tblr-btn-active-bg: var(--tblr-flickr-darken);--tblr-btn-disabled-bg: var(--tblr-flickr);--tblr-btn-disabled-color: var(--tblr-flickr-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-flickr,.btn-outline.btn-flickr{--tblr-btn-color: var(--tblr-flickr);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-flickr);--tblr-btn-hover-color: var(--tblr-flickr-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-flickr);--tblr-btn-active-color: var(--tblr-flickr-fg);--tblr-btn-active-bg: var(--tblr-flickr);--tblr-btn-active-border-color: var(--tblr-flickr);--tblr-btn-disabled-color: var(--tblr-flickr);--tblr-btn-disabled-border-color: var(--tblr-flickr)}.btn-ghost-flickr,.btn-ghost.btn-flickr{--tblr-btn-color: var(--tblr-flickr);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-flickr-fg);--tblr-btn-hover-bg: var(--tblr-flickr);--tblr-btn-hover-border-color: var(--tblr-flickr);--tblr-btn-active-color: var(--tblr-flickr-fg);--tblr-btn-active-bg: var(--tblr-flickr);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-flickr);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-bitbucket{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-bitbucket-fg, #ffffff);--tblr-btn-bg: var(--tblr-bitbucket);--tblr-btn-hover-color: var(--tblr-bitbucket-fg);--tblr-btn-hover-bg: var(--tblr-bitbucket-darken);--tblr-btn-active-color: var(--tblr-bitbucket-fg);--tblr-btn-active-bg: var(--tblr-bitbucket-darken);--tblr-btn-disabled-bg: var(--tblr-bitbucket);--tblr-btn-disabled-color: var(--tblr-bitbucket-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-bitbucket,.btn-outline.btn-bitbucket{--tblr-btn-color: var(--tblr-bitbucket);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-bitbucket);--tblr-btn-hover-color: var(--tblr-bitbucket-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-bitbucket);--tblr-btn-active-color: var(--tblr-bitbucket-fg);--tblr-btn-active-bg: var(--tblr-bitbucket);--tblr-btn-active-border-color: var(--tblr-bitbucket);--tblr-btn-disabled-color: var(--tblr-bitbucket);--tblr-btn-disabled-border-color: var(--tblr-bitbucket)}.btn-ghost-bitbucket,.btn-ghost.btn-bitbucket{--tblr-btn-color: var(--tblr-bitbucket);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-bitbucket-fg);--tblr-btn-hover-bg: var(--tblr-bitbucket);--tblr-btn-hover-border-color: var(--tblr-bitbucket);--tblr-btn-active-color: var(--tblr-bitbucket-fg);--tblr-btn-active-bg: var(--tblr-bitbucket);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-bitbucket);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-tabler{--tblr-btn-border-color: transparent;--tblr-btn-hover-border-color: transparent;--tblr-btn-active-border-color: transparent;--tblr-btn-color: var(--tblr-tabler-fg, #ffffff);--tblr-btn-bg: var(--tblr-tabler);--tblr-btn-hover-color: var(--tblr-tabler-fg);--tblr-btn-hover-bg: var(--tblr-tabler-darken);--tblr-btn-active-color: var(--tblr-tabler-fg);--tblr-btn-active-bg: var(--tblr-tabler-darken);--tblr-btn-disabled-bg: var(--tblr-tabler);--tblr-btn-disabled-color: var(--tblr-tabler-fg);--tblr-btn-box-shadow: var(--tblr-shadow-input)}.btn-outline-tabler,.btn-outline.btn-tabler{--tblr-btn-color: var(--tblr-tabler);--tblr-btn-bg: transparent;--tblr-btn-border-color: var(--tblr-tabler);--tblr-btn-hover-color: var(--tblr-tabler-fg);--tblr-btn-hover-border-color: transparent;--tblr-btn-hover-bg: var(--tblr-tabler);--tblr-btn-active-color: var(--tblr-tabler-fg);--tblr-btn-active-bg: var(--tblr-tabler);--tblr-btn-active-border-color: var(--tblr-tabler);--tblr-btn-disabled-color: var(--tblr-tabler);--tblr-btn-disabled-border-color: var(--tblr-tabler)}.btn-ghost-tabler,.btn-ghost.btn-tabler{--tblr-btn-color: var(--tblr-tabler);--tblr-btn-bg: transparent;--tblr-btn-border-color: transparent;--tblr-btn-hover-color: var(--tblr-tabler-fg);--tblr-btn-hover-bg: var(--tblr-tabler);--tblr-btn-hover-border-color: var(--tblr-tabler);--tblr-btn-active-color: var(--tblr-tabler-fg);--tblr-btn-active-bg: var(--tblr-tabler);--tblr-btn-active-border-color: transparent;--tblr-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--tblr-btn-disabled-color: var(--tblr-tabler);--tblr-btn-disabled-bg: transparent;--tblr-btn-disabled-border-color: transparent;--tblr-gradient: none;--tblr-btn-box-shadow: none}.btn-sm,.btn-group-sm>.btn{--tblr-btn-line-height: 1.3333333333;--tblr-btn-icon-size: 1rem}.btn-lg,.btn-group-lg>.btn{--tblr-btn-line-height: 1.5rem;--tblr-btn-icon-size: 1.5rem}.btn-xl,.btn-group-xl>.btn{--tblr-btn-line-height: 2;--tblr-btn-icon-size: 2rem;--tblr-btn-padding-y: .6875rem;--tblr-btn-padding-x: 2rem;--tblr-btn-font-size: 1.5rem}.btn-pill{padding-right:1.5em;padding-left:1.5em;border-radius:10rem}.btn-pill[class*=btn-icon]{padding:.375rem 15px}.btn-square{border-radius:0}.btn-icon,.btn-action{padding-left:0;padding-right:0}.btn-icon .icon,.btn-action .icon{margin:calc(-1 * var(--tblr-btn-padding-x))}.btn-list{--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.btn-floating{position:fixed;z-index:1030;bottom:1rem;left:1rem;box-shadow:var(--tblr-shadow-dropdown)}.btn-loading{position:relative;color:transparent!important;text-shadow:none!important;pointer-events:none}.btn-loading>*{opacity:0}.btn-loading:after{content:"";display:inline-block;vertical-align:text-bottom;border:2px var(--tblr-border-style) currentColor;border-right-color:transparent;border-radius:100rem;color:var(--tblr-btn-color);position:absolute;width:var(--tblr-btn-icon-size);height:var(--tblr-btn-icon-size);left:calc(50% - var(--tblr-btn-icon-size) / 2);top:calc(50% - var(--tblr-btn-icon-size) / 2);animation:spinner-border .75s linear infinite}.btn-action{--tblr-border-color: transparent;color:var(--tblr-secondary);border-radius:var(--tblr-border-radius);background:transparent;box-shadow:none}.btn-action:after{content:none}.btn-action:focus{outline:none;box-shadow:none}.btn-action:hover,.btn-action.show{color:var(--tblr-body-color);background:var(--tblr-active-bg);border-color:transparent}.btn-action.show{color:var(--tblr-primary)}.btn-actions{display:flex}.btn-animate-icon .icon{transition:transform .3s ease}.btn-animate-icon:hover .icon,.btn-animate-icon:focus-visible .icon{transform:translate(4px)}.btn-animate-icon.btn-animate-icon-rotate:hover .icon,.btn-animate-icon.btn-animate-icon-rotate:focus-visible .icon{transform:rotate(90deg)}.btn-animate-icon.btn-animate-icon-move-start:hover .icon,.btn-animate-icon.btn-animate-icon-move-start:focus-visible .icon{transform:translate(-4px)}.btn-animate-icon.btn-animate-icon-pulse:hover .icon,.btn-animate-icon.btn-animate-icon-pulse:focus-visible .icon{transform:none;animation:pulse .9s}.btn-animate-icon.btn-animate-icon-shake:hover .icon,.btn-animate-icon.btn-animate-icon-shake:focus-visible .icon{transform:none;animation:shake .9s}.btn-animate-icon.btn-animate-icon-tada:hover .icon,.btn-animate-icon.btn-animate-icon-tada:focus-visible .icon{transform:none;animation:tada .9s}.btn-group,.btn-group-vertical{box-shadow:var(--tblr-shadow-input)}.btn-group>.btn-check:checked+.btn,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:5}.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus{z-index:1}.calendar{display:block;font-size:.765625rem;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.calendar-nav{display:flex;align-items:center}.calendar-title{flex:1;text-align:center}.calendar-body,.calendar-header{display:flex;flex-wrap:wrap;justify-content:flex-start;padding:.5rem 0}.calendar-header{color:var(--tblr-secondary)}.calendar-date{flex:0 0 14.2857142857%;max-width:14.2857142857%;padding:.2rem;text-align:center;border:0}.calendar-date.prev-month,.calendar-date.next-month{opacity:.25}.calendar-date .date-item{position:relative;display:inline-block;width:1.4rem;height:1.4rem;line-height:1.4rem;color:#66758c;text-align:center;text-decoration:none;white-space:nowrap;vertical-align:middle;cursor:pointer;background:0 0;border:var(--tblr-border-width) var(--tblr-border-style) transparent;border-radius:100rem;outline:0;transition:background .3s,border .3s,box-shadow .32s,color .3s}@media(prefers-reduced-motion:reduce){.calendar-date .date-item{transition:none}}.calendar-date .date-item:hover{color:var(--tblr-primary);text-decoration:none;background:#fefeff;border-color:var(--tblr-border-color)}.calendar-date .date-today{color:var(--tblr-primary);border-color:var(--tblr-border-color)}.calendar-range{position:relative}.calendar-range:before{position:absolute;top:50%;right:0;left:0;height:1.4rem;content:"";background:rgba(var(--tblr-primary-rgb),.1);transform:translateY(-50%)}.calendar-range.range-start .date-item,.calendar-range.range-end .date-item{color:#fff;background:var(--tblr-primary);border-color:var(--tblr-primary)}.calendar-range.range-start:before{left:50%}.calendar-range.range-end:before{right:50%}.carousel-indicators-vertical{left:auto;top:0;margin:0 1rem 0 0;flex-direction:column}.carousel-indicators-vertical [data-bs-target]{margin:3px 0;width:3px;height:30px;border:0;border-left:10px var(--tblr-border-style) transparent;border-right:10px var(--tblr-border-style) transparent}.carousel-indicators-dot [data-bs-target]{width:.5rem;height:.5rem;border-radius:100rem;border:10px var(--tblr-border-style) transparent;margin:0}.carousel-indicators-thumb [data-bs-target]{width:2rem;height:auto;background:no-repeat center/cover;border:0;border-radius:var(--tblr-border-radius);box-shadow:rgba(var(--tblr-body-color-rgb),.04) 0 2px 4px;margin:0 3px;opacity:.75}@media(min-width:992px){.carousel-indicators-thumb [data-bs-target]{width:4rem}}.carousel-indicators-thumb [data-bs-target]:before{content:"";padding-top:var(--tblr-aspect-ratio, 100%);display:block}.carousel-indicators-thumb.carousel-indicators-vertical [data-bs-target]{margin:3px 0}.carousel-caption-background{background:red;position:absolute;left:0;right:0;bottom:0;height:90%;background:linear-gradient(0deg,#1f2937e6,#1f293700)}.card{transition:transform .3s ease-out,opacity .3s ease-out,box-shadow .3s ease-out}@media(prefers-reduced-motion:reduce){.card{transition:none}}@media print{.card{border:none;box-shadow:none}}a.card{color:inherit}a.card:hover{text-decoration:none;box-shadow:rgba(var(--tblr-body-color-rgb),.16) 0 2px 16px}.card .card{box-shadow:none}.card-borderless,.card-borderless .card-header,.card-borderless .card-footer{border-color:transparent}.card-stamp{--tblr-stamp-size: 7rem;position:absolute;top:0;right:0;width:calc(var(--tblr-stamp-size) * 1);height:calc(var(--tblr-stamp-size) * 1);max-height:100%;border-top-right-radius:6px;opacity:.2;overflow:hidden;pointer-events:none}.card-stamp-lg{--tblr-stamp-size: 13rem}.card-stamp-icon{background:var(--tblr-secondary);color:var(--tblr-card-bg, var(--tblr-bg-surface));display:flex;align-items:center;justify-content:center;border-radius:100rem;width:calc(var(--tblr-stamp-size) * 1);height:calc(var(--tblr-stamp-size) * 1);position:relative;top:calc(var(--tblr-stamp-size) * -.25);right:calc(var(--tblr-stamp-size) * -.25);font-size:calc(var(--tblr-stamp-size) * .75);transform:rotate(10deg)}.card-stamp-icon .icon{stroke-width:2;width:calc(var(--tblr-stamp-size) * .75);height:calc(var(--tblr-stamp-size) * .75)}.card-img,.card-img-start{border-top-left-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));border-bottom-left-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)))}.card-img,.card-img-end{border-top-right-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)));border-bottom-right-radius:calc(var(--tblr-border-radius-lg) - (var(--tblr-border-width)))}.card-img-overlay{display:flex;flex-direction:column;justify-content:flex-end}.card-img-overlay-dark{background-image:linear-gradient(180deg,#0000,#0009)}.card-inactive{pointer-events:none;box-shadow:none}.card-inactive .card-body{opacity:.64}.card-active{--tblr-card-border-color: var(--tblr-primary);--tblr-card-bg: var(--tblr-active-bg)}.card-btn{display:flex;align-items:center;justify-content:center;padding:1rem 1.25rem;text-align:center;transition:background .3s}@media(prefers-reduced-motion:reduce){.card-btn{transition:none}}.card-btn{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);flex:1;color:inherit;font-weight:var(--tblr-font-weight-medium)}.card-btn:hover{text-decoration:none;background:rgba(var(--tblr-primary-rgb),.04)}.card-btn+.card-btn{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.card-stacked{--tblr-card-stacked-offset: .25rem;position:relative}.card-stacked:after{position:absolute;top:calc(-1 * var(--tblr-card-stacked-offset));right:var(--tblr-card-stacked-offset);left:var(--tblr-card-stacked-offset);height:var(--tblr-card-stacked-offset);content:"";background:var(--tblr-card-bg, var(--tblr-bg-surface));border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-card-border-color);border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-cover{position:relative;padding:1rem 1.25rem;background:#666 no-repeat center/cover}.card-cover:before{position:absolute;inset:0;content:"";background:#1f29377a}.card-cover:first-child,.card-cover:first-child:before{border-radius:6px 6px 0 0}.card-cover-blurred:before{backdrop-filter:blur(2px)}.card-actions{margin:-.5rem -.5rem -.5rem auto;padding-left:.5rem}.card-actions a{text-decoration:none}.card-header{color:inherit;display:flex;align-items:center;background:transparent}.card-header:first-child{border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-header-light{border-bottom-color:transparent;background:var(--tblr-bg-surface-tertiary)}.card-header-tabs{background:var(--tblr-bg-surface-tertiary);flex:1;margin:calc(var(--tblr-card-cap-padding-y) * -1) calc(var(--tblr-card-cap-padding-x) * -1) calc(var(--tblr-card-cap-padding-y) * -1);padding:calc(var(--tblr-card-cap-padding-y) * .5) calc(var(--tblr-card-cap-padding-x) * .5) 0;border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-header-pills{flex:1;margin-top:-.5rem;margin-bottom:-.5rem}.card-rotate-left,.card-rotate-start{transform:rotate(-1.5deg)}.card-rotate-right,.card-rotate-end{transform:rotate(1.5deg)}.card-link{color:inherit}.card-link:hover{color:inherit;text-decoration:none;box-shadow:0 1px 6px #00000014}.card-link-rotate:hover{transform:rotate(1.5deg);opacity:1}.card-link-pop:hover{transform:translateY(-2px);opacity:1}.card-footer{margin-top:auto}.card-footer:last-child{border-radius:0 0 var(--tblr-card-border-radius) var(--tblr-card-border-radius)}.card-footer-transparent{background:transparent;border-color:transparent;padding-top:0}.card-footer-borderless{border-top:none}.card-progress{height:.25rem}.card-progress:last-child{border-radius:0 0 2px 2px}.card-progress:first-child{border-radius:2px 2px 0 0}.card-meta{color:var(--tblr-secondary)}.card-title{display:block;margin:0 0 1rem;font-size:1rem;font-weight:var(--tblr-font-weight-medium);color:inherit;line-height:1.5rem}a.card-title:hover{color:inherit}.card-header .card-title{margin:0}.card-subtitle{margin-bottom:1.25rem;color:var(--tblr-secondary);font-weight:400}.card-header .card-subtitle{margin:0}.card-title .card-subtitle{margin:0 0 0 .25rem;font-size:.875rem}.card-body{position:relative}.card-body>:last-child{margin-bottom:0}.card-sm>.card-body{padding:1rem}@media(min-width:768px){.card-md>.card-body{padding:2.5rem}}@media(min-width:768px){.card-lg>.card-body{padding:2rem}}@media(min-width:992px){.card-lg>.card-body{padding:4rem}}@media print{.card-body{padding:0}}.card-body+.card-body{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.card-body-scrollable{overflow:auto}.card-options{top:1.5rem;right:.75rem;display:flex;margin-left:auto}.card-options-link{display:inline-block;min-width:1rem;margin-left:.25rem;color:var(--tblr-secondary)}.card-status-top{position:absolute;top:0;right:0;left:0;height:2px;border-radius:var(--tblr-card-border-radius) var(--tblr-card-border-radius) 0 0}.card-status-start{position:absolute;right:auto;bottom:0;width:2px;height:100%;border-radius:var(--tblr-card-border-radius) 0 0 var(--tblr-card-border-radius)}.card-status-bottom{position:absolute;top:initial;bottom:0;width:100%;height:2px;border-radius:0 0 var(--tblr-card-border-radius) var(--tblr-card-border-radius)}.card-table{margin-bottom:0!important}.card-table tr td:first-child,.card-table tr th:first-child{padding-left:1.25rem;border-left:0}.card-table tr td:last-child,.card-table tr th:last-child{padding-right:1.25rem;border-right:0}.card-table thead tr:first-child,.card-table tbody tr:first-child,.card-table tfoot tr:first-child,.card-table thead tr:first-child td,.card-table thead tr:first-child th,.card-table tbody tr:first-child td,.card-table tbody tr:first-child th,.card-table tfoot tr:first-child td,.card-table tfoot tr:first-child th{border-top:0}.card-body+.card-table{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-table-border-color)}.card-code{padding:0}.card-code .highlight{margin:0;border:0}.card-code pre{margin:0!important;border:0!important}.card-chart{position:relative;z-index:1;height:3.5rem}.card-avatar{margin-left:auto;margin-right:auto;box-shadow:0 0 0 .25rem var(--tblr-card-bg, var(--tblr-bg-surface));margin-top:calc(-1 * var(--tblr-avatar-size) * .5)}.card-body+.card-list-group{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.card-list-group .list-group-item{padding-right:1.25rem;padding-left:1.25rem;border-right:0;border-left:0;border-radius:0}.card-list-group .list-group-item:last-child{border-bottom:0}.card-list-group .list-group-item:first-child{border-top:0}.card-tabs .nav-tabs{position:relative;z-index:1000;border-bottom:0}.card-tabs .nav-tabs .nav-link{background:var(--tblr-bg-surface-tertiary);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.card-tabs .nav-tabs .nav-link.active,.card-tabs .nav-tabs .nav-link:active,.card-tabs .nav-tabs .nav-link:hover{border-color:var(--tblr-border-color-translucent);color:var(--tblr-body-color)}.card-tabs .nav-tabs .nav-link.active{color:inherit;background:var(--tblr-card-bg, var(--tblr-bg-surface));border-bottom-color:transparent}.card-tabs .nav-tabs .nav-item:not(:first-child) .nav-link{border-top-left-radius:0}.card-tabs .nav-tabs .nav-item:not(:last-child) .nav-link{border-top-right-radius:0}.card-tabs .nav-tabs .nav-item+.nav-item{margin-left:calc(-1 * var(--tblr-border-width))}.card-tabs .nav-tabs-bottom,.card-tabs .nav-tabs-bottom .nav-link{margin-bottom:0}.card-tabs .nav-tabs-bottom .nav-link.active{border-top-color:transparent}.card-tabs .nav-tabs-bottom .nav-item{margin-top:calc(-1 * var(--tblr-border-width));margin-bottom:0}.card-tabs .nav-tabs-bottom .nav-item .nav-link{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);border-radius:0 0 var(--tblr-border-radius-lg) var(--tblr-border-radius-lg)}.card-tabs .nav-tabs-bottom .nav-item:not(:first-child) .nav-link{border-bottom-left-radius:0}.card-tabs .nav-tabs-bottom .nav-item:not(:last-child) .nav-link{border-bottom-right-radius:0}.card-tabs .card{border-bottom-left-radius:0}.card-tabs .nav-tabs+.tab-content .card{border-bottom-left-radius:var(--tblr-card-border-radius);border-top-left-radius:0}.card-note{--tblr-card-bg: #fff7dd;--tblr-card-border-color: #fff1c9}.btn-close{--tblr-btn-close-color: currentColor;--tblr-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%231f2937'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");--tblr-btn-close-opacity: .4;--tblr-btn-close-hover-opacity: .75;--tblr-btn-close-focus-shadow: 0 0 0 .25rem rgba(var(--tblr-primary-rgb), .25);--tblr-btn-close-focus-opacity: 1;--tblr-btn-close-disabled-opacity: .25;--tblr-btn-close-size: 1em;width:var(--tblr-btn-close-size);height:var(--tblr-btn-close-size);padding:.25em;color:var(--tblr-btn-close-color);mask:var(--tblr-btn-close-bg) no-repeat center/calc(var(--tblr-btn-close-size) * .75);background-color:var(--tblr-btn-close-color);border:0;border-radius:var(--tblr-border-radius);opacity:var(--tblr-btn-close-opacity);cursor:pointer;display:block}.btn-close:hover{color:var(--tblr-btn-close-color);text-decoration:none;opacity:var(--tblr-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--tblr-btn-close-focus-shadow);opacity:var(--tblr-btn-close-focus-opacity)}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;opacity:var(--tblr-btn-close-disabled-opacity)}.dropdown-menu{user-select:none;background-clip:border-box}.dropdown-menu.card{padding:0;min-width:25rem;display:none}.dropdown-menu.card.show{display:flex}.dropdown-item{min-width:11rem;display:flex;align-items:center;margin:0;line-height:1.4285714286;gap:.5rem}.dropdown-item-icon{width:1.25rem!important;height:1.25rem!important;margin-right:.5rem;color:var(--tblr-secondary);opacity:.7;text-align:center}.dropdown-item-indicator{margin-right:.5rem;margin-left:-.25rem;height:1.25rem;display:inline-flex;line-height:1;vertical-align:bottom;align-items:center}.dropdown-header{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);padding-bottom:.25rem;pointer-events:none}.dropdown-menu-scrollable{height:auto;max-height:13rem;overflow-x:hidden}.dropdown-menu-column{min-width:11rem}.dropdown-menu-column .dropdown-item{min-width:0}.dropdown-menu-columns{display:flex;flex:0 .25rem}.dropdown-menu-arrow:before{content:"";position:absolute;top:-.25rem;left:.75rem;display:block;background:inherit;width:14px;height:14px;transform:rotate(45deg);transform-origin:center;border:1px solid;border-color:inherit;z-index:-1;clip:rect(0px,9px,9px,0px)}.dropdown-menu-arrow.dropdown-menu-end:before{right:.75rem;left:auto}.dropend>.dropdown-menu{margin-top:calc(-.25rem - 1px);margin-left:-.25rem}.dropend .dropdown-toggle:after{margin-left:auto}.dropdown-menu-card{padding:0;min-width:20rem}.dropdown-menu-card>.card{margin:0;border:0;box-shadow:none}.datagrid{--tblr-datagrid-padding: 1.5rem;--tblr-datagrid-item-width: 15rem;display:grid;grid-gap:var(--tblr-datagrid-padding);grid-template-columns:repeat(auto-fit,minmax(var(--tblr-datagrid-item-width),1fr))}.datagrid-title{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);margin-bottom:.25rem}.empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:1rem;text-align:center}@media(min-width:768px){.empty{padding:3rem}}.empty-icon{margin:0 0 1rem;width:3rem;height:3rem;line-height:1;color:var(--tblr-secondary)}.empty-icon svg{width:100%;height:100%}.empty-img{margin:0 0 2rem;line-height:1}.empty-header{margin:0 0 1rem;font-size:4rem;font-weight:var(--tblr-font-weight-light);line-height:1;color:var(--tblr-secondary)}.empty-title{font-size:1.25rem;line-height:1.75rem;font-weight:var(--tblr-font-weight-bold)}.empty-title,.empty-subtitle{margin:0 0 .5rem}.empty-action{margin-top:1.5rem}.empty-bordered{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.row>*{min-width:0}.col-separator{border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.container-slim{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto;max-width:16rem}.container-tight{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto;max-width:30rem}.container-narrow{--tblr-gutter-x: calc(var(--tblr-page-padding) * 2);--tblr-gutter-y: 0;width:100%;padding-right:calc(var(--tblr-gutter-x) * .5);padding-left:calc(var(--tblr-gutter-x) * .5);margin-right:auto;margin-left:auto;max-width:61.875rem}.row-0{margin-right:0;margin-left:0}.row-0>.col,.row-0>[class*=col-]{padding-right:0;padding-left:0}.row-0 .card{margin-bottom:0}.row-sm{margin-right:-.375rem;margin-left:-.375rem}.row-sm>.col,.row-sm>[class*=col-]{padding-right:.375rem;padding-left:.375rem}.row-sm .card{margin-bottom:.75rem}.row-md{margin-right:-1.5rem;margin-left:-1.5rem}.row-md>.col,.row-md>[class*=col-]{padding-right:1.5rem;padding-left:1.5rem}.row-md .card{margin-bottom:3rem}.row-lg{margin-right:-3rem;margin-left:-3rem}.row-lg>.col,.row-lg>[class*=col-]{padding-right:3rem;padding-left:3rem}.row-lg .card{margin-bottom:6rem}.row-deck>.col,.row-deck>[class*=col-]{display:flex;align-items:stretch}.row-deck>.col .card,.row-deck>[class*=col-] .card{flex:1 1 auto}.row-cards{--tblr-gutter-x: var(--tblr-page-padding);--tblr-gutter-y: var(--tblr-page-padding);min-width:0}.row-cards .row-cards{flex:1}.space-y{display:flex;flex-direction:column;gap:1rem}.space-x{display:flex;gap:1rem}.space-y-0{display:flex;flex-direction:column;gap:0}.space-x-0{display:flex;gap:0}.space-y-1{display:flex;flex-direction:column;gap:.25rem}.space-x-1{display:flex;gap:.25rem}.space-y-2{display:flex;flex-direction:column;gap:.5rem}.space-x-2{display:flex;gap:.5rem}.space-y-3{display:flex;flex-direction:column;gap:1rem}.space-x-3{display:flex;gap:1rem}.space-y-4{display:flex;flex-direction:column;gap:1.5rem}.space-x-4{display:flex;gap:1.5rem}.space-y-5{display:flex;flex-direction:column;gap:2rem}.space-x-5{display:flex;gap:2rem}.space-y-6{display:flex;flex-direction:column;gap:2.5rem}.space-x-6{display:flex;gap:2.5rem}.divide-y>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y>:not(template):not(:first-child){padding-top:1rem!important}.divide-y>:not(template):not(:last-child){padding-bottom:1rem!important}.divide-x>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x>:not(template):not(:first-child){padding-left:1rem!important}.divide-x>:not(template):not(:last-child){padding-right:1rem!important}.divide-y-0>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-0>:not(template):not(:first-child){padding-top:0!important}.divide-y-0>:not(template):not(:last-child){padding-bottom:0!important}.divide-x-0>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-0>:not(template):not(:first-child){padding-left:0!important}.divide-x-0>:not(template):not(:last-child){padding-right:0!important}.divide-y-1>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-1>:not(template):not(:first-child){padding-top:.25rem!important}.divide-y-1>:not(template):not(:last-child){padding-bottom:.25rem!important}.divide-x-1>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-1>:not(template):not(:first-child){padding-left:.25rem!important}.divide-x-1>:not(template):not(:last-child){padding-right:.25rem!important}.divide-y-2>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-2>:not(template):not(:first-child){padding-top:.5rem!important}.divide-y-2>:not(template):not(:last-child){padding-bottom:.5rem!important}.divide-x-2>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-2>:not(template):not(:first-child){padding-left:.5rem!important}.divide-x-2>:not(template):not(:last-child){padding-right:.5rem!important}.divide-y-3>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-3>:not(template):not(:first-child){padding-top:1rem!important}.divide-y-3>:not(template):not(:last-child){padding-bottom:1rem!important}.divide-x-3>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-3>:not(template):not(:first-child){padding-left:1rem!important}.divide-x-3>:not(template):not(:last-child){padding-right:1rem!important}.divide-y-4>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-4>:not(template):not(:first-child){padding-top:1.5rem!important}.divide-y-4>:not(template):not(:last-child){padding-bottom:1.5rem!important}.divide-x-4>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-4>:not(template):not(:first-child){padding-left:1.5rem!important}.divide-x-4>:not(template):not(:last-child){padding-right:1.5rem!important}.divide-y-5>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-5>:not(template):not(:first-child){padding-top:2rem!important}.divide-y-5>:not(template):not(:last-child){padding-bottom:2rem!important}.divide-x-5>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-5>:not(template):not(:first-child){padding-left:2rem!important}.divide-x-5>:not(template):not(:last-child){padding-right:2rem!important}.divide-y-6>:not(template)~:not(template){border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-y-6>:not(template):not(:first-child){padding-top:2.5rem!important}.divide-y-6>:not(template):not(:last-child){padding-bottom:2.5rem!important}.divide-x-6>:not(template)~:not(template){border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)!important}.divide-x-6>:not(template):not(:first-child){padding-left:2.5rem!important}.divide-x-6>:not(template):not(:last-child){padding-right:2.5rem!important}.divide-y-fill{display:flex;flex-direction:column;height:100%}.divide-y-fill>:not(template){flex:1;display:flex;justify-content:center;flex-direction:column}.icon{--tblr-icon-size: 1.25rem;width:var(--tblr-icon-size);height:var(--tblr-icon-size);font-size:var(--tblr-icon-size);vertical-align:bottom;stroke-width:1.5}.icon:hover{text-decoration:none}.icon-inline{--tblr-icon-size: 1rem;vertical-align:-.2rem}.icon-filled{fill:currentColor}.icon-sm{--tblr-icon-size: 1rem;stroke-width:1}.icon-md{--tblr-icon-size: 2.5rem;stroke-width:1}.icon-lg{--tblr-icon-size: 3.5rem;stroke-width:1}.icon-pulse{transition:all .15s ease 0s;animation:pulse 2s ease infinite;animation-fill-mode:both}.icon-tada{transition:all .15s ease 0s;animation:tada 3s ease infinite;animation-fill-mode:both}.icon-rotate{transition:all .15s ease 0s;animation:rotate-360 3s linear infinite;animation-fill-mode:both}.img-responsive{--tblr-img-responsive-ratio: 75%;background:no-repeat center/cover;padding-top:var(--tblr-img-responsive-ratio)}.img-responsive-grid{padding-top:calc(var(--tblr-img-responsive-ratio) - var(--tblr-gutter-y) / 2)}.img-responsive-1x1{--tblr-img-responsive-ratio: 100%}.img-responsive-2x1{--tblr-img-responsive-ratio: 50%}.img-responsive-1x2{--tblr-img-responsive-ratio: 200%}.img-responsive-3x1{--tblr-img-responsive-ratio: 33.3333333333%}.img-responsive-1x3{--tblr-img-responsive-ratio: 300%}.img-responsive-4x1{--tblr-img-responsive-ratio: 25%}.img-responsive-1x4{--tblr-img-responsive-ratio: 400%}.img-responsive-4x3{--tblr-img-responsive-ratio: 75%}.img-responsive-3x4{--tblr-img-responsive-ratio: 133.3333333333%}.img-responsive-16x9{--tblr-img-responsive-ratio: 56.25%}.img-responsive-9x16{--tblr-img-responsive-ratio: 177.7777777778%}.img-responsive-21x9{--tblr-img-responsive-ratio: 42.8571428571%}.img-responsive-9x21{--tblr-img-responsive-ratio: 233.3333333333%}.img-bg{background:no-repeat center/cover}textarea[cols]{height:auto}.col-form-label,.form-label{display:block;font-weight:var(--tblr-font-weight-medium)}.col-form-label.required:after,.form-label.required:after{content:"*";margin-left:.25rem;color:#d63939}.form-label-description{float:right;font-weight:var(--tblr-font-weight-normal);color:var(--tblr-secondary)}.form-hint{display:block;color:var(--tblr-secondary)}.form-hint:last-child{margin-bottom:0}.form-hint+.form-control{margin-top:.25rem}.form-label+.form-hint{margin-top:-.25rem}.input-group+.form-hint,.form-control+.form-hint,.form-select+.form-hint{margin-top:.5rem;color:var(--tblr-secondary)}.form-select:-moz-focusring{color:var(--tblr-body-color)}.form-control:-webkit-autofill{box-shadow:0 0 0 1000px var(--tblr-bg-surface-secondary) inset;color:var(--tblr-body-color);-webkit-text-fill-color:var(--tblr-body-color)}.form-control:disabled,.form-control.disabled{color:var(--tblr-secondary);user-select:none}.form-control[size]{width:auto}.form-control-light{background-color:var(--tblr-gray-100);border-color:transparent}.form-control-dark{background-color:#0000001a;color:#fff;border-color:transparent}.form-control-dark:focus{background-color:#0000001a;box-shadow:none;border-color:#ffffff3d}.form-control-dark::placeholder{color:#fff9}.form-control-rounded{border-radius:10rem}.form-control-flush{padding:0;background:none!important;border-color:transparent!important;resize:none;box-shadow:none!important;line-height:inherit}.form-footer{margin-top:2rem}.form-fieldset{padding:1rem;margin-bottom:1rem;background:var(--tblr-bg-surface-secondary);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius)}fieldset:empty{display:none}.form-help{display:inline-flex;font-weight:var(--tblr-font-weight-bold);align-items:center;justify-content:center;width:1.125rem;height:1.125rem;font-size:.75rem;color:var(--tblr-secondary);text-align:center;text-decoration:none;cursor:pointer;user-select:none;background:var(--tblr-gray-100);border-radius:100rem;transition:background-color .3s,color .3s}@media(prefers-reduced-motion:reduce){.form-help{transition:none}}.form-help:hover,.form-help[aria-describedby]{color:#fff;background:var(--tblr-primary)}.input-group{box-shadow:var(--tblr-shadow-input);border-radius:var(--tblr-border-radius)}.input-group .form-control,.input-group .btn{box-shadow:none}.input-group-link{font-size:.75rem}.input-group-flat:focus-within{box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25);border-radius:var(--tblr-border-radius)}.input-group-flat:focus-within .form-control,.input-group-flat:focus-within .input-group-text{border-color:#80c2be!important}.input-group-flat .form-control:focus{border-color:var(--tblr-border-color);box-shadow:none}.input-group-flat .form-control:not(:last-child){border-right:0}.input-group-flat .form-control:not(:first-child){border-left:0}.input-group-flat .input-group-text{background:var(--tblr-bg-forms);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.input-group-flat .input-group-text{transition:none}}.input-group-flat .input-group-text:first-child{padding-right:0}.input-group-flat .input-group-text:last-child{padding-left:0}.form-file-button{margin-left:0;border-left:0}label[for=floating-input]{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:575.98px){.form-control,.form-select{font-size:1rem}}.input-icon{position:relative}.input-icon .form-control:not(:last-child),.input-icon .form-select:not(:last-child){padding-right:2.5rem}.input-icon .form-control:not(:first-child),.input-icon .form-select:not(:last-child){padding-left:2.5rem}.input-icon-addon{position:absolute;top:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;min-width:2.5rem;color:var(--tblr-icon-color);pointer-events:none;font-size:1.2em}.input-icon-addon:last-child{right:0;left:auto}.form-colorinput{position:relative;display:inline-block;margin:0;line-height:1;cursor:pointer}.form-colorinput-input{position:absolute;z-index:-1;opacity:0}.form-colorinput-color{display:block;width:1.5rem;height:1.5rem;color:#fff;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);border-radius:var(--tblr-border-radius);box-shadow:0 1px 2px #0000000d}.form-colorinput-color:before{position:absolute;top:0;left:0;width:100%;height:100%;content:"";background:no-repeat center center/1.25rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e");opacity:0;transition:opacity .3s}@media(prefers-reduced-motion:reduce){.form-colorinput-color:before{transition:none}}.form-colorinput-input:checked~.form-colorinput-color:before{opacity:1}.form-colorinput-input:focus~.form-colorinput-color{border-color:var(--tblr-primary);box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-colorinput-light .form-colorinput-color:before{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%231f2937' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e")}.form-imagecheck{--tblr-form-imagecheck-radius: var(--tblr-border-radius);position:relative;margin:0;cursor:pointer}.form-imagecheck-input{position:absolute;z-index:-1;opacity:0}.form-imagecheck-figure{position:relative;display:block;margin:0;user-select:none;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-form-imagecheck-radius)}.form-imagecheck-input:focus~.form-imagecheck-figure{border-color:var(--tblr-primary);box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-imagecheck-input:checked~.form-imagecheck-figure{border-color:var(--tblr-primary)}.form-imagecheck-figure:before{position:absolute;top:.25rem;left:.25rem;z-index:1;display:block;width:1.25rem;height:1.25rem;color:#fff;pointer-events:none;content:"";user-select:none;background:var(--tblr-bg-forms);border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius);transition:opacity .3s}@media(prefers-reduced-motion:reduce){.form-imagecheck-figure:before{transition:none}}.form-imagecheck-input:checked~.form-imagecheck-figure:before{background-color:var(--tblr-primary);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e");background-repeat:repeat;background-position:center;background-size:1.25rem;border-color:var(--tblr-border-color-translucent)}.form-imagecheck-input[type=radio]~.form-imagecheck-figure:before{border-radius:50%}.form-imagecheck-input[type=radio]:checked~.form-imagecheck-figure:before{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3ccircle r='3' fill='%23ffffff' cx='8' cy='8' /%3e%3c/svg%3e")}.form-imagecheck-image{max-width:100%;display:block;opacity:.64;transition:opacity .3s}@media(prefers-reduced-motion:reduce){.form-imagecheck-image{transition:none}}.form-imagecheck-image:first-child{border-top-left-radius:calc(var(--tblr-form-imagecheck-radius) - 1px);border-top-right-radius:calc(var(--tblr-form-imagecheck-radius) - 1px)}.form-imagecheck-image:last-child{border-bottom-right-radius:calc(var(--tblr-form-imagecheck-radius) - 1px);border-bottom-left-radius:calc(var(--tblr-form-imagecheck-radius) - 1px)}.form-imagecheck:hover .form-imagecheck-image,.form-imagecheck-input:focus~.form-imagecheck-figure .form-imagecheck-image,.form-imagecheck-input:checked~.form-imagecheck-figure .form-imagecheck-image{opacity:1}.form-imagecheck-caption{padding:.25rem;font-size:.765625rem;color:var(--tblr-secondary);text-align:center;transition:color .3s}@media(prefers-reduced-motion:reduce){.form-imagecheck-caption{transition:none}}.form-imagecheck:hover .form-imagecheck-caption,.form-imagecheck-input:focus~.form-imagecheck-figure .form-imagecheck-caption,.form-imagecheck-input:checked~.form-imagecheck-figure .form-imagecheck-caption{color:var(--tblr-body-color)}.form-selectgroup{display:inline-flex;margin:0 -.5rem -.5rem 0;flex-wrap:wrap}.form-selectgroup .form-selectgroup-item{margin:0 .5rem .5rem 0}.form-selectgroup-vertical{flex-direction:column}.form-selectgroup-item{display:block;position:relative}.form-selectgroup-input{position:absolute;top:0;left:0;z-index:-1;opacity:0}.form-selectgroup-label{position:relative;display:block;min-width:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2));margin:0;padding:.5625rem 1rem;font-size:.875rem;line-height:1.25rem;color:var(--tblr-secondary);background:var(--tblr-bg-forms);text-align:center;cursor:pointer;user-select:none;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);border-radius:var(--tblr-border-radius);box-shadow:var(--tblr-shadow-input);transition:border-color .3s,background .3s,color .3s}@media(prefers-reduced-motion:reduce){.form-selectgroup-label{transition:none}}.form-selectgroup-label .icon:only-child{margin:0 -.25rem}.form-selectgroup-label:hover{color:var(--tblr-body-color)}.form-selectgroup-check{display:inline-block;width:1.25rem;height:1.25rem;border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);vertical-align:middle;box-shadow:var(--tblr-shadow-input)}.form-selectgroup-input[type=checkbox]+.form-selectgroup-label .form-selectgroup-check{border-radius:var(--tblr-border-radius)}.form-selectgroup-input[type=radio]+.form-selectgroup-label .form-selectgroup-check{border-radius:50%}.form-selectgroup-input:checked+.form-selectgroup-label .form-selectgroup-check{background-color:var(--tblr-primary);background-repeat:repeat;background-position:center;background-size:1.25rem;border-color:var(--tblr-border-color-translucent)}.form-selectgroup-input[type=checkbox]:checked+.form-selectgroup-label .form-selectgroup-check{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8.5l2.5 2.5l5.5 -5.5'/%3e%3c/svg%3e")}.form-selectgroup-input[type=radio]:checked+.form-selectgroup-label .form-selectgroup-check{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3ccircle r='3' fill='%23ffffff' cx='8' cy='8' /%3e%3c/svg%3e")}.form-selectgroup-check-floated{position:absolute;top:.5625rem;right:.5625rem}.form-selectgroup-input:checked+.form-selectgroup-label{z-index:1;color:var(--tblr-primary);background:rgba(var(--tblr-primary-rgb),.04);border-color:var(--tblr-primary)}.form-selectgroup-input:focus+.form-selectgroup-label{z-index:2;color:var(--tblr-primary);border-color:var(--tblr-primary);box-shadow:0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.form-selectgroup-boxes .form-selectgroup-label{text-align:left;padding:1.25rem 1rem;color:inherit}.form-selectgroup-boxes .form-selectgroup-input:checked+.form-selectgroup-label{color:inherit}.form-selectgroup-boxes .form-selectgroup-input:checked+.form-selectgroup-label .form-selectgroup-title{color:var(--tblr-primary)}.form-selectgroup-boxes .form-selectgroup-input:checked+.form-selectgroup-label .form-selectgroup-label-content{opacity:1}.form-selectgroup-pills{flex-wrap:wrap;align-items:flex-start}.form-selectgroup-pills .form-selectgroup-item{flex-grow:0}.form-selectgroup-pills .form-selectgroup-label{border-radius:50px}.form-control-color::-webkit-color-swatch{border:none}[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}.form-control::file-selector-button{background-color:var(--tblr-btn-color, var(--tblr-tertiary-bg))}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--tblr-btn-color, var(--tblr-secondary-bg))}.form-check{user-select:none}.form-check.form-check-highlight .form-check-input:not(:checked)~.form-check-label{color:var(--tblr-secondary)}.form-check .form-check-label-off{color:var(--tblr-secondary)}.form-check .form-check-input:checked~.form-check-label-off{display:none}.form-check .form-check-input:not(:checked)~.form-check-label-on{display:none}.form-check-input{background-size:1.25rem;margin-top:0rem;box-shadow:var(--tblr-shadow-input)}.form-switch .form-check-input{transition:background-color .3s,background-position .3s}@media(prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-check-label{display:block}.form-check-label.required:after{content:"*";margin-left:.25rem;color:#d63939}.form-check-description{display:block;color:var(--tblr-secondary);font-size:.75rem;margin-top:.25rem}.form-check-single,.form-check-single .form-check-input{margin:0}.form-switch .form-check-input{height:1.25rem;margin-top:0rem}.form-switch-lg{padding-left:3.5rem;min-height:1.5rem}.form-switch-lg .form-check-input{height:1.5rem;width:2.75rem;background-size:1.5rem;margin-left:-3.5rem}.form-switch-lg .form-check-label{padding-top:.125rem}.form-check-input:checked{border:none}.form-select.is-invalid-lite,.form-control.is-invalid-lite,.form-select.is-valid-lite,.form-control.is-valid-lite{border-color:var(--tblr-border-color)!important}.legend{--tblr-legend-size: .75em;display:inline-block;background:var(--tblr-border-color);width:var(--tblr-legend-size);height:var(--tblr-legend-size);border-radius:var(--tblr-border-radius-sm);border:1px solid var(--tblr-border-color-translucent)}.list-group{margin-left:0;margin-right:0}.list-group-header{background:var(--tblr-bg-surface-tertiary);padding:.5rem 1.25rem;font-size:.75rem;font-weight:var(--tblr-font-weight-medium);line-height:1;text-transform:uppercase;color:var(--tblr-gray-500);border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.list-group-flush>.list-group-header:last-child{border-bottom-width:0}.list-group-item{background-color:inherit}.list-group-item.active{background-color:rgba(var(--tblr-secondary-rgb),.08);border-left-color:#00857d;border-left-width:2px}.list-group-item.disabled,.list-group-item:disabled{color:#6b7280;background-color:rgba(var(--tblr-secondary-rgb),.08)}.list-bordered .list-item{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);margin-top:-1px}.list-bordered .list-item:first-child{border-top:none}.list-group-hoverable .list-group-item:active,.list-group-hoverable .list-group-item:focus,.list-group-hoverable .list-group-item:hover{background-color:rgba(var(--tblr-secondary-rgb),.08)}.list-group-hoverable .list-group-item-actions{opacity:0;transition:opacity .3s}@media(prefers-reduced-motion:reduce){.list-group-hoverable .list-group-item-actions{transition:none}}.list-group-hoverable .list-group-item:hover .list-group-item-actions,.list-group-hoverable .list-group-item-actions.show{opacity:1}.list-group-transparent{--tblr-list-group-border-radius: 0;margin:0 -1.25rem}.list-group-transparent .list-group-item{background:none;border:0}.list-group-transparent .list-group-item .icon{color:var(--tblr-secondary)}.list-group-transparent .list-group-item.active{font-weight:var(--tblr-font-weight-bold);color:inherit;background:var(--tblr-active-bg)}.list-group-transparent .list-group-item.active .icon{color:inherit}.list-separated{display:flex;flex-direction:column;gap:1rem}.list-inline{margin:0}.list-inline-item:not(:last-child){margin-right:auto;margin-inline-end:.5rem}.list-inline-dots .list-inline-item+.list-inline-item:before{content:" \b7 ";margin-inline-end:.5rem}.loader{position:relative;display:block;width:2.5rem;height:2.5rem;color:#066fd1;vertical-align:middle}.loader:after{position:absolute;top:0;left:0;width:100%;height:100%;content:"";border:1px var(--tblr-border-style);border-color:transparent;border-top-color:currentColor;border-left-color:currentColor;border-radius:100rem;animation:rotate-360 .6s linear;animation-iteration-count:infinite}.dimmer{position:relative}.dimmer .loader{position:absolute;top:50%;right:0;left:0;display:none;margin:0 auto;transform:translateY(-50%)}.dimmer.active .loader{display:block}.dimmer.active .dimmer-content{pointer-events:none;opacity:.1}@keyframes animated-dots{0%{transform:translate(-100%)}}.animated-dots{display:inline-block;overflow:hidden;vertical-align:bottom}.animated-dots:after{display:inline-block;content:"...";animation:animated-dots 1.2s steps(4,jump-none) infinite}.modal-content>.btn-close,.modal-header>.btn-close{position:absolute;top:0;right:0;width:3.5rem;height:3.5rem;margin:0;padding:0;z-index:10}.modal-body{scrollbar-color:color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent) transparent}.modal-body::-webkit-scrollbar{width:1rem;height:1rem;transition:background .3s}@media(prefers-reduced-motion:reduce){.modal-body::-webkit-scrollbar{transition:none}}.modal-body::-webkit-scrollbar-thumb{border-radius:1rem;border:5px solid transparent;box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent)}.modal-body::-webkit-scrollbar-track{background:transparent}.modal-body:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 40%,transparent)}.modal-body::-webkit-scrollbar-corner{background:transparent}.modal-body .modal-title{margin-bottom:1rem}.modal-body+.modal-body{border-top:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.modal-status{position:absolute;top:0;left:0;right:0;height:2px;background:var(--tblr-secondary);border-radius:var(--tblr-border-radius-lg) var(--tblr-border-radius-lg) 0 0}.modal-header{align-items:center;min-height:3.5rem;background:transparent;padding:0 3.5rem 0 1.5rem}.modal-title{font-size:1rem;font-weight:var(--tblr-font-weight-bold);color:inherit;line-height:1.4285714286}.modal-footer{padding-top:.75rem;padding-bottom:.75rem}.modal-blur{backdrop-filter:blur(4px)}.modal-full-width{max-width:none;margin:0 .5rem}.nav{--tblr-nav-link-hover-bg: color-mix(in srgb, var(--tblr-nav-link-color) 4%, transparent)}.nav-vertical,.nav-vertical .nav{flex-direction:column;flex-wrap:nowrap}.nav-vertical .nav{margin-left:1.25rem;border-left:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);padding-left:.5rem}.nav-vertical .nav-link.active,.nav-vertical .nav-item.show .nav-link{font-weight:var(--tblr-font-weight-bold);color:var(--tblr-nav-link-active-color)}.nav-vertical.nav-pills{margin:0 -.75rem}.nav-bordered{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.nav-bordered .nav-item+.nav-item{margin-left:1.25rem}.nav-bordered .nav-link{padding-left:0;padding-right:0;margin:0 0 calc(-1 * var(--tblr-border-width));border:0;border-bottom:2px var(--tblr-border-style) transparent}.nav-bordered .nav-link:hover{background-color:transparent}.nav-bordered .nav-link.active,.nav-bordered .nav-item.show .nav-link{color:var(--tblr-primary);border-color:var(--tblr-primary)}.nav-underline .nav-link{border-radius:0}.nav-link{display:flex;transition:color .3s,background-color .3s}@media(prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link{align-items:center}.nav-link:hover,.nav-link:focus{background-color:var(--tblr-nav-link-hover-bg)}.nav-link-toggle{margin-left:auto;padding:0 .25rem;transition:transform .3s}@media(prefers-reduced-motion:reduce){.nav-link-toggle{transition:none}}.nav-link-toggle:after{content:"";display:inline-block;vertical-align:.306em;width:.36em;height:.36em;border-bottom:1px var(--tblr-border-style);border-left:1px var(--tblr-border-style);margin-right:.1em;margin-left:.4em;transform:rotate(-45deg)}.nav-link-toggle:after{margin:0}.nav-link[aria-expanded=true] .nav-link-toggle{transform:rotate(180deg)}.nav-link-icon{width:1.25rem;height:1.25rem;margin-right:.5rem;color:inherit}.nav-link-icon svg{display:block;height:100%}.nav-fill .nav-item .nav-link{justify-content:center}.stars{display:inline-flex;color:#9ca3af;font-size:.75rem}.stars .star:not(:first-child){margin-left:.25rem}.pagination{margin:0;--tblr-pagination-gap: .25rem;user-select:none;gap:var(--tblr-pagination-gap);line-height:var(--tblr-body-line-height)}.page-link{min-width:2rem;border-radius:var(--tblr-pagination-border-radius)}.page-item:not(.active) .page-link:hover{background:var(--tblr-pagination-hover-bg)}.page-text{padding-left:.5rem;padding-right:.5rem}.page-item{text-align:center}.page-item.page-prev,.page-item.page-next{flex:0 0 50%;text-align:left}.page-item.page-next{margin-left:auto;text-align:right}.page-item-subtitle{margin-bottom:2px;font-size:12px;color:var(--tblr-secondary);text-transform:uppercase}.page-item.disabled .page-item-subtitle{color:var(--tblr-disabled-color)}.page-item-title{font-size:1rem;font-weight:var(--tblr-font-weight-normal);color:var(--tblr-body-color)}.page-link:hover .page-item-title{color:#00857d}.page-item.disabled .page-item-title{color:var(--tblr-disabled-color)}.pagination-outline{--tblr-pagination-border-color: var(--tblr-border-color);--tblr-pagination-disabled-border-color: var(--tblr-border-color);--tblr-pagination-border-width: 1px}.pagination-circle{--tblr-pagination-border-radius: var(--tblr-border-radius-pill)}@keyframes progress-indeterminate{0%{right:100%;left:-35%}to,60%{right:-90%;left:100%}}.progress{position:relative;width:100%;line-height:.5rem;appearance:none}.progress::-webkit-progress-bar{background:var(--tblr-progress-bg)}.progress::-webkit-progress-value{background-color:var(--tblr-primary)}.progress::-moz-progress-bar{background-color:var(--tblr-primary)}.progress::-ms-fill{background-color:var(--tblr-primary);border:none}.progress-sm{height:.25rem}.progress-bar{height:100%}.progress-bar-indeterminate:after,.progress-bar-indeterminate:before{position:absolute;top:0;bottom:0;left:0;content:"";background-color:inherit;will-change:left,right}.progress-bar-indeterminate:before{animation:progress-indeterminate 1.5s cubic-bezier(.65,.815,.735,.395) infinite}.progress-separated .progress-bar{box-shadow:0 0 0 2px var(--tblr-card-bg, var(--tblr-bg-surface))}.progressbg{position:relative;padding:.25rem .5rem;display:flex}.progressbg-text{position:relative;z-index:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.progressbg-progress{position:absolute;inset:0;z-index:0;height:100%;background:transparent;pointer-events:none}.progressbg-value{font-weight:var(--tblr-font-weight-medium);margin-left:auto;padding-left:2rem}.ribbon{--tblr-ribbon-margin: .25rem;--tblr-ribbon-border-radius: var(--tblr-border-radius);position:absolute;top:.75rem;right:calc(-1 * var(--tblr-ribbon-margin));z-index:1;padding:.25rem .75rem;font-size:.625rem;font-weight:var(--tblr-font-weight-bold);line-height:1;color:#fff;text-align:center;text-transform:uppercase;background:var(--tblr-primary);border-color:var(--tblr-primary);border-radius:var(--tblr-ribbon-border-radius) 0 var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius);display:inline-flex;align-items:center;justify-content:center;min-height:2rem;min-width:2rem}.ribbon:before{position:absolute;right:0;bottom:100%;width:0;height:0;content:"";filter:brightness(70%);border:calc(var(--tblr-ribbon-margin) * .5) var(--tblr-border-style);border-color:inherit;border-top-color:transparent;border-right-color:transparent}.ribbon.bg-blue{border-color:var(--tblr-blue)}.ribbon.bg-blue-lt{border-color:rgba(var(--tblr-blue-rgb),.1)!important}.ribbon.bg-azure{border-color:var(--tblr-azure)}.ribbon.bg-azure-lt{border-color:rgba(var(--tblr-azure-rgb),.1)!important}.ribbon.bg-indigo{border-color:var(--tblr-indigo)}.ribbon.bg-indigo-lt{border-color:rgba(var(--tblr-indigo-rgb),.1)!important}.ribbon.bg-purple{border-color:var(--tblr-purple)}.ribbon.bg-purple-lt{border-color:rgba(var(--tblr-purple-rgb),.1)!important}.ribbon.bg-pink{border-color:var(--tblr-pink)}.ribbon.bg-pink-lt{border-color:rgba(var(--tblr-pink-rgb),.1)!important}.ribbon.bg-red{border-color:var(--tblr-red)}.ribbon.bg-red-lt{border-color:rgba(var(--tblr-red-rgb),.1)!important}.ribbon.bg-orange{border-color:var(--tblr-orange)}.ribbon.bg-orange-lt{border-color:rgba(var(--tblr-orange-rgb),.1)!important}.ribbon.bg-yellow{border-color:var(--tblr-yellow)}.ribbon.bg-yellow-lt{border-color:rgba(var(--tblr-yellow-rgb),.1)!important}.ribbon.bg-lime{border-color:var(--tblr-lime)}.ribbon.bg-lime-lt{border-color:rgba(var(--tblr-lime-rgb),.1)!important}.ribbon.bg-green{border-color:var(--tblr-green)}.ribbon.bg-green-lt{border-color:rgba(var(--tblr-green-rgb),.1)!important}.ribbon.bg-teal{border-color:var(--tblr-teal)}.ribbon.bg-teal-lt{border-color:rgba(var(--tblr-teal-rgb),.1)!important}.ribbon.bg-cyan{border-color:var(--tblr-cyan)}.ribbon.bg-cyan-lt{border-color:rgba(var(--tblr-cyan-rgb),.1)!important}.ribbon .icon{width:1.25rem;height:1.25rem;font-size:1.25rem}.ribbon-top{top:calc(-1 * var(--tblr-ribbon-margin));right:.75rem;width:2rem;padding:.5rem 0;border-radius:0 var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius)}.ribbon-top:before{top:0;right:100%;bottom:auto;border-color:inherit;border-top-color:transparent;border-left-color:transparent}.ribbon-top.ribbon-start{right:auto;left:.75rem}.ribbon-top.ribbon-start:before{top:0;right:100%;left:auto}.ribbon-start{right:auto;left:calc(-1 * var(--tblr-ribbon-margin));border-radius:0 var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius) var(--tblr-ribbon-border-radius)}.ribbon-start:before{top:auto;bottom:100%;left:0;border-color:inherit;border-top-color:transparent;border-left-color:transparent}.ribbon-bottom{top:auto;bottom:.75rem}.ribbon-bookmark{padding-left:.25rem;border-radius:0 0 var(--tblr-ribbon-border-radius) 0}.ribbon-bookmark:after{position:absolute;top:0;right:100%;display:block;width:0;height:0;content:"";border:1rem var(--tblr-border-style);border-color:inherit;border-right-width:0;border-left-color:transparent;border-left-width:.5rem}.ribbon-bookmark.ribbon-left{padding-right:.5rem}.ribbon-bookmark.ribbon-left:after{right:auto;left:100%;border-right-color:transparent;border-right-width:.5rem;border-left-width:0}.ribbon-bookmark.ribbon-top{padding-right:0;padding-bottom:.25rem;padding-left:0;border-radius:0 var(--tblr-ribbon-border-radius) 0 0}.ribbon-bookmark.ribbon-top:after{top:100%;right:0;left:0;border-color:inherit;border-width:1rem;border-top-width:0;border-bottom-color:transparent;border-bottom-width:.5rem}.markdown{line-height:2}.markdown>:first-child{margin-top:0}.markdown>:last-child,.markdown>:last-child .highlight{margin-bottom:0}@media(min-width:768px){.markdown>hr,.markdown>.hr{margin-top:3em;margin-bottom:3em}}.markdown>h1,.markdown>.h1,.markdown>h2,.markdown>.h2,.markdown>h3,.markdown>.h3,.markdown>h4,.markdown>.h4,.markdown>h5,.markdown>.h5,.markdown>h6,.markdown>.h6{font-weight:var(--tblr-font-weight-bold)}.markdown>h2,.markdown>.h2,.markdown>h3,.markdown>.h3,.markdown>h4,.markdown>.h4,.markdown>h5,.markdown>.h5,.markdown>h6,.markdown>.h6{margin-top:2.5rem}.markdown>table{font-size:var(--tblr-body-font-size)}.markdown>blockquote{font-size:1rem;margin:1.5rem 0;padding:.5rem 1.5rem}.markdown>img,.markdown>p>img{border-radius:var(--tblr-border-radius);border:1px solid var(--tblr-border-color)}.markdown pre{max-height:20rem}.placeholder:not(.btn):not([class*=bg-]){background-color:currentColor!important}.placeholder:not(.avatar):not([class*=card-img-]){border-radius:var(--tblr-border-radius)}.nav-segmented{--tblr-nav-bg: var(--tblr-bg-surface-tertiary);--tblr-nav-padding: 2px;--tblr-nav-height: 2.5rem;--tblr-nav-gap: .25rem;--tblr-nav-active-bg: var(--tblr-bg-surface);--tblr-nav-font-size: inherit;--tblr-nav-radius: 6px;--tblr-nav-link-disabled-color: var(--tblr-disabled-color);--tblr-nav-link-gap: .25rem;--tblr-nav-link-padding-x: .75rem;--tblr-nav-link-icon-size: 1.25rem;display:inline-flex;flex-wrap:wrap;gap:var(--tblr-nav-gap);padding:var(--tblr-nav-padding);list-style:none;background:var(--tblr-nav-bg);border-radius:calc(var(--tblr-nav-radius) + var(--tblr-nav-padding));box-shadow:inset 0 0 0 1px #0000000a}.nav-segmented .nav-link{display:inline-flex;gap:calc(.25rem + var(--tblr-nav-link-gap));align-items:center;margin:0;font-size:var(--tblr-nav-font-size);min-width:calc(var(--tblr-nav-height) - 2 * var(--tblr-nav-padding));height:calc(var(--tblr-nav-height) - 2 * var(--tblr-nav-padding));padding:0 calc(var(--tblr-nav-link-padding-x) - 2px);border:1px solid transparent;background:transparent;color:var(--tblr-secondary);text-align:center;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .3s,color .3s;border-radius:var(--tblr-nav-radius);flex-grow:1;justify-content:center}.nav-segmented .nav-link:hover,.nav-segmented .nav-link.hover{background:#0000000a;color:var(--tblr-body-color)}.nav-segmented .nav-link.disabled,.nav-segmented .nav-link:disabled{color:var(--tblr-nav-link-disabled-color);cursor:not-allowed}.nav-segmented .nav-link-input:checked+.nav-link,.nav-segmented .nav-link.active{color:var(--tblr-body-color);background:var(--tblr-nav-active-bg);border-color:var(--tblr-border-color)}.nav-segmented .nav-link-input{display:none}.nav-segmented .nav-link-icon{width:var(--tblr-nav-link-icon-size);height:var(--tblr-nav-link-icon-size);margin:0 -.25rem;color:inherit}.nav-segmented-vertical{flex-direction:column}.nav-segmented-vertical .nav-link{justify-content:flex-start}.nav-sm{--tblr-nav-height: 2rem;--tblr-nav-font-size: var(--tblr-font-size-h5);--tblr-nav-radius: 4px;--tblr-nav-link-padding-x: .5rem;--tblr-nav-link-gap: .25rem;--tblr-nav-link-icon-size: 1rem}.nav-lg{--tblr-nav-height: 3rem;--tblr-nav-font-size: var(--tblr-font-size-h3);--tblr-nav-radius: 8px;--tblr-nav-link-padding-x: 1rem;--tblr-nav-link-gap: .5rem;--tblr-nav-link-icon-size: 1.5rem}.steps{--tblr-steps-color: var(--tblr-primary);--tblr-steps-inactive-color: var(--tblr-border-color);--tblr-steps-dot-size: .5rem;--tblr-steps-border-width: 2px;display:flex;flex-wrap:nowrap;width:100%;padding:0;margin:0;list-style:none}.steps-blue{--tblr-steps-color: var(--tblr-blue)}.steps-blue-lt{--tblr-steps-color: var(--tblr-blue-lt)}.steps-azure{--tblr-steps-color: var(--tblr-azure)}.steps-azure-lt{--tblr-steps-color: var(--tblr-azure-lt)}.steps-indigo{--tblr-steps-color: var(--tblr-indigo)}.steps-indigo-lt{--tblr-steps-color: var(--tblr-indigo-lt)}.steps-purple{--tblr-steps-color: var(--tblr-purple)}.steps-purple-lt{--tblr-steps-color: var(--tblr-purple-lt)}.steps-pink{--tblr-steps-color: var(--tblr-pink)}.steps-pink-lt{--tblr-steps-color: var(--tblr-pink-lt)}.steps-red{--tblr-steps-color: var(--tblr-red)}.steps-red-lt{--tblr-steps-color: var(--tblr-red-lt)}.steps-orange{--tblr-steps-color: var(--tblr-orange)}.steps-orange-lt{--tblr-steps-color: var(--tblr-orange-lt)}.steps-yellow{--tblr-steps-color: var(--tblr-yellow)}.steps-yellow-lt{--tblr-steps-color: var(--tblr-yellow-lt)}.steps-lime{--tblr-steps-color: var(--tblr-lime)}.steps-lime-lt{--tblr-steps-color: var(--tblr-lime-lt)}.steps-green{--tblr-steps-color: var(--tblr-green)}.steps-green-lt{--tblr-steps-color: var(--tblr-green-lt)}.steps-teal{--tblr-steps-color: var(--tblr-teal)}.steps-teal-lt{--tblr-steps-color: var(--tblr-teal-lt)}.steps-cyan{--tblr-steps-color: var(--tblr-cyan)}.steps-cyan-lt{--tblr-steps-color: var(--tblr-cyan-lt)}.step-item{position:relative;flex:1 1 0;min-height:1rem;margin-top:0;color:inherit;text-align:center;cursor:default;padding-top:calc(var(--tblr-steps-dot-size))}a.step-item{cursor:pointer}a.step-item:hover{color:inherit}.step-item:after,.step-item:before{background:var(--tblr-steps-color)}.step-item:not(:last-child):after{position:absolute;left:50%;width:100%;content:"";transform:translateY(-50%)}.step-item:after{top:calc(var(--tblr-steps-dot-size) * .5);height:var(--tblr-steps-border-width)}.step-item:before{content:"";position:absolute;top:0;left:50%;z-index:1;box-sizing:content-box;display:flex;align-items:center;justify-content:center;border-radius:100rem;transform:translate(-50%);color:var(--tblr-white);width:var(--tblr-steps-dot-size);height:var(--tblr-steps-dot-size)}.step-item.active{font-weight:var(--tblr-font-weight-bold)}.step-item.active:after{background:var(--tblr-steps-inactive-color)}.step-item.active~.step-item{color:var(--tblr-disabled-color)}.step-item.active~.step-item:after,.step-item.active~.step-item:before{background:var(--tblr-steps-inactive-color)}.steps-counter{--tblr-steps-dot-size: 1.5rem;counter-reset:steps}.steps-counter .step-item{counter-increment:steps}.steps-counter .step-item:before{content:counter(steps)}.steps-vertical{--tblr-steps-dot-offset: 6px;flex-direction:column}.steps-vertical.steps-counter{--tblr-steps-dot-offset: -2px}.steps-vertical .step-item{text-align:left;padding-top:0;padding-left:calc(var(--tblr-steps-dot-size) + 1rem);min-height:auto}.steps-vertical .step-item:not(:first-child){margin-top:1rem}.steps-vertical .step-item:before{top:var(--tblr-steps-dot-offset);left:0;transform:translate(0)}.steps-vertical .step-item:not(:last-child):after{position:absolute;content:"";transform:translate(-50%);top:var(--tblr-steps-dot-offset);left:calc(var(--tblr-steps-dot-size) * .5);width:var(--tblr-steps-border-width);height:calc(100% + 1rem)}@keyframes status-pulsate-main{40%{transform:scale(1.25)}60%{transform:scale(1.25)}}@keyframes status-pulsate-secondary{10%{transform:scale(1)}30%{transform:scale(3)}80%{transform:scale(3)}to{transform:scale(1)}}@keyframes status-pulsate-tertiary{25%{transform:scale(1)}80%{transform:scale(3);opacity:0}to{transform:scale(3);opacity:0}}.status{--tblr-status-height: 1.5rem;--tblr-status-color: #6b7280;--tblr-status-color-rgb: 107, 114, 128;display:inline-flex;align-items:center;height:var(--tblr-status-height);padding:.25rem .75rem;gap:.5rem;color:var(--tblr-status-color);background:rgba(var(--tblr-status-color-rgb),.1);font-size:.875rem;text-transform:none;letter-spacing:normal;border-radius:100rem;font-weight:var(--tblr-font-weight-medium);line-height:1;margin:0}.status .status-dot{background:var(--tblr-status-color)}.status .icon{font-size:1.25rem}.status-lite{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)!important;background:transparent!important;color:var(--tblr-body-color)!important}.status-primary{--tblr-status-color: #00857D;--tblr-status-color-rgb: 0, 133, 125}.status-secondary{--tblr-status-color: #6b7280;--tblr-status-color-rgb: 107, 114, 128}.status-success{--tblr-status-color: #2fb344;--tblr-status-color-rgb: 47, 179, 68}.status-info{--tblr-status-color: #4299e1;--tblr-status-color-rgb: 66, 153, 225}.status-warning{--tblr-status-color: #f59f00;--tblr-status-color-rgb: 245, 159, 0}.status-danger{--tblr-status-color: #d63939;--tblr-status-color-rgb: 214, 57, 57}.status-light{--tblr-status-color: #f9fafb;--tblr-status-color-rgb: 249, 250, 251}.status-dark{--tblr-status-color: #1f2937;--tblr-status-color-rgb: 31, 41, 55}.status-muted{--tblr-status-color: #6b7280;--tblr-status-color-rgb: 107, 114, 128}.status-blue{--tblr-status-color: #066fd1;--tblr-status-color-rgb: 6, 111, 209}.status-azure{--tblr-status-color: #4299e1;--tblr-status-color-rgb: 66, 153, 225}.status-indigo{--tblr-status-color: #4263eb;--tblr-status-color-rgb: 66, 99, 235}.status-purple{--tblr-status-color: #ae3ec9;--tblr-status-color-rgb: 174, 62, 201}.status-pink{--tblr-status-color: #d6336c;--tblr-status-color-rgb: 214, 51, 108}.status-red{--tblr-status-color: #d63939;--tblr-status-color-rgb: 214, 57, 57}.status-orange{--tblr-status-color: #f76707;--tblr-status-color-rgb: 247, 103, 7}.status-yellow{--tblr-status-color: #f59f00;--tblr-status-color-rgb: 245, 159, 0}.status-lime{--tblr-status-color: #74b816;--tblr-status-color-rgb: 116, 184, 22}.status-green{--tblr-status-color: #2fb344;--tblr-status-color-rgb: 47, 179, 68}.status-teal{--tblr-status-color: #0ca678;--tblr-status-color-rgb: 12, 166, 120}.status-cyan{--tblr-status-color: #17a2b8;--tblr-status-color-rgb: 23, 162, 184}.status-dot{--tblr-status-dot-color: var(--tblr-status-color, #6b7280);--tblr-status-size: .5rem;position:relative;display:inline-block;width:var(--tblr-status-size);height:var(--tblr-status-size);background:var(--tblr-status-dot-color);border-radius:100rem}.status-dot-animated:before{content:"";position:absolute;inset:0;z-index:0;background:inherit;border-radius:inherit;opacity:.6;animation:1s linear 2s backwards infinite status-pulsate-tertiary}.status-indicator{--tblr-status-indicator-size: 2.5rem;--tblr-status-indicator-color: var(--tblr-status-color, #6b7280);display:block;position:relative;width:var(--tblr-status-indicator-size);height:var(--tblr-status-indicator-size)}.status-indicator-circle{--tblr-status-circle-size: .75rem;position:absolute;left:50%;top:50%;margin:calc(var(--tblr-status-circle-size) / -2) 0 0 calc(var(--tblr-status-circle-size) / -2);width:var(--tblr-status-circle-size);height:var(--tblr-status-circle-size);border-radius:100rem;background:var(--tblr-status-color)}.status-indicator-circle:nth-child(1){z-index:3}.status-indicator-circle:nth-child(2){z-index:2;opacity:.1}.status-indicator-circle:nth-child(3){z-index:1;opacity:.3}.status-indicator-animated .status-indicator-circle:nth-child(1){animation:2s linear 1s infinite backwards status-pulsate-main}.status-indicator-animated .status-indicator-circle:nth-child(2){animation:2s linear 1s infinite backwards status-pulsate-secondary}.status-indicator-animated .status-indicator-circle:nth-child(3){animation:2s linear 1s infinite backwards status-pulsate-tertiary}.switch-icon{display:inline-block;line-height:1;border:0;padding:0;background:transparent;width:1.25rem;height:1.25rem;vertical-align:bottom;position:relative;cursor:pointer}.switch-icon.disabled{pointer-events:none;opacity:.4}.switch-icon:focus{outline:none}.switch-icon svg{display:block;width:100%;height:100%}.switch-icon .switch-icon-a,.switch-icon .switch-icon-b{display:block;width:100%;height:100%}.switch-icon .switch-icon-a{opacity:1}.switch-icon .switch-icon-b{position:absolute;top:0;left:0;opacity:0}.switch-icon.active .switch-icon-a{opacity:0}.switch-icon.active .switch-icon-b{opacity:1}.switch-icon-fade .switch-icon-a,.switch-icon-fade .switch-icon-b{transition:opacity .5s}@media(prefers-reduced-motion:reduce){.switch-icon-fade .switch-icon-a,.switch-icon-fade .switch-icon-b{transition:none}}.switch-icon-scale .switch-icon-a,.switch-icon-scale .switch-icon-b{transition:opacity .5s,transform 0s .5s}@media(prefers-reduced-motion:reduce){.switch-icon-scale .switch-icon-a,.switch-icon-scale .switch-icon-b{transition:none}}.switch-icon-scale .switch-icon-b{transform:scale(1.5)}.switch-icon-scale.active .switch-icon-a,.switch-icon-scale.active .switch-icon-b{transition:opacity 0s,transform .5s}@media(prefers-reduced-motion:reduce){.switch-icon-scale.active .switch-icon-a,.switch-icon-scale.active .switch-icon-b{transition:none}}.switch-icon-scale.active .switch-icon-b{transform:scale(1)}.switch-icon-flip{perspective:10em}.switch-icon-flip .switch-icon-a,.switch-icon-flip .switch-icon-b{backface-visibility:hidden;transform-style:preserve-3d;transition:opacity 0s .2s,transform .4s ease-in-out}@media(prefers-reduced-motion:reduce){.switch-icon-flip .switch-icon-a,.switch-icon-flip .switch-icon-b{transition:none}}.switch-icon-flip .switch-icon-a{opacity:1;transform:rotateY(0)}.switch-icon-flip .switch-icon-b{opacity:1;transform:rotateY(-180deg)}.switch-icon-flip.active .switch-icon-a{opacity:1;transform:rotateY(180deg)}.switch-icon-flip.active .switch-icon-b{opacity:1;transform:rotateY(0)}.switch-icon-slide-up,.switch-icon-slide-left,.switch-icon-slide-start,.switch-icon-slide-right,.switch-icon-slide-end,.switch-icon-slide-down{overflow:hidden}.switch-icon-slide-up .switch-icon-a,.switch-icon-slide-up .switch-icon-b,.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-a,.switch-icon-slide-start .switch-icon-b,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-a,.switch-icon-slide-end .switch-icon-b,.switch-icon-slide-down .switch-icon-a,.switch-icon-slide-down .switch-icon-b{transition:opacity .3s,transform .3s}@media(prefers-reduced-motion:reduce){.switch-icon-slide-up .switch-icon-a,.switch-icon-slide-up .switch-icon-b,.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-a,.switch-icon-slide-start .switch-icon-b,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-a,.switch-icon-slide-end .switch-icon-b,.switch-icon-slide-down .switch-icon-a,.switch-icon-slide-down .switch-icon-b{transition:none}}.switch-icon-slide-up .switch-icon-a,.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-start .switch-icon-a,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-end .switch-icon-a,.switch-icon-slide-down .switch-icon-a{transform:translateY(0)}.switch-icon-slide-up .switch-icon-b,.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-b,.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-b,.switch-icon-slide-down .switch-icon-b{transform:translateY(100%)}.switch-icon-slide-up.active .switch-icon-a,.switch-icon-slide-left.active .switch-icon-a,.switch-icon-slide-start.active .switch-icon-a,.switch-icon-slide-right.active .switch-icon-a,.switch-icon-slide-end.active .switch-icon-a,.switch-icon-slide-down.active .switch-icon-a{transform:translateY(-100%)}.switch-icon-slide-up.active .switch-icon-b,.switch-icon-slide-left.active .switch-icon-b,.switch-icon-slide-start.active .switch-icon-b,.switch-icon-slide-right.active .switch-icon-b,.switch-icon-slide-end.active .switch-icon-b,.switch-icon-slide-down.active .switch-icon-b{transform:translateY(0)}.switch-icon-slide-left .switch-icon-a,.switch-icon-slide-start .switch-icon-a{transform:translate(0)}.switch-icon-slide-left .switch-icon-b,.switch-icon-slide-start .switch-icon-b{transform:translate(100%)}.switch-icon-slide-left.active .switch-icon-a,.switch-icon-slide-start.active .switch-icon-a{transform:translate(-100%)}.switch-icon-slide-left.active .switch-icon-b,.switch-icon-slide-start.active .switch-icon-b,.switch-icon-slide-right .switch-icon-a,.switch-icon-slide-end .switch-icon-a{transform:translate(0)}.switch-icon-slide-right .switch-icon-b,.switch-icon-slide-end .switch-icon-b{transform:translate(-100%)}.switch-icon-slide-right.active .switch-icon-a,.switch-icon-slide-end.active .switch-icon-a{transform:translate(100%)}.switch-icon-slide-right.active .switch-icon-b,.switch-icon-slide-end.active .switch-icon-b{transform:translate(0)}.switch-icon-slide-down .switch-icon-a{transform:translateY(0)}.switch-icon-slide-down .switch-icon-b{transform:translateY(-100%)}.switch-icon-slide-down.active .switch-icon-a{transform:translateY(100%)}.switch-icon-slide-down.active .switch-icon-b{transform:translateY(0)}.table thead th,.markdown>table thead th{background:var(--tblr-bg-surface-tertiary);font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);padding-top:.5rem;padding-bottom:.5rem;white-space:nowrap}@media print{.table thead th,.markdown>table thead th{background:transparent}}.table-responsive .table,.table-responsive .markdown>table{margin-bottom:0}.table-responsive+.card-footer{border-top:0}.table-transparent thead th{background:transparent}.table-nowrap>:not(caption)>*>*{white-space:nowrap}.table-vcenter>:not(caption)>*>*{vertical-align:middle}.table-center>:not(caption)>*>*{text-align:center}.td-truncate{max-width:1px;width:100%}.table-mobile{display:block}.table-mobile thead{display:none}.table-mobile tbody,.table-mobile tr{display:flex;flex-direction:column}.table-mobile td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile .btn{display:block}@media(max-width:575.98px){.table-mobile-sm{display:block}.table-mobile-sm thead{display:none}.table-mobile-sm tbody,.table-mobile-sm tr{display:flex;flex-direction:column}.table-mobile-sm td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-sm td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-sm tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-sm .btn{display:block}}@media(max-width:767.98px){.table-mobile-md{display:block}.table-mobile-md thead{display:none}.table-mobile-md tbody,.table-mobile-md tr{display:flex;flex-direction:column}.table-mobile-md td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-md td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-md tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-md .btn{display:block}}@media(max-width:991.98px){.table-mobile-lg{display:block}.table-mobile-lg thead{display:none}.table-mobile-lg tbody,.table-mobile-lg tr{display:flex;flex-direction:column}.table-mobile-lg td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-lg td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-lg tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-lg .btn{display:block}}@media(max-width:1199.98px){.table-mobile-xl{display:block}.table-mobile-xl thead{display:none}.table-mobile-xl tbody,.table-mobile-xl tr{display:flex;flex-direction:column}.table-mobile-xl td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-xl td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-xl tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-xl .btn{display:block}}@media(max-width:1399.98px){.table-mobile-xxl{display:block}.table-mobile-xxl thead{display:none}.table-mobile-xxl tbody,.table-mobile-xxl tr{display:flex;flex-direction:column}.table-mobile-xxl td{display:block;padding:.5rem!important;border:none;color:var(--tblr-body-color)!important}.table-mobile-xxl td[data-label]:before{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);content:attr(data-label);display:block}.table-mobile-xxl tr{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent)}.table-mobile-xxl .btn{display:block}}.table-sort{font:inherit;color:inherit;text-transform:inherit;letter-spacing:inherit;border:0;background:inherit;display:block;width:100%;text-align:inherit;transition:color .3s}@media(prefers-reduced-motion:reduce){.table-sort{transition:none}}.table-sort{margin:-.5rem;padding:.5rem}.table-sort:hover,.table-sort.asc,.table-sort.desc{color:var(--tblr-body-color)}.table-sort:after{content:"";display:inline-flex;width:1rem;height:1rem;vertical-align:bottom;mask-image:url("data:image/svg+xml,");background:currentColor;margin-left:.25rem}.table-sort.asc:after{mask-image:url("data:image/svg+xml,")}.table-sort.desc:after{mask-image:url("data:image/svg+xml,")}.table-borderless thead th{background:transparent}.table-selectable tbody tr .on-checked{display:none}.table-selectable tbody tr .on-unchecked{display:initial}.table-selectable tbody tr:has(.table-selectable-check:checked){background-color:var(--tblr-active-bg)}.table-selectable tbody tr:has(.table-selectable-check:checked) .on-checked{display:initial}.table-selectable tbody tr:has(.table-selectable-check:checked) .on-unchecked{display:none}.tag{--tblr-tag-height: 1.5rem;border:1px solid var(--tblr-border-color);display:inline-flex;align-items:center;height:var(--tblr-tag-height);border-radius:var(--tblr-border-radius);padding:0 .5rem;background:var(--tblr-bg-surface);box-shadow:var(--tblr-shadow-input);gap:.5rem}.tag .btn-close{margin-right:-.25rem;margin-left:-.125rem;padding:0;width:1rem;height:1rem;font-size:.5rem}.tag-badge{--tblr-badge-font-size: .625rem;--tblr-badge-padding-x: .25rem;--tblr-badge-padding-y: .125rem;margin-right:-.25rem}.tag-avatar,.tag-flag,.tag-payment,.tag-icon,.tag-check{margin-left:-.25rem}.tag-icon{color:var(--tblr-secondary);margin-right:-.125rem;width:1rem;height:1rem}.tag-check{width:1rem;height:1rem;background-size:1rem}.tags-list{--tblr-list-gap: .5rem;display:flex;flex-wrap:wrap;gap:var(--tblr-list-gap)}.toast{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color-translucent);box-shadow:#1f29370a 0 2px 4px}.toast .toast-header{user-select:none}.toast button[data-bs-dismiss=toast]{outline:none}.toast-primary{--tblr-toast-color: #00857D}.toast-secondary{--tblr-toast-color: #6b7280}.toast-success{--tblr-toast-color: #2fb344}.toast-info{--tblr-toast-color: #4299e1}.toast-warning{--tblr-toast-color: #f59f00}.toast-danger{--tblr-toast-color: #d63939}.toast-light{--tblr-toast-color: #f9fafb}.toast-dark{--tblr-toast-color: #1f2937}.toast-muted{--tblr-toast-color: #6b7280}.toast-blue{--tblr-toast-color: #066fd1}.toast-azure{--tblr-toast-color: #4299e1}.toast-indigo{--tblr-toast-color: #4263eb}.toast-purple{--tblr-toast-color: #ae3ec9}.toast-pink{--tblr-toast-color: #d6336c}.toast-red{--tblr-toast-color: #d63939}.toast-orange{--tblr-toast-color: #f76707}.toast-yellow{--tblr-toast-color: #f59f00}.toast-lime{--tblr-toast-color: #74b816}.toast-green{--tblr-toast-color: #2fb344}.toast-teal{--tblr-toast-color: #0ca678}.toast-cyan{--tblr-toast-color: #17a2b8}.toolbar{display:flex;flex-wrap:nowrap;flex-shrink:0;margin:0 -.5rem}.toolbar>*{margin:0 .5rem}.tracking{--tblr-tracking-height: 1.5rem;--tblr-tracking-gap-width: .125rem;--tblr-tracking-block-border-radius: var(--tblr-border-radius);display:flex;gap:var(--tblr-tracking-gap-width)}.tracking-squares{--tblr-tracking-block-border-radius: var(--tblr-border-radius-sm)}.tracking-squares .tracking-block{height:auto}.tracking-squares .tracking-block:before{content:"";display:block;padding-top:100%}.tracking-block{flex:1;border-radius:var(--tblr-tracking-block-border-radius);height:var(--tblr-tracking-height);min-width:.25rem;background:var(--tblr-border-color)}.timeline{--tblr-timeline-icon-size: 2.5rem;position:relative;list-style:none;padding:0}.timeline-event{position:relative}.timeline-event:not(:last-child){margin-bottom:var(--tblr-page-padding)}.timeline-event:not(:last-child):before{content:"";position:absolute;top:var(--tblr-timeline-icon-size);left:calc(var(--tblr-timeline-icon-size) / 2);bottom:calc(-1 * var(--tblr-page-padding));width:var(--tblr-border-width);background-color:var(--tblr-border-color);border-radius:var(--tblr-border-radius)}.timeline-event-icon{position:absolute;display:flex;align-items:center;justify-content:center;width:var(--tblr-timeline-icon-size, 2.5rem);height:var(--tblr-timeline-icon-size, 2.5rem);background:var(--tblr-bg-surface-secondary);color:var(--tblr-secondary);border-radius:var(--tblr-border-radius);z-index:5}.timeline-event-card{margin-left:calc(var(--tblr-timeline-icon-size, 2.5rem) + var(--tblr-page-padding))}.timeline-simple .timeline-event-icon{display:none}.timeline-simple .timeline-event-card{margin-left:0}.hr-text{display:flex;align-items:center;margin:2rem 0;font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary);height:1px}.hr-text:after,.hr-text:before{flex:1 1 auto;height:1px;background-color:var(--tblr-border-color)}.hr-text:before{content:"";margin-right:.5rem}.hr-text:after{content:"";margin-left:.5rem}.hr-text>*:first-child{padding-right:.5rem;padding-left:0;color:var(--tblr-secondary)}.hr-text.hr-text-left:before,.hr-text.hr-text-start:before{content:none}.hr-text.hr-text-left>*:first-child,.hr-text.hr-text-start>*:first-child{padding-right:.5rem;padding-left:.5rem}.hr-text.hr-text-right:before,.hr-text.hr-text-end:before{content:""}.hr-text.hr-text-right:after,.hr-text.hr-text-end:after{content:none}.hr-text.hr-text-right>*:first-child,.hr-text.hr-text-end>*:first-child{padding-right:0;padding-left:.5rem}.card>.hr-text{margin:0}.hr-text-spaceless{margin:-.5rem 0}.lead{color:var(--tblr-secondary);font-size:inherit}a{text-decoration-skip-ink:auto;color:color-mix(in srgb,transparent,var(--tblr-link-color) var(--tblr-link-opacity, 100%))}a:hover{color:color-mix(in srgb,transparent,var(--tblr-link-hover-color) var(--tblr-link-opacity, 100%))}h1 a,h2 a,h3 a,.field-group h2 a,h4 a,h5 a,h6 a,.h1 a,.h2 a,.h3 a,.h4 a,.h5 a,.h6 a,h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover,.h1 a:hover,.h2 a:hover,.h3 a:hover,.h4 a:hover,.h5 a:hover,.h6 a:hover{color:inherit}h1,.h1{font-size:var(--tblr-font-size-h1);line-height:var(--tblr-line-height-h1)}h2,.h2{font-size:var(--tblr-font-size-h2);line-height:var(--tblr-line-height-h2)}h3,.field-group h2,.field-group .h2,.h3{font-size:var(--tblr-font-size-h3);line-height:var(--tblr-line-height-h3)}h4,.h4{font-size:var(--tblr-font-size-h4);line-height:var(--tblr-line-height-h4)}h5,.h5{font-size:var(--tblr-font-size-h5);line-height:var(--tblr-line-height-h5)}h6,.h6{font-size:var(--tblr-font-size-h6);line-height:var(--tblr-line-height-h6)}.fs-base{font-size:var(--tblr-body-font-size)}strong,.strong,b{font-weight:var(--tblr-font-weight-bold)}blockquote{padding:1rem;border-left:2px var(--tblr-border-style) var(--tblr-border-color)}blockquote p{margin-bottom:1rem}blockquote cite{display:block;text-align:right}blockquote cite:before{content:"\2014 "}ul,ol{padding-left:1.5rem}hr,.hr{margin:2rem 0}dl dd:last-child{margin-bottom:0}pre{--tblr-scrollbar-color: var(--tblr-light);padding:1rem;background:var(--tblr-bg-surface-dark);color:var(--tblr-light);border-radius:var(--tblr-border-radius);line-height:1.4285714286}pre{scrollbar-color:color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent) transparent}pre::-webkit-scrollbar{width:1rem;height:1rem;transition:background .3s}@media(prefers-reduced-motion:reduce){pre::-webkit-scrollbar{transition:none}}pre::-webkit-scrollbar-thumb{border-radius:1rem;border:5px solid transparent;box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 20%,transparent)}pre::-webkit-scrollbar-track{background:transparent}pre:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 1rem color-mix(in srgb,var(--tblr-scrollbar-color, var(--tblr-body-color)) 40%,transparent)}pre::-webkit-scrollbar-corner{background:transparent}pre code{background:transparent;padding:0}code{background:var(--tblr-code-bg);padding:2px 4px;border-radius:var(--tblr-border-radius)}abbr{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}kbd,.kbd{border:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color);display:inline-block;box-sizing:border-box;max-width:100%;font-size:var(--tblr-font-size-h5);font-weight:var(--tblr-font-weight-medium);line-height:1;vertical-align:baseline;border-radius:var(--tblr-border-radius)}img{max-width:100%;height:auto}.list-unstyled{margin-left:0}::selection,.text-selected{background-color:color-mix(in srgb,var(--tblr-primary) 10%,transparent)}.text-selected{display:inline-block}[class^=link-].disabled,[class*=" link-"].disabled{color:var(--tblr-disabled-color)!important;pointer-events:none}a:hover:has(.icon){text-decoration:none}.link-hoverable{border-radius:var(--tblr-border-radius);transition:background-color .15s ease-in-out}.link-hoverable:hover{text-decoration:none;color:var(--tblr-primary);background:color-mix(in srgb,var(--tblr-secondary) 4%,transparent)}.subheader{font-size:.75rem;font-weight:var(--tblr-font-weight-medium);text-transform:uppercase;letter-spacing:.04em;line-height:1rem;color:var(--tblr-secondary)}.mention{display:inline-block;box-shadow:var(--tblr-shadow-border);border-radius:var(--tblr-border-radius-pill);line-height:1.3333333333em;font-size:.8571428571em;color:var(--tblr-body-color);background:var(--tblr-bg-surface-tertiary);padding:.1666666667em .6666666667em;font-weight:var(--tblr-font-weight-medium)}a.mention{cursor:pointer}a.mention:hover,a.mention.hover{background:var(--tblr-bg-surface-secondary);text-decoration:underline}.mention-avatar,.mention-app,.mention-color{width:1.1666666667em;height:1.1666666667em;border-radius:var(--tblr-border-radius-pill);margin:-.1666666667em .3333333333em 0 -.3333333333em;display:inline-flex;background:no-repeat center center/cover;box-shadow:var(--tblr-shadow-border);vertical-align:middle;text-align:center}.mention-app{box-shadow:none;background:none;border-radius:0}.mention-count{color:var(--tblr-secondary);margin-left:.6666666667em}.text-incorrect{background:color-mix(in srgb,var(--tblr-red) 4%,transparent);text-decoration:underline;text-decoration-thickness:1px;text-decoration-color:var(--tblr-red)}.text-correct{background:color-mix(in srgb,var(--tblr-green) 4%,transparent);text-decoration:underline;text-decoration-thickness:1px;text-decoration-color:var(--tblr-green)}.steps{--tblr-steps-padding: 2rem;--tblr-steps-item-size: 1.5rem;margin-left:1rem;padding-left:var(--tblr-steps-padding);counter-reset:step;border-left:1px solid var(--tblr-border-color);margin-bottom:2rem}.steps h3,.steps .field-group h2,.field-group .steps h2,.steps .field-group .h2,.field-group .steps .h2,.steps .h3{counter-increment:step}.steps h3:not(:first-child),.steps .field-group h2:not(:first-child),.field-group .steps h2:not(:first-child),.steps .field-group .h2:not(:first-child),.field-group .steps .h2:not(:first-child),.steps .h3:not(:first-child){margin-top:2.5rem!important}.steps h3:before,.steps .field-group h2:before,.field-group .steps h2:before,.steps .field-group .h2:before,.field-group .steps .h2:before,.steps .h3:before{content:counter(step);display:inline-block;position:absolute;margin-top:1px;margin-left:calc(-1 * var(--tblr-steps-padding) - var(--tblr-steps-item-size) / 2);width:var(--tblr-steps-item-size);height:var(--tblr-steps-item-size);text-align:center;color:var(--tblr-body-color);border:1px solid var(--tblr-border-color);background:var(--tblr-bg-surface);border-radius:var(--tblr-border-radius);line-height:calc(var(--tblr-steps-item-size) - 2px);font-size:var(--tblr-font-size-h4);font-weight:var(--tblr-font-weight-bold)}.steps>:last-child{margin-bottom:0}.callout{margin-bottom:1.5rem;border:1px solid var(--tblr-primary-200);border-radius:var(--tblr-border-radius);padding:.5rem 1rem;background:var(--tblr-primary-lt)}.callout>:last-child{margin-bottom:0}.chart{display:block;min-height:10rem}.chart text{font-family:inherit}.chart-sm{height:2.5rem}.chart-lg{height:15rem}.chart-square{height:5.75rem}.chart-sparkline{position:relative;width:4rem;height:2.5rem;line-height:1;min-height:0!important}.chart-sparkline-sm{height:1.5rem}.chart-sparkline-square{width:2.5rem}.chart-sparkline-wide{width:6rem}.chart-sparkline-label{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:.625rem}.chart-sparkline-label .icon{width:1rem;height:1rem;font-size:1rem}.offcanvas-header{border-bottom:var(--tblr-border-width) var(--tblr-border-style) var(--tblr-border-color)}.offcanvas-footer{padding:1.5rem}.offcanvas-title{font-size:1rem;font-weight:var(--tblr-font-weight-medium);line-height:1.5rem}.offcanvas-narrow{width:20rem}.chat-bubbles{display:flex;flex-direction:column;gap:1rem}.chat-bubble{background:var(--tblr-bg-surface-secondary);border-radius:var(--tblr-border-radius-lg);padding:1rem;position:relative}.chat-bubble-me{background-color:var(--tblr-primary-lt);box-shadow:none}.chat-bubble-title{margin-bottom:.25rem}.chat-bubble-author{font-weight:600}.chat-bubble-date{color:var(--tblr-secondary)}.chat-bubble-body>*:last-child{margin-bottom:0}.signature{--tblr-signature-padding: var(--tblr-spacer-1);--tblr-signature-border-radius: var(--tblr-border-radius);border:var(--tblr-border-width) solid var(--tblr-border-color);padding:var(--tblr-signature-padding);border-radius:var(--tblr-border-radius)}.signature-canvas{border:var(--tblr-border-width) dashed var(--tblr-border-color);border-radius:calc(var(--tblr-signature-border-radius) - var(--tblr-signature-padding));display:block;cursor:crosshair;width:100%}.clearfix:after{display:block;clear:both;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:var(--tblr-border-width);min-height:1em;background-color:currentcolor;opacity:.16}.stretched-link:after{position:absolute;inset:0;z-index:1;content:""}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.visually-hidden:not(caption),.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption){position:absolute!important}.visually-hidden *,.visually-hidden-focusable:not(:focus):not(:focus-within) *{overflow:hidden!important}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media(min-width:576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width:1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.ratio{position:relative;width:100%}.ratio:before{display:block;padding-top:var(--tblr-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--tblr-aspect-ratio: 100%}.ratio-2x1{--tblr-aspect-ratio: 50%}.ratio-1x2{--tblr-aspect-ratio: 200%}.ratio-3x1{--tblr-aspect-ratio: 33.3333333333%}.ratio-1x3{--tblr-aspect-ratio: 300%}.ratio-4x1{--tblr-aspect-ratio: 25%}.ratio-1x4{--tblr-aspect-ratio: 400%}.ratio-4x3{--tblr-aspect-ratio: 75%}.ratio-3x4{--tblr-aspect-ratio: 133.3333333333%}.ratio-16x9{--tblr-aspect-ratio: 56.25%}.ratio-9x16{--tblr-aspect-ratio: 177.7777777778%}.ratio-21x9{--tblr-aspect-ratio: 42.8571428571%}.ratio-9x21{--tblr-aspect-ratio: 233.3333333333%}.focus-ring:focus{outline:0;box-shadow:var(--tblr-focus-ring-x, 0) var(--tblr-focus-ring-y, 0) var(--tblr-focus-ring-blur, 0) var(--tblr-focus-ring-width) var(--tblr-focus-ring-color)}.bg-white-overlay{color:#fff;background-color:#f9fafb3d}.bg-dark-overlay{color:#fff;background-color:#1f29373d}.bg-cover{background-repeat:no-repeat;background-size:cover;background-position:center}.bg-primary{background-color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-primary-lt{color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-primary-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-primary{border-color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-primary{--tblr-gradient-from: var(--tblr-primary)}.bg-gradient-to-primary{--tblr-gradient-to: var(--tblr-primary)}.bg-gradient-via-primary{--tblr-gradient-via: var(--tblr-primary);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-primary{color:#f9fafb!important;background-color:RGBA(var(--tblr-primary-rgb),var(--tblr-bg-opacity, 1))!important}.link-primary{color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-primary:hover,.link-primary:focus{color:RGBA(0,106,100,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(0,106,100,var(--tblr-link-underline-opacity, 1))!important}.bg-secondary{background-color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-secondary-lt{color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-secondary-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-secondary{border-color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-secondary{--tblr-gradient-from: var(--tblr-secondary)}.bg-gradient-to-secondary{--tblr-gradient-to: var(--tblr-secondary)}.bg-gradient-via-secondary{--tblr-gradient-via: var(--tblr-secondary);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-secondary,.text-bg-gray{color:#f9fafb!important;background-color:RGBA(var(--tblr-secondary-rgb),var(--tblr-bg-opacity, 1))!important}.link-secondary{color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-secondary:hover,.link-secondary:focus{color:RGBA(86,91,102,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(86,91,102,var(--tblr-link-underline-opacity, 1))!important}.bg-success{background-color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-success-lt{color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-success-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-success{border-color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-success{--tblr-gradient-from: var(--tblr-success)}.bg-gradient-to-success{--tblr-gradient-to: var(--tblr-success)}.bg-gradient-via-success{--tblr-gradient-via: var(--tblr-success);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-success{color:#f9fafb!important;background-color:RGBA(var(--tblr-success-rgb),var(--tblr-bg-opacity, 1))!important}.link-success{color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-success:hover,.link-success:focus{color:RGBA(38,143,54,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(38,143,54,var(--tblr-link-underline-opacity, 1))!important}.bg-info{background-color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-info-lt{color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-info-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-info{border-color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-info{--tblr-gradient-from: var(--tblr-info)}.bg-gradient-to-info{--tblr-gradient-to: var(--tblr-info)}.bg-gradient-via-info{--tblr-gradient-via: var(--tblr-info);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-info{color:#f9fafb!important;background-color:RGBA(var(--tblr-info-rgb),var(--tblr-bg-opacity, 1))!important}.link-info{color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-info:hover,.link-info:focus{color:RGBA(53,122,180,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(53,122,180,var(--tblr-link-underline-opacity, 1))!important}.bg-warning{background-color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-warning-lt{color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-warning-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-warning{border-color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-warning{--tblr-gradient-from: var(--tblr-warning)}.bg-gradient-to-warning{--tblr-gradient-to: var(--tblr-warning)}.bg-gradient-via-warning{--tblr-gradient-via: var(--tblr-warning);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-warning{color:#f9fafb!important;background-color:RGBA(var(--tblr-warning-rgb),var(--tblr-bg-opacity, 1))!important}.link-warning{color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-warning:hover,.link-warning:focus{color:RGBA(196,127,0,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(196,127,0,var(--tblr-link-underline-opacity, 1))!important}.bg-danger{background-color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-danger-lt{color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-danger-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-danger{border-color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-danger{--tblr-gradient-from: var(--tblr-danger)}.bg-gradient-to-danger{--tblr-gradient-to: var(--tblr-danger)}.bg-gradient-via-danger{--tblr-gradient-via: var(--tblr-danger);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-danger{color:#f9fafb!important;background-color:RGBA(var(--tblr-danger-rgb),var(--tblr-bg-opacity, 1))!important}.link-danger{color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-danger:hover,.link-danger:focus{color:RGBA(171,46,46,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(171,46,46,var(--tblr-link-underline-opacity, 1))!important}.bg-light{background-color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-light-lt{color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-light-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-light{border-color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-light{--tblr-gradient-from: var(--tblr-light)}.bg-gradient-to-light{--tblr-gradient-to: var(--tblr-light)}.bg-gradient-via-light{--tblr-gradient-via: var(--tblr-light);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-light,.text-bg-white{color:#1f2937!important;background-color:RGBA(var(--tblr-light-rgb),var(--tblr-bg-opacity, 1))!important}.link-light{color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-light:hover,.link-light:focus{color:RGBA(250,251,252,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(250,251,252,var(--tblr-link-underline-opacity, 1))!important}.bg-dark{background-color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-dark-lt{color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-dark-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-dark{border-color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-dark{--tblr-gradient-from: var(--tblr-dark)}.bg-gradient-to-dark{--tblr-gradient-to: var(--tblr-dark)}.bg-gradient-via-dark{--tblr-gradient-via: var(--tblr-dark);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-dark,.text-bg-black{color:#f9fafb!important;background-color:RGBA(var(--tblr-dark-rgb),var(--tblr-bg-opacity, 1))!important}.link-dark{color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-dark:hover,.link-dark:focus{color:RGBA(25,33,44,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(25,33,44,var(--tblr-link-underline-opacity, 1))!important}.bg-muted{background-color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-muted-lt{color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-muted-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-muted{border-color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-muted{--tblr-gradient-from: var(--tblr-muted)}.bg-gradient-to-muted{--tblr-gradient-to: var(--tblr-muted)}.bg-gradient-via-muted{--tblr-gradient-via: var(--tblr-muted);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-muted{color:#f9fafb!important;background-color:RGBA(var(--tblr-muted-rgb),var(--tblr-bg-opacity, 1))!important}.link-muted{color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-muted:hover,.link-muted:focus{color:RGBA(86,91,102,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(86,91,102,var(--tblr-link-underline-opacity, 1))!important}.bg-blue{background-color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-blue-lt{color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-blue-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-blue{border-color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-blue{--tblr-gradient-from: var(--tblr-blue)}.bg-gradient-to-blue{--tblr-gradient-to: var(--tblr-blue)}.bg-gradient-via-blue{--tblr-gradient-via: var(--tblr-blue);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-blue{color:#f9fafb!important;background-color:RGBA(var(--tblr-blue-rgb),var(--tblr-bg-opacity, 1))!important}.link-blue{color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-blue:hover,.link-blue:focus{color:RGBA(5,89,167,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(5,89,167,var(--tblr-link-underline-opacity, 1))!important}.bg-azure{background-color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-azure-lt{color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-azure-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-azure{border-color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-azure{--tblr-gradient-from: var(--tblr-azure)}.bg-gradient-to-azure{--tblr-gradient-to: var(--tblr-azure)}.bg-gradient-via-azure{--tblr-gradient-via: var(--tblr-azure);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-azure{color:#f9fafb!important;background-color:RGBA(var(--tblr-azure-rgb),var(--tblr-bg-opacity, 1))!important}.link-azure{color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-azure:hover,.link-azure:focus{color:RGBA(53,122,180,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(53,122,180,var(--tblr-link-underline-opacity, 1))!important}.bg-indigo{background-color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-indigo-lt{color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-indigo-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-indigo{border-color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-indigo{--tblr-gradient-from: var(--tblr-indigo)}.bg-gradient-to-indigo{--tblr-gradient-to: var(--tblr-indigo)}.bg-gradient-via-indigo{--tblr-gradient-via: var(--tblr-indigo);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-indigo{color:#f9fafb!important;background-color:RGBA(var(--tblr-indigo-rgb),var(--tblr-bg-opacity, 1))!important}.link-indigo{color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-indigo:hover,.link-indigo:focus{color:RGBA(53,79,188,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(53,79,188,var(--tblr-link-underline-opacity, 1))!important}.bg-purple{background-color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-purple-lt{color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-purple-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-purple{border-color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-purple{--tblr-gradient-from: var(--tblr-purple)}.bg-gradient-to-purple{--tblr-gradient-to: var(--tblr-purple)}.bg-gradient-via-purple{--tblr-gradient-via: var(--tblr-purple);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-purple{color:#f9fafb!important;background-color:RGBA(var(--tblr-purple-rgb),var(--tblr-bg-opacity, 1))!important}.link-purple{color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-purple:hover,.link-purple:focus{color:RGBA(139,50,161,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(139,50,161,var(--tblr-link-underline-opacity, 1))!important}.bg-pink{background-color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-pink-lt{color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-pink-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-pink{border-color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-pink{--tblr-gradient-from: var(--tblr-pink)}.bg-gradient-to-pink{--tblr-gradient-to: var(--tblr-pink)}.bg-gradient-via-pink{--tblr-gradient-via: var(--tblr-pink);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-pink{color:#f9fafb!important;background-color:RGBA(var(--tblr-pink-rgb),var(--tblr-bg-opacity, 1))!important}.link-pink{color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-pink:hover,.link-pink:focus{color:RGBA(171,41,86,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(171,41,86,var(--tblr-link-underline-opacity, 1))!important}.bg-red{background-color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-red-lt{color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-red-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-red{border-color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-red{--tblr-gradient-from: var(--tblr-red)}.bg-gradient-to-red{--tblr-gradient-to: var(--tblr-red)}.bg-gradient-via-red{--tblr-gradient-via: var(--tblr-red);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-red{color:#f9fafb!important;background-color:RGBA(var(--tblr-red-rgb),var(--tblr-bg-opacity, 1))!important}.link-red{color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-red:hover,.link-red:focus{color:RGBA(171,46,46,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(171,46,46,var(--tblr-link-underline-opacity, 1))!important}.bg-orange{background-color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-orange-lt{color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-orange-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-orange{border-color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-orange{--tblr-gradient-from: var(--tblr-orange)}.bg-gradient-to-orange{--tblr-gradient-to: var(--tblr-orange)}.bg-gradient-via-orange{--tblr-gradient-via: var(--tblr-orange);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-orange{color:#f9fafb!important;background-color:RGBA(var(--tblr-orange-rgb),var(--tblr-bg-opacity, 1))!important}.link-orange{color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-orange:hover,.link-orange:focus{color:RGBA(198,82,6,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(198,82,6,var(--tblr-link-underline-opacity, 1))!important}.bg-yellow{background-color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-yellow-lt{color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-yellow-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-yellow{border-color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-yellow{--tblr-gradient-from: var(--tblr-yellow)}.bg-gradient-to-yellow{--tblr-gradient-to: var(--tblr-yellow)}.bg-gradient-via-yellow{--tblr-gradient-via: var(--tblr-yellow);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-yellow{color:#f9fafb!important;background-color:RGBA(var(--tblr-yellow-rgb),var(--tblr-bg-opacity, 1))!important}.link-yellow{color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-yellow:hover,.link-yellow:focus{color:RGBA(196,127,0,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(196,127,0,var(--tblr-link-underline-opacity, 1))!important}.bg-lime{background-color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-lime-lt{color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-lime-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-lime{border-color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-lime{--tblr-gradient-from: var(--tblr-lime)}.bg-gradient-to-lime{--tblr-gradient-to: var(--tblr-lime)}.bg-gradient-via-lime{--tblr-gradient-via: var(--tblr-lime);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-lime{color:#f9fafb!important;background-color:RGBA(var(--tblr-lime-rgb),var(--tblr-bg-opacity, 1))!important}.link-lime{color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-lime:hover,.link-lime:focus{color:RGBA(93,147,18,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(93,147,18,var(--tblr-link-underline-opacity, 1))!important}.bg-green{background-color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-green-lt{color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-green-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-green{border-color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-green{--tblr-gradient-from: var(--tblr-green)}.bg-gradient-to-green{--tblr-gradient-to: var(--tblr-green)}.bg-gradient-via-green{--tblr-gradient-via: var(--tblr-green);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-green{color:#f9fafb!important;background-color:RGBA(var(--tblr-green-rgb),var(--tblr-bg-opacity, 1))!important}.link-green{color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-green:hover,.link-green:focus{color:RGBA(38,143,54,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(38,143,54,var(--tblr-link-underline-opacity, 1))!important}.bg-teal{background-color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-teal-lt{color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-teal-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-teal{border-color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-teal{--tblr-gradient-from: var(--tblr-teal)}.bg-gradient-to-teal{--tblr-gradient-to: var(--tblr-teal)}.bg-gradient-via-teal{--tblr-gradient-via: var(--tblr-teal);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-teal{color:#f9fafb!important;background-color:RGBA(var(--tblr-teal-rgb),var(--tblr-bg-opacity, 1))!important}.link-teal{color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-teal:hover,.link-teal:focus{color:RGBA(10,133,96,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(10,133,96,var(--tblr-link-underline-opacity, 1))!important}.bg-cyan{background-color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-cyan-lt{color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-cyan-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-cyan{border-color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-cyan{--tblr-gradient-from: var(--tblr-cyan)}.bg-gradient-to-cyan{--tblr-gradient-to: var(--tblr-cyan)}.bg-gradient-via-cyan{--tblr-gradient-via: var(--tblr-cyan);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-cyan{color:#f9fafb!important;background-color:RGBA(var(--tblr-cyan-rgb),var(--tblr-bg-opacity, 1))!important}.link-cyan{color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-cyan:hover,.link-cyan:focus{color:RGBA(18,130,147,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(18,130,147,var(--tblr-link-underline-opacity, 1))!important}.bg-white{background-color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.bg-white-lt{color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-text-opacity, 1) * 100%),transparent)!important;background-color:color-mix(in srgb,var(--tblr-white-lt) calc(var(--tblr-bg-opacity, 1) * 100%),transparent)!important}.border-white{border-color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-border-opacity, 1) * 100%),transparent)!important}.bg-gradient-from-white{--tblr-gradient-from: var(--tblr-white)}.bg-gradient-to-white{--tblr-gradient-to: var(--tblr-white)}.bg-gradient-via-white{--tblr-gradient-via: var(--tblr-white);--tblr-gradient-stops: var(--tblr-gradient-from, transparent), var(--tblr-gradient-via, transparent), var(--tblr-gradient-to, transparent)}.text-bg-white{color:#1f2937!important;background-color:RGBA(var(--tblr-white-rgb),var(--tblr-bg-opacity, 1))!important}.link-white{color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-link-opacity, 1) * 100%),transparent)!important;text-decoration-color:color-mix(in srgb,var(--tblr-white) calc(var(--tblr-link-underline-opacity, 1) * 100%),transparent)!important}.link-white:hover,.link-white:focus{color:RGBA(255,255,255,var(--tblr-link-opacity, 1))!important;text-decoration-color:RGBA(255,255,255,var(--tblr-link-underline-opacity, 1))!important}.text-primary{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-primary) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-primary-fg{color:var(--tblr-primary-fg)!important}.text-secondary{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-secondary) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-secondary-fg{color:var(--tblr-secondary-fg)!important}.text-success{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-success) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-success-fg{color:var(--tblr-success-fg)!important}.text-info{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-info) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-info-fg{color:var(--tblr-info-fg)!important}.text-warning{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-warning) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-warning-fg{color:var(--tblr-warning-fg)!important}.text-danger{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-danger) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-danger-fg{color:var(--tblr-danger-fg)!important}.text-light{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-light) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-light-fg{color:var(--tblr-light-fg)!important}.text-dark{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-dark) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-dark-fg{color:var(--tblr-dark-fg)!important}.text-muted{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-muted) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-muted-fg{color:var(--tblr-muted-fg)!important}.text-blue{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-blue) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-blue-fg{color:var(--tblr-blue-fg)!important}.text-azure{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-azure) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-azure-fg{color:var(--tblr-azure-fg)!important}.text-indigo{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-indigo) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-indigo-fg{color:var(--tblr-indigo-fg)!important}.text-purple{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-purple) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-purple-fg{color:var(--tblr-purple-fg)!important}.text-pink{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-pink) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-pink-fg{color:var(--tblr-pink-fg)!important}.text-red{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-red) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-red-fg{color:var(--tblr-red-fg)!important}.text-orange{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-orange) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-orange-fg{color:var(--tblr-orange-fg)!important}.text-yellow{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-yellow) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-yellow-fg{color:var(--tblr-yellow-fg)!important}.text-lime{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-lime) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-lime-fg{color:var(--tblr-lime-fg)!important}.text-green{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-green) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-green-fg{color:var(--tblr-green-fg)!important}.text-teal{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-teal) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-teal-fg{color:var(--tblr-teal-fg)!important}.text-cyan{--tblr-text-opacity: 1;color:color-mix(in srgb,var(--tblr-cyan) calc(var(--tblr-text-opacity) * 100%),transparent)!important}.text-cyan-fg{color:var(--tblr-cyan-fg)!important}.bg-gray-50{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-50) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-50-fg{color:var(--tblr-gray-50-fg)!important}.bg-gray-100{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-100) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-100-fg{color:var(--tblr-gray-100-fg)!important}.bg-gray-200{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-200) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-200-fg{color:var(--tblr-gray-200-fg)!important}.bg-gray-300{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-300) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-300-fg{color:var(--tblr-gray-300-fg)!important}.bg-gray-400{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-400) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-400-fg{color:var(--tblr-gray-400-fg)!important}.bg-gray-500{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-500) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-500-fg{color:var(--tblr-gray-500-fg)!important}.bg-gray-600{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-600) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-600-fg{color:var(--tblr-gray-600-fg)!important}.bg-gray-700{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-700) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-700-fg{color:var(--tblr-gray-700-fg)!important}.bg-gray-800{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-800) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-800-fg{color:var(--tblr-gray-800-fg)!important}.bg-gray-900{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-900) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-900-fg{color:var(--tblr-gray-900-fg)!important}.bg-gray-950{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-gray-950) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-gray-950-fg{color:var(--tblr-gray-950-fg)!important}.bg-x{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-x) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-x-fg{color:var(--tblr-x-fg)!important}.bg-facebook{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-facebook) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-facebook-fg{color:var(--tblr-facebook-fg)!important}.bg-twitter{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-twitter) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-twitter-fg{color:var(--tblr-twitter-fg)!important}.bg-linkedin{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-linkedin) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-linkedin-fg{color:var(--tblr-linkedin-fg)!important}.bg-google{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-google) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-google-fg{color:var(--tblr-google-fg)!important}.bg-youtube{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-youtube) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-youtube-fg{color:var(--tblr-youtube-fg)!important}.bg-vimeo{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-vimeo) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-vimeo-fg{color:var(--tblr-vimeo-fg)!important}.bg-dribbble{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-dribbble) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-dribbble-fg{color:var(--tblr-dribbble-fg)!important}.bg-github{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-github) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-github-fg{color:var(--tblr-github-fg)!important}.bg-instagram{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-instagram) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-instagram-fg{color:var(--tblr-instagram-fg)!important}.bg-pinterest{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-pinterest) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-pinterest-fg{color:var(--tblr-pinterest-fg)!important}.bg-vk{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-vk) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-vk-fg{color:var(--tblr-vk-fg)!important}.bg-rss{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-rss) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-rss-fg{color:var(--tblr-rss-fg)!important}.bg-flickr{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-flickr) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-flickr-fg{color:var(--tblr-flickr-fg)!important}.bg-bitbucket{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-bitbucket) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-bitbucket-fg{color:var(--tblr-bitbucket-fg)!important}.bg-tabler{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-tabler) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.text-tabler-fg{color:var(--tblr-tabler-fg)!important}.bg-inverted{--tblr-bg-opacity: 1;background-color:color-mix(in srgb,var(--tblr-bg-surface-inverted) calc(var(--tblr-bg-opacity) * 100%),transparent)!important}.bg-surface{background-color:var(--tblr-bg-surface)!important}.bg-surface-secondary{background-color:var(--tblr-bg-surface-secondary)!important}.bg-surface-tertiary{background-color:var(--tblr-bg-surface-tertiary)!important}.bg-surface-backdrop{background-color:color-mix(in srgb,var(--tblr-gray-800) 24%,transparent)!important}.scrollable{overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch}.scrollable.hover{overflow-y:hidden}.scrollable.hover>*{margin-top:-1px}.scrollable.hover:hover,.scrollable.hover:focus,.scrollable.hover:active{overflow:visible;overflow-y:auto}.touch .scrollable{overflow-y:auto!important}.scroll-x,.scroll-y{overflow:hidden;-webkit-overflow-scrolling:touch}.scroll-y{overflow-y:auto}.scroll-x{overflow-x:auto}.no-scroll{overflow:hidden}.w-0{width:0!important}.h-0{height:0!important}.w-1{width:.25rem!important}.h-1{height:.25rem!important}.w-2{width:.5rem!important}.h-2{height:.5rem!important}.w-3{width:1rem!important}.h-3{height:1rem!important}.w-4{width:1.5rem!important}.h-4{height:1.5rem!important}.w-5{width:2rem!important}.h-5{height:2rem!important}.w-6{width:2.5rem!important}.h-6{height:2.5rem!important}.w-auto{width:auto!important}.h-auto{height:auto!important}.w-px{width:1px!important}.h-px{height:1px!important}.w-full{width:100%!important}.h-full{height:100%!important}.opacity-0{opacity:0!important}.opacity-5{opacity:.05!important}.opacity-10{opacity:.1!important}.opacity-15{opacity:.15!important}.opacity-20{opacity:.2!important}.opacity-25{opacity:.25!important}.opacity-30{opacity:.3!important}.opacity-35{opacity:calc(35 / 100)!important}.opacity-40{opacity:.4!important}.opacity-45{opacity:.45!important}.opacity-50{opacity:.5!important}.opacity-55{opacity:.55!important}.opacity-60{opacity:.6!important}.opacity-65{opacity:.65!important}.opacity-70{opacity:calc(70 / 100)!important}.opacity-75{opacity:.75!important}.opacity-80{opacity:.8!important}.opacity-85{opacity:.85!important}.opacity-90{opacity:.9!important}.opacity-95{opacity:calc(95 / 100)!important}.opacity-100{opacity:1!important}.hover-shadow-sm:hover{box-shadow:0 .125rem .25rem #00000013!important}.hover-shadow:hover{box-shadow:rgba(var(--tblr-body-color-rgb),.04) 0 2px 4px!important}.hover-shadow-lg:hover{box-shadow:0 1rem 3rem #0000002d!important}.hover-shadow-none:hover{box-shadow:none!important}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.hover-rotate-start,.hover-rotate-end,.hover-scale,.hover-elevate-down,.hover-elevate-up{transition:transform .3s ease}.hover-rotate-start:hover,.hover-rotate-end:hover,.hover-scale:hover,.hover-elevate-down:hover,.hover-elevate-up:hover{will-change:transform}.hover-elevate-up:hover{transform:translateY(-4px)}.hover-elevate-down:hover{transform:translateY(4px)}.hover-scale:hover{transform:scale(1.1)}.hover-rotate-end:hover{transform:rotate(4deg)}.hover-rotate-start:hover{transform:rotate(-4deg)}.ts-control{border:1px solid var(--tblr-border-color);padding:.5625rem 1rem;width:100%;overflow:hidden;position:relative;z-index:1;box-sizing:border-box;box-shadow:none;border-radius:var(--tblr-border-radius);display:flex;flex-wrap:wrap}.ts-wrapper.multi.has-items .ts-control{padding:calc(.5625rem - 1px) 1rem calc(.5625rem - 4px)}.full .ts-control{background-color:var(--tblr-bg-forms)}.disabled .ts-control,.disabled .ts-control *{cursor:default!important}.focus .ts-control{box-shadow:none}.ts-control>*{vertical-align:baseline;display:inline-block}.ts-wrapper.multi .ts-control>div{cursor:pointer;margin:0 3px 3px 0;padding:1px 5px;background:#efefef;color:#1f2937;border:0px solid #e5e7eb;overflow:auto}.ts-wrapper.multi .ts-control>div.active{background:#00857d;color:#fff;border:0px solid rgba(0,0,0,0)}.ts-wrapper.multi.disabled .ts-control>div,.ts-wrapper.multi.disabled .ts-control>div.active{color:#787878;background:#fff;border:0px solid white}.ts-control>input{flex:1 1 auto;min-width:7rem;display:inline-block!important;padding:0!important;min-height:0!important;max-height:none!important;max-width:100%!important;margin:0!important;text-indent:0!important;border:0 none!important;background:none!important;line-height:inherit!important;user-select:auto!important;box-shadow:none!important}.ts-control>input::-ms-clear{display:none}.ts-control>input:focus{outline:none!important}.has-items .ts-control>input{margin:0 4px!important}.ts-control.rtl{text-align:right}.ts-control.rtl.single .ts-control:after{left:calc(1rem + 5px);right:auto}.ts-control.rtl .ts-control>input{margin:0 4px 0 -2px!important}.disabled .ts-control{opacity:1;background-color:var(--tblr-bg-surface-secondary)}.input-hidden .ts-control>input{opacity:0;position:absolute;left:-10000px}.ts-dropdown{position:absolute;top:100%;left:0;width:100%;z-index:10;border:1px solid #d0d0d0;background:var(--tblr-bg-surface);margin:.25rem 0 0;border-top:0 none;box-sizing:border-box;box-shadow:0 1px 3px #0000001a;border-radius:0 0 var(--tblr-border-radius) var(--tblr-border-radius)}.ts-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.ts-dropdown [data-selectable] .highlight{background:#ffed2866;border-radius:1px}.ts-dropdown .option,.ts-dropdown .optgroup-header,.ts-dropdown .no-results,.ts-dropdown .create{padding:3px 1rem}.ts-dropdown .option,.ts-dropdown [data-disabled],.ts-dropdown [data-disabled] [data-selectable].option{cursor:inherit;opacity:.5}.ts-dropdown [data-selectable].option{opacity:1;cursor:pointer}.ts-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.ts-dropdown .optgroup-header{color:#4b5563;background:var(--tblr-bg-surface);cursor:default}.ts-dropdown .active{background-color:rgba(var(--tblr-secondary-rgb),.08);color:inherit}.ts-dropdown .active.create{color:inherit}.ts-dropdown .create{color:#1f293780}.ts-dropdown .spinner{display:inline-block;width:30px;height:30px;margin:3px 1rem}.ts-dropdown .spinner:after{content:" ";display:block;width:24px;height:24px;margin:3px;border-radius:50%;border:5px solid #d0d0d0;border-color:#d0d0d0 transparent #d0d0d0 transparent;animation:lds-dual-ring 1.2s linear infinite}@keyframes lds-dual-ring{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ts-dropdown-content{overflow:hidden auto;max-height:200px;scroll-behavior:smooth}.ts-wrapper.plugin-drag_drop .ts-dragging{color:transparent!important}.ts-wrapper.plugin-drag_drop .ts-dragging>*{visibility:hidden!important}.plugin-checkbox_options:not(.rtl) .option input{margin-right:.5rem}.plugin-checkbox_options.rtl .option input{margin-left:.5rem}.plugin-clear_button{--ts-pr-clear-button: 1em}.plugin-clear_button .clear-button{opacity:0;position:absolute;top:50%;transform:translateY(-50%);right:calc(1rem - 5px);margin-right:0!important;background:transparent!important;transition:opacity .5s;cursor:pointer}.plugin-clear_button.form-select .clear-button,.plugin-clear_button.single .clear-button{right:max(var(--ts-pr-caret),1rem)}.plugin-clear_button.focus.has-items .clear-button,.plugin-clear_button:not(.disabled):hover.has-items .clear-button{opacity:1}.ts-wrapper .dropdown-header{position:relative;padding:6px 1rem;border-bottom:1px solid #d0d0d0;background:color-mix(var(--tblr-bg-surface),#d0d0d0,85%);border-radius:var(--tblr-border-radius) var(--tblr-border-radius) 0 0}.ts-wrapper .dropdown-header-close{position:absolute;right:1rem;top:50%;color:#1f2937;opacity:.4;margin-top:-12px;line-height:20px;font-size:20px!important}.ts-wrapper .dropdown-header-close:hover{color:#000}.plugin-dropdown_input.focus.dropdown-active .ts-control{box-shadow:none;border:1px solid var(--tblr-border-color);box-shadow:var(--tblr-shadow-input)}.plugin-dropdown_input .dropdown-input{border:1px solid #d0d0d0;border-width:0 0 1px;display:block;padding:.5625rem 1rem;box-shadow:none;width:100%;background:transparent}.plugin-dropdown_input.focus .ts-dropdown .dropdown-input{border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.plugin-dropdown_input .items-placeholder{border:0 none!important;box-shadow:none!important;width:100%}.plugin-dropdown_input.has-items .items-placeholder,.plugin-dropdown_input.dropdown-active .items-placeholder{display:none!important}.ts-wrapper.plugin-input_autogrow.has-items .ts-control>input{min-width:0}.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control>input{flex:none;min-width:4px}.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control>input::placeholder{color:transparent}.ts-dropdown.plugin-optgroup_columns .ts-dropdown-content{display:flex}.ts-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;flex-grow:1;flex-basis:0;min-width:0}.ts-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.ts-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.ts-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.ts-wrapper.plugin-remove_button .item{display:inline-flex;align-items:center}.ts-wrapper.plugin-remove_button .item .remove{color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:0 5px;border-radius:0 2px 2px 0;box-sizing:border-box}.ts-wrapper.plugin-remove_button .item .remove:hover{background:#0000000d}.ts-wrapper.plugin-remove_button.disabled .item .remove:hover{background:none}.ts-wrapper.plugin-remove_button .remove-single{position:absolute;right:0;top:0;font-size:23px}.ts-wrapper.plugin-remove_button:not(.rtl) .item{padding-right:0!important}.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove{border-left:1px solid #e5e7eb;margin-left:5px}.ts-wrapper.plugin-remove_button:not(.rtl) .item.active .remove{border-left-color:#0000}.ts-wrapper.plugin-remove_button:not(.rtl).disabled .item .remove{border-left-color:#fff}.ts-wrapper.plugin-remove_button.rtl .item{padding-left:0!important}.ts-wrapper.plugin-remove_button.rtl .item .remove{border-right:1px solid #e5e7eb;margin-right:5px}.ts-wrapper.plugin-remove_button.rtl .item.active .remove{border-right-color:#0000}.ts-wrapper.plugin-remove_button.rtl.disabled .item .remove{border-right-color:#fff}:root{--ts-pr-clear-button: 0px;--ts-pr-caret: 0px;--ts-pr-min: .75rem}.ts-wrapper.single .ts-control,.ts-wrapper.single .ts-control input{cursor:pointer}.ts-control:not(.rtl){padding-right:max(var(--ts-pr-min),var(--ts-pr-clear-button) + var(--ts-pr-caret))!important}.ts-control.rtl{padding-left:max(var(--ts-pr-min),var(--ts-pr-clear-button) + var(--ts-pr-caret))!important}.ts-wrapper{position:relative}.ts-dropdown,.ts-control,.ts-control input{color:#1f2937;font-family:inherit;font-size:inherit;line-height:1.25rem}.ts-control,.ts-wrapper.single.input-active .ts-control{background:var(--tblr-bg-forms);cursor:text}.ts-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;white-space:nowrap!important}.ts-dropdown,.ts-dropdown.form-control,.ts-dropdown.form-select{height:auto;padding:0;z-index:1000;background:var(--tblr-bg-surface);border:1px solid var(--tblr-border-color-translucent);border-radius:6px;box-shadow:0 6px 12px #0000002d}.ts-dropdown .optgroup-header{font-size:.765625rem;line-height:1.4285714286}.ts-dropdown .optgroup:first-child:before{display:none}.ts-dropdown .optgroup:before{content:" ";display:block;height:0;margin:var(--tblr-spacer-2) 0;overflow:hidden;border-top:1px solid var(--tblr-border-color-translucent);margin-left:-1rem;margin-right:-1rem}.ts-dropdown .create{padding-left:1rem}.ts-dropdown-content{padding:5px 0}.ts-control{box-shadow:var(--tblr-shadow-input);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion:reduce){.ts-control{transition:none}}.ts-control{display:flex;align-items:center}.focus .ts-control{border-color:#80c2be;outline:0;box-shadow:var(--tblr-shadow-input),0 0 0 .25rem rgba(var(--tblr-primary-rgb),.25)}.ts-control .item{display:flex;align-items:center}.ts-control input::placeholder{color:var(--bs-secondary-color, #a7aeb8);opacity:1}.ts-wrapper.is-invalid,select.tomselected.is-invalid+div.ts-wrapper,.was-validated .invalid,.was-validated :invalid+.ts-wrapper{border-color:var(--tblr-form-invalid-color)}.ts-wrapper.is-invalid:not(.single),select.tomselected.is-invalid+div.ts-wrapper:not(.single),.was-validated .invalid:not(.single),.was-validated :invalid+.ts-wrapper:not(.single){background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-invalid.single,select.tomselected.is-invalid+div.ts-wrapper.single,.was-validated .invalid.single,.was-validated :invalid+.ts-wrapper.single{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23d63939' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cline x1='18' y1='6' x2='6' y2='18'%3e%3c/line%3e%3cline x1='6' y1='6' x2='18' y2='18'%3e%3c/line%3e%3c/svg%3e");background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-invalid.focus .ts-control,select.tomselected.is-invalid+div.ts-wrapper.focus .ts-control,.was-validated .invalid.focus .ts-control,.was-validated :invalid+.ts-wrapper.focus .ts-control{border-color:var(--tblr-form-invalid-color);box-shadow:0 0 0 .25rem rgba(var(--tblr-form-invalid-color),.25)}.ts-wrapper.is-valid,.was-validated .valid,.was-validated :valid+.ts-wrapper{border-color:var(--tblr-form-valid-color)}.ts-wrapper.is-valid:not(.single),.was-validated .valid:not(.single),.was-validated :valid+.ts-wrapper:not(.single){background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");background-position:right 1.53125rem center;background-size:1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-valid.single,.was-validated .valid.single,.was-validated :valid+.ts-wrapper.single{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%232fb344' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='20 6 9 17 4 12'%3e%3c/polyline%3e%3c/svg%3e");background-position:right 1rem center,center right 3rem;background-size:16px 12px,1.8125rem 1.8125rem;background-repeat:no-repeat}.ts-wrapper.is-valid.focus .ts-control,.was-validated .valid.focus .ts-control,.was-validated :valid+.ts-wrapper.focus .ts-control{border-color:var(--tblr-form-valid-color);box-shadow:0 0 0 .25rem rgba(var(--tblr-form-valid-color),.25)}.ts-wrapper{min-height:calc(1.25rem + 1.125rem + calc(var(--tblr-border-width) * 2));display:flex}.input-group-sm>.ts-wrapper,.ts-wrapper.form-select-sm,.ts-wrapper.form-control-sm{min-height:calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2))}.input-group-sm>.ts-wrapper .ts-control,.ts-wrapper.form-select-sm .ts-control,.ts-wrapper.form-control-sm .ts-control{border-radius:var(--tblr-border-radius-sm);font-size:.75rem}.input-group-sm>.ts-wrapper.has-items .ts-control,.ts-wrapper.form-select-sm.has-items .ts-control,.ts-wrapper.form-control-sm.has-items .ts-control{font-size:.75rem}.input-group-sm>.ts-wrapper.multi.has-items .ts-control,.ts-wrapper.form-select-sm.multi.has-items .ts-control,.ts-wrapper.form-control-sm.multi.has-items .ts-control{padding-top:calc((calc(1.25rem + .625rem + calc(var(--tblr-border-width) * 2)) - 1.25rem * .75rem - calc((var(--tblr-border-width) + 1px) * 2)) / 2)!important}.ts-wrapper.multi.has-items .ts-control{padding-left:calc(1rem - 5px);--ts-pr-min: calc(1rem - 5px) }.ts-wrapper.multi .ts-control>div{border-radius:calc(var(--tblr-border-radius) - 1px)}.input-group-lg>.ts-wrapper,.ts-wrapper.form-control-lg,.ts-wrapper.form-select-lg{min-height:calc(1.25rem + 1.375rem + calc(var(--tblr-border-width) * 2))}.input-group-lg>.ts-wrapper .ts-control,.ts-wrapper.form-control-lg .ts-control,.ts-wrapper.form-select-lg .ts-control{border-radius:var(--tblr-border-radius-lg);font-size:1rem}.ts-wrapper:not(.form-control,.form-select){padding:0;border:none;height:auto;box-shadow:none;background:none}.ts-wrapper:not(.form-control,.form-select).single .ts-control{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right 1rem center;background-size:16px 12px}.ts-wrapper.form-select,.ts-wrapper.single{--ts-pr-caret: 3rem}.ts-wrapper.form-control,.ts-wrapper.form-select{padding:0!important;height:auto;box-shadow:none;display:flex}.ts-wrapper.form-control .ts-control,.ts-wrapper.form-control.single.input-active .ts-control,.ts-wrapper.form-select .ts-control,.ts-wrapper.form-select.single.input-active .ts-control{border:none!important}.ts-wrapper.form-control:not(.disabled) .ts-control,.ts-wrapper.form-control:not(.disabled).single.input-active .ts-control,.ts-wrapper.form-select:not(.disabled) .ts-control,.ts-wrapper.form-select:not(.disabled).single.input-active .ts-control{background:transparent!important}.input-group>.ts-wrapper{flex-grow:1;width:1%}.input-group>.ts-wrapper:not(:nth-child(2))>.ts-control{border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.ts-wrapper:not(:last-child)>.ts-control{border-top-right-radius:0;border-bottom-right-radius:0}.form-select .ts-dropdown,.form-select .ts-control,.form-select .ts-control input{color:var(--tblr-body-color)}:root{--ts-pr-clear-button: 0rem;--ts-pr-caret: 0rem}.ts-input{color:inherit}.focus .ts-control{border-radius:var(--tblr-border-radius)}.ts-control{color:inherit}.ts-control .dropdown-menu{width:100%;height:auto}.ts-wrapper .form-control,.ts-wrapper .form-select,.ts-wrapper.form-control,.ts-wrapper.form-select{box-shadow:var(--tblr-shadow-input)}.ts-wrapper.is-invalid .ts-control,select.tomselected.is-invalid+div.ts-wrapper .ts-control,.ts-wrapper.is-valid .ts-control{--ts-pr-clear-button: 1.5rem}.ts-dropdown{background:var(--tblr-bg-surface);color:var(--tblr-body-color);box-shadow:var(--tblr-shadow-dropdown);z-index:1000}.ts-dropdown .option{padding:.5rem .75rem}.ts-control,.ts-control input{color:var(--tblr-body-color)}.ts-control input::placeholder{color:var(--tblr-tertiary)}.ts-wrapper.multi .ts-control>div,.ts-wrapper.multi.disabled .ts-control>div{background:var(--tblr-bg-surface-secondary);border:1px solid var(--tblr-border-color);color:var(--tblr-body-color)}.ts-wrapper.disabled .ts-control{opacity:1}.ts-wrapper.disabled .ts-control>div.item{color:var(--tblr-gray-500)}html{scroll-behavior:auto!important}mark,.mark{padding-left:0;padding-right:0}.table-responsive .dropdown,.table-responsive .btn-group,.table-responsive .btn-group-vertical{position:static}.progress{min-width:80px}hr.dropdown-divider,.dropdown-divider.hr{margin-bottom:.25rem;margin-top:.25rem}.dropdown-item{font-weight:400}*{font-feature-settings:"liga" 0;font-variant-ligatures:none}@media(min-width:992px){:root,:host{margin-left:0;scrollbar-gutter:stable}}pre{background-color:transparent;color:inherit}.alert{background:var(--tblr-bg-surface)}.badge{user-select:text}.btn{display:inline-block}.btn:focus{border:1px solid var(--tblr-primary-fg);outline:2px solid var(--tblr-primary)!important}.btn-sm,.btn-group-sm>.btn{border-radius:6px}.dropdown-item{display:inline-block}.footer .text-primary{color:#001423!important}.nav-tabs .nav-link{display:inline-block}.page,.page-tabs .nav-tabs .nav-link.active{background-color:var(--tblr-bg-surface-tertiary)!important}.navbar{--tblr-navbar-active-bg: rgba(0, 0, 0, .06)}[data-bs-theme=dark],body[data-bs-theme=dark] [data-bs-theme=light]{--tblr-alert-color: darken(var(--tblr-warning),10%);--tblr-link-color: #00F2D4;--tblr-link-color-rgb: 0,242,212;--tblr-link-hover-color-rgb: 0,242,212;--tblr-secondary: #9ca3af;--tblr-primary: #00F2D4;--tblr-primary-fg: #001423;--tblr-primary-rgb: 0,242,212;--tblr-btn-active-color: #001423}html[data-bs-theme=dark] ::selection,body[data-bs-theme=dark] html[data-bs-theme=light] ::selection{background-color:rgba(var(--tblr-primary-rgb),.48)}html[data-bs-theme=dark] .btn-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .btn-primary,html[data-bs-theme=dark] .bg-primary .card-title,body[data-bs-theme=dark] html[data-bs-theme=light] .bg-primary .card-title,html[data-bs-theme=dark] .bg-primary a,body[data-bs-theme=dark] html[data-bs-theme=light] .bg-primary a,html[data-bs-theme=dark] .bg-primary i,body[data-bs-theme=dark] html[data-bs-theme=light] .bg-primary i,html[data-bs-theme=dark] .text-bg-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .text-bg-primary{color:#001423!important}html[data-bs-theme=dark] .card,body[data-bs-theme=dark] html[data-bs-theme=light] .card{background:#001423!important}html[data-bs-theme=dark],body[data-bs-theme=dark] html[data-bs-theme=light],html[data-bs-theme=dark] .navbar,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar,html[data-bs-theme=dark] .page-header,body[data-bs-theme=dark] html[data-bs-theme=light] .page-header{background-color:#001423}html[data-bs-theme=dark] .page,body[data-bs-theme=dark] html[data-bs-theme=light] .page,html[data-bs-theme=dark] .page-tabs .nav-tabs .nav-link.active,body[data-bs-theme=dark] html[data-bs-theme=light] .page-tabs .nav-tabs .nav-link.active{background-color:#081b2a!important}html[data-bs-theme=dark] .page-link.active,body[data-bs-theme=dark] html[data-bs-theme=light] .page-link.active,html[data-bs-theme=dark] .active>.page-link,body[data-bs-theme=dark] html[data-bs-theme=light] .active>.page-link{color:#001423}html[data-bs-theme=dark] .text-bg-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .text-bg-primary{color:#001423!important}html[data-bs-theme=dark] .text-muted,body[data-bs-theme=dark] html[data-bs-theme=light] .text-muted{color:var(--tblr-secondary-color)!important}html[data-bs-theme=dark] .text-secondary,body[data-bs-theme=dark] html[data-bs-theme=light] .text-secondary{color:#9ca3af!important}html[data-bs-theme=dark] .footer .text-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .footer .text-primary{color:#fff!important}html[data-bs-theme=dark] .toast,body[data-bs-theme=dark] html[data-bs-theme=light] .toast{color:var(--tblr-body-color)}html[data-bs-theme=dark] .table-primary,body[data-bs-theme=dark] html[data-bs-theme=light] .table-primary{--tblr-table-bg: rgba(var(--tblr-secondary-rgb), .48);--tblr-table-hover-bg: inherit;--tblr-table-hover-color: inherit}pre code{padding:unset}.dropdown-toggle:after{font-family:Material Design Icons;content:"\f0140";padding-right:9px;border-bottom:none;border-left:none;transform:none;vertical-align:.05em;height:auto}.accordion-button-toggle{align-items:center;justify-content:center;flex:0 0 auto}.accordion-button-toggle>i{display:block;line-height:1}:root:not(.dummy)[data-bs-theme=light] .hide-theme-light,:root:not(.dummy)[data-bs-theme=dark] .hide-theme-dark,body[data-bs-theme=dark] [data-bs-theme=light]:root:not(.dummy) .hide-theme-dark{display:none!important}:root:not(.dummy)[data-bs-theme=dark] .hide-theme-light,body[data-bs-theme=dark] [data-bs-theme=light]:root:not(.dummy) .hide-theme-light,:root:not(.dummy)[data-bs-theme=light] .hide-theme-dark{display:inline-flex!important}.ts-wrapper.multi .ts-control{padding:7px 7px 3px}.ts-wrapper.multi .ts-control div{margin:0 4px 4px 0}.badge a{color:inherit;text-decoration:none}.page-body .card{margin-bottom:1rem}.page-body .card .card-header,.page-body .card .card-body,.page-body .card .card-footer{padding:.75rem}.page-body .card .card-header{background:var(--tblr-bg-surface-tertiary)}.page-body .card h2.card-header,.page-body .card .card-header.h2{font-size:var(--tblr-font-size-h5);line-height:var(--tblr-line-height-h5);margin-bottom:0}.page-body .card .list-group-item{padding:.5rem .75rem}.page-body .card .table,.page-body .card .markdown>table{margin-bottom:0}form.object-edit{margin:auto;max-width:800px}.col-form-label.required{font-weight:700}.col-form-label.required:after{position:absolute;display:inline-block;margin-left:0;font-family:Material Design Icons;font-size:8px;content:"\f06c4"}.has-errors input,.has-errors select,.has-errors textarea{border:1px solid #d63939}select[multiple] optgroup{top:0;background-color:var(--bs-body-bg);font-style:normal;font-weight:700}select[multiple] option{padding-left:.5rem}.modifier-select{min-width:10rem;max-width:15rem;width:auto;white-space:nowrap}.page{background-color:var(--tblr-bg-surface-secondary)}.page-header{background-color:var(--tblr-bg-surface);min-height:0}.navbar-vertical.navbar-expand-lg .navbar-collapse .nav-link-icon,.navbar-vertical.navbar-expand-lg .navbar-collapse .nav-link-title{color:#001423}.navbar-vertical.navbar-expand-lg .navbar-collapse .text-secondary{color:#00857d!important}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item a{color:#001423}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item .btn-group{visibility:hidden}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:hover,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active{background-color:var(--tblr-navbar-active-bg)}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:hover a,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active a{text-decoration:none}.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item:hover .btn-group,.navbar-vertical.navbar-expand-lg .navbar-collapse .dropdown-menu .dropdown-item.active .btn-group{visibility:visible}.navbar-vertical.navbar-expand-lg .navbar-nav{z-index:1}@media(max-width:991.98px){.navbar-vertical.navbar-expand-lg .navbar-brand{padding:.2rem 0}}.navbar-vertical.navbar-expand-lg .navbar-brand a:hover{text-decoration:none}.navbar-vertical.navbar-expand-lg img.motif{bottom:0;display:none;left:0;mask-image:linear-gradient(180deg,#0000,#0000004d);opacity:.5;position:fixed;user-drag:none;user-select:none;-moz-user-select:none;-webkit-user-drag:none;-webkit-user-select:none;-ms-user-select:none;width:18rem}@media(min-width:992px){.navbar-vertical.navbar-expand-lg img.motif{display:block}}html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg{background:linear-gradient(180deg,#00857d00,#00857d1a),#fff}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg{background:linear-gradient(180deg,#00f2d400,#00f2d41a),#001423}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .nav-item.dropdown.active:after,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .nav-item.dropdown.active:after{border-color:#00f2d4!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .nav-link-title,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .nav-link-title,html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .nav-link-icon,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .nav-link-icon,html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .dropdown-item a,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .dropdown-item a{color:#fff!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .dropdown-item.active,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .dropdown-item.active,html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .dropdown-item:hover,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .dropdown-item:hover{background-color:#ffffff0f!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg .text-secondary,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg .text-secondary{color:#00f2d4!important}html[data-bs-theme=dark] .navbar-vertical.navbar-expand-lg img.motif,body[data-bs-theme=dark] html[data-bs-theme=light] .navbar-vertical.navbar-expand-lg img.motif{opacity:.25}.progress{height:20px}.progress .progress-label{display:flex;flex-direction:column;justify-content:center;padding-left:.25rem}.table thead th,.markdown>table thead th{font-size:.625rem}table.object-list tbody>tr:last-child>td{border-bottom-width:0}table.object-list th.asc>a:after{content:"\f0140";font-family:Material Design Icons}table.object-list th.desc>a:after{content:"\f0143";font-family:Material Design Icons}table.attr-table th{font-weight:400;width:min-content}table.attr-table th,table.attr-table td{border-bottom-style:dashed}table.attr-table tr:last-child{border-bottom-style:hidden}table.attr-table td{overflow-wrap:anywhere}td pre{margin-bottom:0}table th.orderable a{color:var(--tblr-body-color)}html[data-bs-theme=dark] .table thead th,body[data-bs-theme=dark] html[data-bs-theme=light] .table thead th,body[data-bs-theme=dark] html[data-bs-theme=light] .markdown>table thead th,html[data-bs-theme=dark] .markdown>table thead th{background:#001423!important}.page-tabs{border-bottom:1px solid var(--tblr-border-color-translucent)}.page-tabs .nav-tabs{position:relative;border:none}.page-tabs .nav-tabs .nav-link.active,.page-tabs .nav-tabs .nav-link:active,.page-tabs .nav-tabs .nav-link:hover{border-color:var(--tblr-border-color-translucent);border-bottom-color:transparent}.page-tabs .nav-tabs .nav-link.active{color:inherit;background:var(--tblr-bg-surface-secondary);border-bottom-color:transparent}pre.change-data{border-radius:0;padding:0;margin-inline:-.75rem}pre.change-data>span{display:block;padding-inline:.5rem;max-width:100%;min-width:fit-content;border-left:.25rem solid transparent}pre.change-data>span.added{background-color:var(--tblr-green-200);border-left-color:var(--tblr-green-darken)}pre.change-data>span.removed{background-color:var(--tblr-red-200);border-left-color:var(--tblr-red-darken)}pre.change-diff{border:var(--tblr-border-width) solid transparent}pre.change-diff.change-added{background-color:var(--tblr-green-lt);border-color:var(--tblr-green)}pre.change-diff.change-removed{background-color:var(--tblr-red-lt);border-color:var(--tblr-red)}pre.block{padding:1rem;border:var(--tblr-border-width) solid #e5e7eb;border-radius:6px}.grid-stack .card-header.bg-default{background:var(--tblr-bg-surface-secondary)!important}.grid-stack .card-header a{color:inherit!important}tr[data-cable-status=connected]{--tblr-table-bg-state: rgba(47, 179, 68, .15)}tr[data-cable-status=planned]{--tblr-table-bg-state: rgba(6, 111, 209, .15)}tr[data-cable-status=decommissioning]{--tblr-table-bg-state: rgba(245, 159, 0, .15)}tr[data-mark-connected=true]{--tblr-table-bg-state: rgba(47, 179, 68, .15)}tr[data-virtual=true]{--tblr-table-bg-state: rgba(0, 133, 125, .15)}tr[data-enabled=disabled]{--tblr-table-bg-state: rgba(156, 163, 175, .15)}tr[data-cable-status]>*,tr[data-mark-connected=true]>*,tr[data-virtual=true]>*,tr[data-enabled=disabled]>*{background-color:var(--tblr-table-bg-state);border-bottom-color:var(--tblr-gray-300);box-shadow:none}tr[data-cable-status=connected] button.mark-installed{display:none}tr:not([data-cable-status=connected]) button.mark-planned{display:none}.rendered-markdown table{width:100%}.rendered-markdown table th{border-bottom:2px solid #dddddd;padding:8px}.rendered-markdown table td{border-top:1px solid #dddddd;padding:8px}.rendered-markdown table th[align=left]{text-align:left}.rendered-markdown table th[align=center]{text-align:center}.rendered-markdown table th[align=right]{text-align:right}.rendered-markdown p:last-child{margin-bottom:0}td>.rendered-markdown{max-height:200px;overflow-y:scroll}.markdown-widget .preview{border:1px solid #e5e7eb;border-radius:6px;min-height:200px}span.color-label{display:inline-block;width:5rem;height:1rem;padding:.25em .5em;border:1px solid #303030;border-radius:6px}.record-depth{display:inline;user-select:none;opacity:33%}.record-depth span:only-of-type,.record-depth span:last-of-type{margin-right:.25rem}.hide-last-child :last-child{visibility:hidden;opacity:0}.netbox-edition{letter-spacing:.15rem}.logo{height:80px}.sso-icon{height:24px}img.plugin-icon{max-width:1.4285em;height:auto}.thumbnail{max-width:200px}.thumbnail img{border:1px solid #606060}.image-preview-popover{--bs-popover-max-width: clamp(240px, 25vw, 640px)}.image-preview-popover .popover-header{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.image-preview-popover .popover-body{display:flex;justify-content:center;align-items:center}.image-preview-popover img{display:block;max-width:100%;max-height:clamp(160px,33vh,640px);height:auto}html[data-bs-theme=dark] img.plugin-icon,body[data-bs-theme=dark] html[data-bs-theme=light] img.plugin-icon{filter:grayscale(100%) invert(100%) brightness(80%)}.sticky-actions{z-index:4}.sticky-actions[data-sticky-when=always],.sticky-actions.is-sticky-active{position:sticky;bottom:.25rem}.sticky-actions[data-sticky-position=left],.sticky-actions[data-sticky-position=right]{display:flex;align-items:center;gap:.5rem;padding:.5rem;max-width:100%;width:fit-content}.sticky-actions[data-sticky-position=right]{margin-left:auto}.sticky-actions[data-sticky-position=full]{max-width:100%}.sticky-actions-footer{max-width:100%;margin-top:1.5rem;padding:1rem;padding-bottom:calc(1rem + env(safe-area-inset-bottom,0));background:var(--tblr-bg-surface-secondary);border-top:1px solid var(--tblr-border-color)}.sticky-actions-footer[data-sticky-when=always],.sticky-actions-footer.is-sticky-active{bottom:0}.sticky-actions-footer>.btn-list{justify-content:flex-end;margin-bottom:0}.object-edit--with-sticky-actions{padding-bottom:calc(1.5rem + env(safe-area-inset-bottom,0))}[data-sticky-when=selection] .bulk-action-buttons .btn:disabled,[data-sticky-when=selection] .bulk-action-buttons .btn.disabled{border-color:transparent;box-shadow:none}[data-sticky-when=selection] .bulk-action-buttons .btn.disabled{pointer-events:none}.btn-float-group-right{position:sticky;bottom:10px;z-index:4;margin-left:auto;width:fit-content}.btn-float-group-left{position:sticky;bottom:10px;z-index:4;width:fit-content}tr[data-read=True] td{background-color:var(--tblr-bg-surface-secondary);color:#6b7280}.rack-loading-container{min-height:200px;margin-left:30px} diff --git a/netbox/project-static/styles/custom/_interfaces.scss b/netbox/project-static/styles/custom/_interfaces.scss index 9e6baa7e5..a1a5a999c 100644 --- a/netbox/project-static/styles/custom/_interfaces.scss +++ b/netbox/project-static/styles/custom/_interfaces.scss @@ -1,23 +1,41 @@ @use 'sass:map'; // Interface row coloring +// Use --tblr-table-bg-state so type highlights take precedence over striping +// (which sets --tblr-table-bg-type via the box-shadow cascade). tr[data-cable-status=connected] { - background-color: rgba(map.get($theme-colors, "green"), 0.15); + --tblr-table-bg-state: #{rgba(map.get($theme-colors, "green"), 0.15)}; } tr[data-cable-status=planned] { - background-color: rgba(map.get($theme-colors, "blue"), 0.15); + --tblr-table-bg-state: #{rgba(map.get($theme-colors, "blue"), 0.15)}; } tr[data-cable-status=decommissioning] { - background-color: rgba(map.get($theme-colors, "yellow"), 0.15); + --tblr-table-bg-state: #{rgba(map.get($theme-colors, "yellow"), 0.15)}; } tr[data-mark-connected=true] { - background-color: rgba(map.get($theme-colors, "success"), 0.15); + --tblr-table-bg-state: #{rgba(map.get($theme-colors, "success"), 0.15)}; } tr[data-virtual=true] { - background-color: rgba(map.get($theme-colors, "primary"), 0.15); + --tblr-table-bg-state: #{rgba(map.get($theme-colors, "primary"), 0.15)}; } tr[data-enabled=disabled] { - background-color: rgba($gray-400, 0.15); + --tblr-table-bg-state: #{rgba($gray-400, 0.15)}; +} + +// Bootstrap paints --tblr-table-bg-state via an inset box-shadow on each cell. +// In Chrome with border-collapse: collapse, that shadow covers the cell's +// bottom border and the row separator vanishes (Safari paints them in a +// different order, which is why it's not visible there). Repaint the highlight +// via background-color and clear the inset shadow so the border stays on top. +// Also use the opaque border color, since the default translucent value blends +// nearly invisibly against a tinted background. +tr[data-cable-status] > *, +tr[data-mark-connected=true] > *, +tr[data-virtual=true] > *, +tr[data-enabled=disabled] > * { + background-color: var(--tblr-table-bg-state); + border-bottom-color: var(--tblr-gray-300); + box-shadow: none; } // Only show the correct button depending on the cable status From 770c3647fbf46d6b13e66f6d5ae062501cf7924d Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Thu, 7 May 2026 17:20:42 +0200 Subject: [PATCH 019/131] feat(ui): Add nested breadcrumb display for GenericForeignKey attrs Add `nested` and `max_depth` params to GenericForeignKeyAttr to render hierarchical objects as breadcrumbs when they expose `get_ancestors()`. Applied to scope fields in IPAM/wireless and circuit termination points. Fixes #21938 --- netbox/circuits/ui/panels.py | 33 +++++++++- netbox/ipam/ui/panels.py | 4 +- netbox/netbox/tests/test_ui.py | 66 +++++++++++++++++++ netbox/netbox/ui/attrs.py | 33 +++++++++- .../inc/circuit_termination_fields.html | 6 +- .../panels/circuit_circuit_termination.html | 2 +- netbox/templates/ui/attrs/generic_object.html | 8 ++- netbox/virtualization/ui/panels.py | 2 +- netbox/wireless/ui/panels.py | 2 +- 9 files changed, 145 insertions(+), 11 deletions(-) diff --git a/netbox/circuits/ui/panels.py b/netbox/circuits/ui/panels.py index 3572479cd..a874da3da 100644 --- a/netbox/circuits/ui/panels.py +++ b/netbox/circuits/ui/panels.py @@ -12,16 +12,43 @@ class CircuitCircuitTerminationPanel(panels.ObjectPanel): template_name = 'circuits/panels/circuit_circuit_termination.html' title = _('Termination') + termination_ancestor_max_depth = 3 def __init__(self, side, accessor=None, **kwargs): super().__init__(accessor=accessor, **kwargs) self.side = side + def _get_termination_nodes(self, termination): + """ + Return the termination target's ancestors, including itself, when the + target is tree-like. + + Non-tree GFK targets return None, so the template preserves the current + single-object rendering. + """ + target = getattr(termination, 'termination', None) + if target is None: + return None + + get_ancestors = getattr(target, 'get_ancestors', None) + if not callable(get_ancestors): + return None + + nodes = list(get_ancestors(include_self=True)) + + if self.termination_ancestor_max_depth is not None: + nodes = nodes[-self.termination_ancestor_max_depth:] + + return nodes + def get_context(self, context): + termination = resolve_attr_path(context, f'{self.accessor}.termination_{self.side.lower()}') + return { **super().get_context(context), 'side': self.side, - 'termination': resolve_attr_path(context, f'{self.accessor}.termination_{self.side.lower()}'), + 'termination': termination, + 'termination_nodes': self._get_termination_nodes(termination), } @@ -58,7 +85,9 @@ class CircuitTerminationPanel(panels.ObjectAttributesPanel): title = _('Circuit Termination') circuit = attrs.RelatedObjectAttr('circuit', linkify=True) provider = attrs.RelatedObjectAttr('circuit.provider', linkify=True) - termination = attrs.GenericForeignKeyAttr('termination', linkify=True, label=_('Termination point')) + termination = attrs.GenericForeignKeyAttr( + 'termination', linkify=True, nested=True, max_depth=3, label=_('Termination point') + ) connection = attrs.TemplatedAttr( 'pk', template_name='circuits/circuit_termination/attrs/connection.html', diff --git a/netbox/ipam/ui/panels.py b/netbox/ipam/ui/panels.py index c8984352a..6e0f53d34 100644 --- a/netbox/ipam/ui/panels.py +++ b/netbox/ipam/ui/panels.py @@ -144,7 +144,7 @@ class PrefixPanel(panels.ObjectAttributesPanel): template_name='ipam/prefix/attrs/aggregate.html', label=_('Aggregate'), ) - scope = attrs.GenericForeignKeyAttr('scope', linkify=True) + scope = attrs.GenericForeignKeyAttr('scope', linkify=True, nested=True, max_depth=3) vlan = attrs.RelatedObjectAttr('vlan', linkify=True, label=_('VLAN'), grouped_by='group') status = attrs.ChoiceAttr('status') role = attrs.RelatedObjectAttr('role', linkify=True) @@ -155,7 +155,7 @@ class PrefixPanel(panels.ObjectAttributesPanel): class VLANGroupPanel(panels.ObjectAttributesPanel): name = attrs.TextAttr('name') description = attrs.TextAttr('description') - scope = attrs.GenericForeignKeyAttr('scope', linkify=True) + scope = attrs.GenericForeignKeyAttr('scope', linkify=True, nested=True, max_depth=3) vid_ranges = attrs.TemplatedAttr( 'vid_ranges_items', template_name='ipam/vlangroup/attrs/vid_ranges.html', diff --git a/netbox/netbox/tests/test_ui.py b/netbox/netbox/tests/test_ui.py index 31c38bf81..a1cd6fab6 100644 --- a/netbox/netbox/tests/test_ui.py +++ b/netbox/netbox/tests/test_ui.py @@ -341,6 +341,23 @@ class RelatedObjectAttrTest(TestCase): class GenericForeignKeyAttrTest(TestCase): + class TreeNode: + def __init__(self, name, ancestors=()): + self.name = name + self.ancestors = list(ancestors) + self.include_self = None + self._meta = SimpleNamespace(verbose_name='location') + + def __str__(self): + return self.name + + def get_ancestors(self, include_self=False): + self.include_self = include_self + + if include_self: + return [*self.ancestors, self] + return self.ancestors + def test_get_context_content_type(self): value = SimpleNamespace(_meta=SimpleNamespace(verbose_name='provider')) obj = SimpleNamespace() @@ -355,6 +372,55 @@ class GenericForeignKeyAttrTest(TestCase): context = attr.get_context(obj, 'assigned_object', value, {}) self.assertTrue(context['linkify']) + def test_get_context_nested_disabled(self): + root = self.TreeNode('Root') + child = self.TreeNode('Child', ancestors=[root]) + + obj = SimpleNamespace() + attr = attrs.GenericForeignKeyAttr('assigned_object') + context = attr.get_context(obj, 'assigned_object', child, {}) + + self.assertIsNone(context['nodes']) + + def test_get_context_nested_non_hierarchical_object(self): + value = SimpleNamespace(_meta=SimpleNamespace(verbose_name='site')) + obj = SimpleNamespace() + attr = attrs.GenericForeignKeyAttr('assigned_object', nested=True) + context = attr.get_context(obj, 'assigned_object', value, {}) + + self.assertIsNone(context['nodes']) + + def test_get_context_nested_hierarchical_object(self): + root = self.TreeNode('Root') + parent = self.TreeNode('Parent', ancestors=[root]) + child = self.TreeNode('Child', ancestors=[root, parent]) + + obj = SimpleNamespace() + attr = attrs.GenericForeignKeyAttr('assigned_object', nested=True) + context = attr.get_context(obj, 'assigned_object', child, {}) + + self.assertEqual(context['nodes'], [root, parent, child]) + self.assertTrue(child.include_self) + + def test_get_context_nested_max_depth(self): + root = self.TreeNode('Root') + parent = self.TreeNode('Parent', ancestors=[root]) + child = self.TreeNode('Child', ancestors=[root, parent]) + + obj = SimpleNamespace() + attr = attrs.GenericForeignKeyAttr('assigned_object', nested=True, max_depth=2) + context = attr.get_context(obj, 'assigned_object', child, {}) + + self.assertEqual(context['nodes'], [parent, child]) + + def test_get_context_nested_null_value(self): + obj = SimpleNamespace() + attr = attrs.GenericForeignKeyAttr('assigned_object', nested=True) + context = attr.get_context(obj, 'assigned_object', None, {}) + + self.assertIsNone(context['content_type']) + self.assertIsNone(context['nodes']) + class GPSCoordinatesAttrTest(TestCase): diff --git a/netbox/netbox/ui/attrs.py b/netbox/netbox/ui/attrs.py index d5f066ddd..e2535a40c 100644 --- a/netbox/netbox/ui/attrs.py +++ b/netbox/netbox/ui/attrs.py @@ -412,19 +412,48 @@ class GenericForeignKeyAttr(ObjectAttribute): Parameters: linkify (bool): If True, the rendered value will be hyperlinked - to the related object's detail view + to the related object's detail view. + nested (bool): If True and the related object exposes a callable + `get_ancestors(include_self=True)`, render the object together + with its ancestors as a breadcrumb, similar to `NestedObjectAttr`. + Non-hierarchical objects continue to render normally. + max_depth (int): Maximum number of ancestors to display when + `nested` is enabled. Ignored otherwise. """ template_name = 'ui/attrs/generic_object.html' - def __init__(self, *args, linkify=None, **kwargs): + def __init__(self, *args, linkify=None, nested=False, max_depth=None, **kwargs): super().__init__(*args, **kwargs) self.linkify = linkify + self.nested = nested + self.max_depth = max_depth + + def _get_nodes(self, value): + """ + Retrieves a list of nodes representing the hierarchical path to a given value. + """ + if value is None: + return None + + get_ancestors = getattr(value, 'get_ancestors', None) + if not callable(get_ancestors): + return None + + nodes = list(get_ancestors(include_self=True)) + + if self.max_depth is not None: + nodes = nodes[-self.max_depth:] + + return nodes def get_context(self, obj, attr, value, context): content_type = value._meta.verbose_name if value is not None else None + nodes = self._get_nodes(value) if (self.nested and value is not None) else None + return { 'content_type': content_type, 'linkify': self.linkify, + 'nodes': nodes, } diff --git a/netbox/templates/circuits/inc/circuit_termination_fields.html b/netbox/templates/circuits/inc/circuit_termination_fields.html index 1ea465fca..cc37ed0d2 100644 --- a/netbox/templates/circuits/inc/circuit_termination_fields.html +++ b/netbox/templates/circuits/inc/circuit_termination_fields.html @@ -5,7 +5,11 @@ {% if termination.termination %} {% else %} diff --git a/netbox/templates/circuits/panels/circuit_circuit_termination.html b/netbox/templates/circuits/panels/circuit_circuit_termination.html index 5f79d48d4..589d2bd2b 100644 --- a/netbox/templates/circuits/panels/circuit_circuit_termination.html +++ b/netbox/templates/circuits/panels/circuit_circuit_termination.html @@ -24,7 +24,7 @@ {% if termination %}
{% trans "Termination point" %} - {{ termination.termination|linkify }} + {% if termination_nodes %} + {% include 'ui/attrs/nested_object.html' with nodes=termination_nodes linkify=True colored=False only %} + {% else %} + {{ termination.termination|linkify }} + {% endif %}
{% trans termination.termination_type.name|bettertitle %}
- {% include 'circuits/inc/circuit_termination_fields.html' with termination=termination %} + {% include 'circuits/inc/circuit_termination_fields.html' with termination=termination termination_nodes=termination_nodes %} @@ -55,7 +55,7 @@ {% for table, prefs in request.user.config.data.tables.items %} diff --git a/netbox/templates/dcim/device/base.html b/netbox/templates/dcim/device/base.html index 9a2286e40..d40afb51b 100644 --- a/netbox/templates/dcim/device/base.html +++ b/netbox/templates/dcim/device/base.html @@ -20,7 +20,7 @@ - {% endif %} @@ -24,10 +24,10 @@ {% endfor %} diff --git a/netbox/templates/dcim/manufacturer.html b/netbox/templates/dcim/manufacturer.html index f6bd7dfc3..53295c308 100644 --- a/netbox/templates/dcim/manufacturer.html +++ b/netbox/templates/dcim/manufacturer.html @@ -7,7 +7,7 @@ -
{% trans "Tags" %} diff --git a/netbox/templates/ui/attrs/generic_object.html b/netbox/templates/ui/attrs/generic_object.html index 64b1a6d9a..9a7a2d498 100644 --- a/netbox/templates/ui/attrs/generic_object.html +++ b/netbox/templates/ui/attrs/generic_object.html @@ -1,5 +1,11 @@ {% load helpers %} - {% if linkify %}{{ value|linkify }}{% else %}{{ value }}{% endif %} + {% if nodes %} + {% include 'ui/attrs/nested_object.html' with nodes=nodes linkify=linkify colored=False only %} + {% elif linkify %} + {{ value|linkify }} + {% else %} + {{ value }} + {% endif %} {% if content_type %}
{{ content_type|bettertitle }}
{% endif %} diff --git a/netbox/virtualization/ui/panels.py b/netbox/virtualization/ui/panels.py index f5505e392..f562efc77 100644 --- a/netbox/virtualization/ui/panels.py +++ b/netbox/virtualization/ui/panels.py @@ -14,7 +14,7 @@ class ClusterPanel(panels.ObjectAttributesPanel): description = attrs.TextAttr('description') group = attrs.RelatedObjectAttr('group', linkify=True) tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group') - scope = attrs.GenericForeignKeyAttr('scope', linkify=True) + scope = attrs.GenericForeignKeyAttr('scope', linkify=True, nested=True, max_depth=3) # diff --git a/netbox/wireless/ui/panels.py b/netbox/wireless/ui/panels.py index 0135fe4bb..df440724a 100644 --- a/netbox/wireless/ui/panels.py +++ b/netbox/wireless/ui/panels.py @@ -11,7 +11,7 @@ class WirelessLANPanel(panels.ObjectAttributesPanel): ssid = attrs.TextAttr('ssid', label=_('SSID')) group = attrs.RelatedObjectAttr('group', linkify=True) status = attrs.ChoiceAttr('status') - scope = attrs.GenericForeignKeyAttr('scope', linkify=True) + scope = attrs.GenericForeignKeyAttr('scope', linkify=True, nested=True, max_depth=3) description = attrs.TextAttr('description') vlan = attrs.RelatedObjectAttr('vlan', label=_('VLAN'), linkify=True) tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group') From 692658012403e0e7707750ebe3f3959238768e0e Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 05:41:23 +0000 Subject: [PATCH 020/131] Update source translation strings --- netbox/translations/en/LC_MESSAGES/django.po | 290 ++++++++++--------- 1 file changed, 150 insertions(+), 140 deletions(-) diff --git a/netbox/translations/en/LC_MESSAGES/django.po b/netbox/translations/en/LC_MESSAGES/django.po index 98729292d..21371e7f3 100644 --- a/netbox/translations/en/LC_MESSAGES/django.po +++ b/netbox/translations/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-06 05:59+0000\n" +"POT-Creation-Date: 2026-05-08 05:41+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -195,7 +195,7 @@ msgstr "" #: netbox/templates/dcim/inc/cable_termination.html:8 #: netbox/templates/dcim/inc/cable_termination.html:36 #: netbox/templates/ipam/vlan_edit.html:52 -#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_edit.py:127 #: netbox/virtualization/forms/bulk_import.py:62 #: netbox/virtualization/forms/bulk_import.py:124 #: netbox/virtualization/forms/filtersets.py:86 @@ -397,7 +397,7 @@ msgstr "" #: netbox/circuits/forms/bulk_edit.py:48 netbox/circuits/forms/filtersets.py:68 #: netbox/circuits/forms/model_forms.py:48 -#: netbox/circuits/tables/providers.py:32 netbox/circuits/ui/panels.py:108 +#: netbox/circuits/tables/providers.py:32 netbox/circuits/ui/panels.py:137 #: netbox/dcim/forms/bulk_edit.py:142 netbox/dcim/forms/filtersets.py:227 #: netbox/dcim/forms/model_forms.py:144 netbox/dcim/tables/sites.py:74 #: netbox/ipam/models/asns.py:164 netbox/ipam/tables/asn.py:37 @@ -437,7 +437,7 @@ msgid "Provider" msgstr "" #: netbox/circuits/forms/bulk_edit.py:86 -#: netbox/circuits/forms/filtersets.py:106 netbox/circuits/ui/panels.py:122 +#: netbox/circuits/forms/filtersets.py:106 netbox/circuits/ui/panels.py:151 msgid "Service ID" msgstr "" @@ -500,7 +500,7 @@ msgstr "" #: netbox/templates/core/htmx/system_db_schema.html:70 #: netbox/templates/dcim/panels/interface_connection.html:68 #: netbox/templates/wireless/panels/wirelesslink_interface.html:16 -#: netbox/virtualization/forms/bulk_edit.py:54 +#: netbox/virtualization/forms/bulk_edit.py:52 #: netbox/virtualization/forms/bulk_import.py:44 #: netbox/virtualization/forms/filtersets.py:66 #: netbox/virtualization/forms/model_forms.py:64 @@ -567,8 +567,8 @@ msgstr "" #: netbox/templates/core/system.html:20 #: netbox/templates/extras/inc/script_list_content.html:35 #: netbox/users/forms/filtersets.py:36 netbox/users/forms/model_forms.py:215 -#: netbox/virtualization/forms/bulk_edit.py:64 -#: netbox/virtualization/forms/bulk_edit.py:117 +#: netbox/virtualization/forms/bulk_edit.py:62 +#: netbox/virtualization/forms/bulk_edit.py:115 #: netbox/virtualization/forms/bulk_import.py:57 #: netbox/virtualization/forms/bulk_import.py:113 #: netbox/virtualization/forms/filtersets.py:94 @@ -630,8 +630,8 @@ msgstr "" #: netbox/ipam/tables/ip.py:424 netbox/tenancy/forms/filtersets.py:55 #: netbox/tenancy/forms/forms.py:26 netbox/tenancy/forms/forms.py:50 #: netbox/tenancy/forms/model_forms.py:51 netbox/tenancy/tables/columns.py:50 -#: netbox/virtualization/forms/bulk_edit.py:70 -#: netbox/virtualization/forms/bulk_edit.py:161 +#: netbox/virtualization/forms/bulk_edit.py:68 +#: netbox/virtualization/forms/bulk_edit.py:159 #: netbox/virtualization/forms/bulk_import.py:69 #: netbox/virtualization/forms/bulk_import.py:154 #: netbox/virtualization/forms/filtersets.py:58 @@ -775,7 +775,7 @@ msgstr "" #: netbox/netbox/forms/bulk_edit.py:79 netbox/netbox/forms/bulk_edit.py:91 #: netbox/netbox/forms/bulk_edit.py:103 netbox/netbox/ui/panels.py:219 #: netbox/netbox/ui/panels.py:228 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:85 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:89 #: netbox/templates/core/plugin.html:80 #: netbox/templates/dcim/cablebundle.html:21 #: netbox/templates/extras/dashboard/widget_add.html:14 @@ -784,8 +784,8 @@ msgstr "" #: netbox/users/forms/bulk_edit.py:62 netbox/users/forms/bulk_edit.py:80 #: netbox/users/forms/bulk_edit.py:115 netbox/users/forms/bulk_edit.py:143 #: netbox/users/forms/bulk_edit.py:166 -#: netbox/virtualization/forms/bulk_edit.py:241 -#: netbox/virtualization/forms/bulk_edit.py:366 +#: netbox/virtualization/forms/bulk_edit.py:239 +#: netbox/virtualization/forms/bulk_edit.py:357 msgid "Description" msgstr "" @@ -822,10 +822,10 @@ msgid "Mark connected" msgstr "" #: netbox/circuits/forms/bulk_edit.py:220 -#: netbox/circuits/forms/model_forms.py:213 netbox/circuits/ui/panels.py:58 +#: netbox/circuits/forms/model_forms.py:213 netbox/circuits/ui/panels.py:85 #: netbox/dcim/views.py:3564 netbox/dcim/views.py:3665 #: netbox/templates/circuits/circuit_termination/attrs/connection.html:43 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:55 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:59 #: netbox/templates/dcim/panels/interface_connection.html:92 msgid "Circuit Termination" msgstr "" @@ -891,7 +891,7 @@ msgstr "" #: netbox/templates/wireless/panels/wirelesslink_interface.html:20 #: netbox/tenancy/forms/bulk_edit.py:136 netbox/tenancy/forms/filtersets.py:136 #: netbox/tenancy/forms/model_forms.py:137 netbox/tenancy/tables/contacts.py:96 -#: netbox/virtualization/forms/bulk_edit.py:151 +#: netbox/virtualization/forms/bulk_edit.py:149 #: netbox/virtualization/forms/bulk_import.py:145 #: netbox/virtualization/forms/filtersets.py:219 #: netbox/virtualization/forms/model_forms.py:237 @@ -983,7 +983,7 @@ msgstr "" #: netbox/circuits/forms/bulk_import.py:258 #: netbox/circuits/forms/model_forms.py:392 #: netbox/circuits/tables/virtual_circuits.py:109 -#: netbox/circuits/ui/panels.py:150 netbox/dcim/forms/bulk_import.py:1358 +#: netbox/circuits/ui/panels.py:179 netbox/dcim/forms/bulk_import.py:1358 #: netbox/dcim/forms/model_forms.py:1371 netbox/dcim/forms/model_forms.py:1640 #: netbox/dcim/forms/model_forms.py:1821 netbox/dcim/forms/model_forms.py:1856 #: netbox/dcim/forms/model_forms.py:1981 netbox/dcim/tables/connections.py:66 @@ -993,7 +993,7 @@ msgstr "" #: netbox/ipam/tables/fhrp.py:61 netbox/ipam/tables/ip.py:328 #: netbox/ipam/tables/vlans.py:149 #: netbox/templates/circuits/circuit_termination/attrs/connection.html:40 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:52 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:56 #: netbox/templates/dcim/panels/interface_connection.html:83 #: netbox/templates/wireless/panels/wirelesslink_interface.html:12 #: netbox/virtualization/forms/model_forms.py:449 @@ -1217,7 +1217,7 @@ msgstr "" #: netbox/users/forms/filtersets.py:41 netbox/users/forms/filtersets.py:76 #: netbox/users/forms/filtersets.py:165 netbox/users/forms/filtersets.py:171 #: netbox/users/forms/model_forms.py:543 netbox/users/tables.py:186 -#: netbox/virtualization/forms/bulk_edit.py:59 +#: netbox/virtualization/forms/bulk_edit.py:57 #: netbox/virtualization/forms/bulk_import.py:50 #: netbox/virtualization/forms/filtersets.py:102 #: netbox/virtualization/forms/model_forms.py:69 @@ -1257,7 +1257,7 @@ msgstr "" msgid "Group Assignment" msgstr "" -#: netbox/circuits/models/base.py:18 netbox/dcim/models/cables.py:110 +#: netbox/circuits/models/base.py:18 netbox/dcim/models/cables.py:111 #: netbox/dcim/models/device_component_templates.py:363 #: netbox/dcim/models/device_component_templates.py:606 #: netbox/dcim/models/device_component_templates.py:679 @@ -1290,7 +1290,7 @@ msgstr "" #: netbox/circuits/models/circuits.py:72 #: netbox/circuits/models/virtual_circuits.py:60 netbox/core/models/data.py:53 -#: netbox/core/models/jobs.py:95 netbox/dcim/models/cables.py:86 +#: netbox/core/models/jobs.py:95 netbox/dcim/models/cables.py:87 #: netbox/dcim/models/device_components.py:619 #: netbox/dcim/models/device_components.py:1501 #: netbox/dcim/models/devices.py:599 netbox/dcim/models/devices.py:1261 @@ -1424,7 +1424,7 @@ msgstr "" #: netbox/circuits/models/providers.py:21 #: netbox/circuits/models/providers.py:63 #: netbox/circuits/models/providers.py:98 netbox/core/models/data.py:40 -#: netbox/core/models/jobs.py:56 netbox/dcim/models/cables.py:53 +#: netbox/core/models/jobs.py:56 netbox/dcim/models/cables.py:54 #: netbox/dcim/models/device_component_templates.py:55 #: netbox/dcim/models/device_components.py:56 netbox/dcim/models/devices.py:543 #: netbox/dcim/models/devices.py:1184 netbox/dcim/models/devices.py:1256 @@ -1612,7 +1612,7 @@ msgstr "" #: netbox/circuits/tables/circuits.py:53 #: netbox/circuits/tables/virtual_circuits.py:42 -#: netbox/circuits/ui/panels.py:91 netbox/circuits/ui/panels.py:134 +#: netbox/circuits/ui/panels.py:120 netbox/circuits/ui/panels.py:163 #: netbox/templates/dcim/panels/interface_virtual_circuit.html:15 msgid "Circuit ID" msgstr "" @@ -1718,7 +1718,7 @@ msgstr "" #: netbox/templates/dcim/virtualchassis_edit.html:63 #: netbox/templates/wireless/panels/wirelesslink_interface.html:8 #: netbox/virtualization/filtersets.py:212 -#: netbox/virtualization/forms/bulk_edit.py:142 +#: netbox/virtualization/forms/bulk_edit.py:140 #: netbox/virtualization/forms/bulk_import.py:138 #: netbox/virtualization/forms/filtersets.py:190 #: netbox/virtualization/forms/model_forms.py:223 @@ -1732,46 +1732,46 @@ msgstr "" msgid "Device" msgstr "" -#: netbox/circuits/ui/panels.py:33 netbox/netbox/navigation/menu.py:309 +#: netbox/circuits/ui/panels.py:60 netbox/netbox/navigation/menu.py:309 msgid "Group Assignments" msgstr "" -#: netbox/circuits/ui/panels.py:42 netbox/ipam/ui/panels.py:36 +#: netbox/circuits/ui/panels.py:69 netbox/ipam/ui/panels.py:36 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:15 msgid "Assign Group" msgstr "" -#: netbox/circuits/ui/panels.py:61 +#: netbox/circuits/ui/panels.py:89 #: netbox/templates/circuits/inc/circuit_termination_fields.html:5 msgid "Termination point" msgstr "" -#: netbox/circuits/ui/panels.py:65 netbox/dcim/forms/filtersets.py:1481 +#: netbox/circuits/ui/panels.py:94 netbox/dcim/forms/filtersets.py:1481 #: netbox/dcim/forms/filtersets.py:1521 netbox/dcim/forms/filtersets.py:1561 #: netbox/dcim/forms/filtersets.py:1596 netbox/dcim/forms/filtersets.py:1645 #: netbox/dcim/tables/devices.py:381 netbox/dcim/tables/devices.py:693 #: netbox/dcim/ui/panels.py:394 netbox/dcim/ui/panels.py:530 #: netbox/ipam/tables/vlans.py:178 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:16 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:20 msgid "Connection" msgstr "" -#: netbox/circuits/ui/panels.py:70 netbox/dcim/forms/bulk_edit.py:1480 +#: netbox/circuits/ui/panels.py:99 netbox/dcim/forms/bulk_edit.py:1480 #: netbox/dcim/forms/bulk_import.py:835 netbox/dcim/forms/bulk_import.py:861 #: netbox/dcim/forms/filtersets.py:1490 netbox/dcim/forms/filtersets.py:1530 #: netbox/dcim/forms/filtersets.py:1668 netbox/dcim/tables/devices.py:662 #: netbox/dcim/ui/panels.py:488 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:64 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:68 msgid "Speed" msgstr "" -#: netbox/circuits/ui/panels.py:72 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:77 +#: netbox/circuits/ui/panels.py:101 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:81 msgid "Cross-Connect" msgstr "" -#: netbox/circuits/ui/panels.py:73 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:81 +#: netbox/circuits/ui/panels.py:102 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:85 msgid "Patch Panel/Port" msgstr "" @@ -2043,7 +2043,7 @@ msgstr "" #: netbox/users/forms/bulk_edit.py:87 netbox/users/forms/bulk_edit.py:105 #: netbox/users/forms/filtersets.py:67 netbox/users/forms/filtersets.py:133 #: netbox/users/tables.py:30 netbox/users/tables.py:113 -#: netbox/virtualization/forms/bulk_edit.py:230 +#: netbox/virtualization/forms/bulk_edit.py:228 #: netbox/virtualization/forms/filtersets.py:285 msgid "Enabled" msgstr "" @@ -2353,7 +2353,7 @@ msgstr "" msgid "Config revision #{id}" msgstr "" -#: netbox/core/models/data.py:45 netbox/dcim/models/cables.py:79 +#: netbox/core/models/data.py:45 netbox/dcim/models/cables.py:80 #: netbox/dcim/models/device_component_templates.py:220 #: netbox/dcim/models/device_component_templates.py:255 #: netbox/dcim/models/device_component_templates.py:291 @@ -2447,7 +2447,7 @@ msgstr "" msgid "last updated" msgstr "" -#: netbox/core/models/data.py:304 netbox/dcim/models/cables.py:713 +#: netbox/core/models/data.py:304 netbox/dcim/models/cables.py:714 msgid "path" msgstr "" @@ -3087,7 +3087,7 @@ msgstr "" #: netbox/tenancy/forms/bulk_import.py:64 #: netbox/tenancy/forms/model_forms.py:26 #: netbox/tenancy/forms/model_forms.py:67 -#: netbox/virtualization/forms/bulk_edit.py:220 +#: netbox/virtualization/forms/bulk_edit.py:218 #: netbox/virtualization/forms/bulk_import.py:191 #: netbox/virtualization/tables/virtualmachines.py:173 #: netbox/vpn/ui/panels.py:25 netbox/wireless/forms/bulk_edit.py:26 @@ -3212,7 +3212,7 @@ msgstr "" #: netbox/dcim/choices.py:1164 netbox/dcim/forms/bulk_edit.py:1455 #: netbox/dcim/forms/bulk_import.py:965 netbox/dcim/forms/model_forms.py:1170 #: netbox/dcim/tables/devices.py:761 -#: netbox/virtualization/forms/bulk_edit.py:225 +#: netbox/virtualization/forms/bulk_edit.py:223 #: netbox/virtualization/forms/bulk_import.py:198 #: netbox/virtualization/tables/virtualmachines.py:177 msgid "Bridge" @@ -4020,7 +4020,7 @@ msgstr "" #: netbox/ipam/tables/ip.py:263 netbox/ipam/tables/ip.py:316 #: netbox/ipam/tables/ip.py:418 netbox/ipam/ui/panels.py:103 #: netbox/ipam/ui/panels.py:112 netbox/ipam/ui/panels.py:140 -#: netbox/virtualization/forms/bulk_edit.py:274 +#: netbox/virtualization/forms/bulk_edit.py:272 #: netbox/virtualization/forms/bulk_import.py:245 #: netbox/virtualization/forms/filtersets.py:298 #: netbox/virtualization/forms/model_forms.py:440 @@ -4061,7 +4061,7 @@ msgstr "" #: netbox/dcim/forms/model_forms.py:1635 #: netbox/dcim/models/device_components.py:743 #: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:733 -#: netbox/virtualization/forms/bulk_edit.py:279 +#: netbox/virtualization/forms/bulk_edit.py:277 #: netbox/virtualization/forms/filtersets.py:313 #: netbox/virtualization/forms/model_forms.py:445 msgid "VLAN Translation Policy" @@ -4415,7 +4415,7 @@ msgstr "" #: netbox/dcim/forms/bulk_edit.py:513 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:583 netbox/dcim/forms/model_forms.py:416 -#: netbox/virtualization/forms/bulk_edit.py:87 +#: netbox/virtualization/forms/bulk_edit.py:85 #: netbox/virtualization/forms/bulk_import.py:89 #: netbox/virtualization/forms/filtersets.py:124 #: netbox/virtualization/forms/model_forms.py:177 @@ -4515,7 +4515,7 @@ msgstr "" #: netbox/dcim/forms/filtersets.py:822 netbox/dcim/forms/filtersets.py:931 #: netbox/dcim/forms/model_forms.py:602 netbox/dcim/forms/model_forms.py:674 #: netbox/dcim/tables/devices.py:191 netbox/extras/filtersets.py:770 -#: netbox/virtualization/forms/bulk_edit.py:166 +#: netbox/virtualization/forms/bulk_edit.py:164 #: netbox/virtualization/forms/bulk_import.py:161 #: netbox/virtualization/forms/filtersets.py:235 #: netbox/virtualization/forms/model_forms.py:245 @@ -4530,7 +4530,7 @@ msgstr "" #: netbox/ipam/forms/filtersets.py:462 netbox/ipam/forms/filtersets.py:501 #: netbox/virtualization/filtersets.py:200 #: netbox/virtualization/filtersets.py:341 -#: netbox/virtualization/forms/bulk_edit.py:134 +#: netbox/virtualization/forms/bulk_edit.py:132 #: netbox/virtualization/forms/bulk_import.py:131 #: netbox/virtualization/forms/filtersets.py:153 #: netbox/virtualization/forms/filtersets.py:185 @@ -4543,7 +4543,7 @@ msgstr "" #: netbox/dcim/forms/bulk_edit.py:752 #: netbox/templates/extras/dashboard/widget_config.html:7 -#: netbox/virtualization/forms/bulk_edit.py:192 +#: netbox/virtualization/forms/bulk_edit.py:190 msgid "Configuration" msgstr "" @@ -4688,7 +4688,7 @@ msgid "Virtual device contexts" msgstr "" #: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/bulk_import.py:1010 -#: netbox/virtualization/forms/bulk_edit.py:246 +#: netbox/virtualization/forms/bulk_edit.py:244 #: netbox/virtualization/forms/bulk_import.py:205 #: netbox/vpn/forms/bulk_edit.py:128 netbox/vpn/forms/bulk_edit.py:196 #: netbox/vpn/forms/bulk_import.py:175 netbox/vpn/forms/bulk_import.py:233 @@ -4701,7 +4701,7 @@ msgstr "" #: netbox/dcim/forms/bulk_edit.py:1517 netbox/dcim/forms/bulk_import.py:1016 #: netbox/dcim/forms/model_forms.py:1584 netbox/ipam/forms/bulk_import.py:184 #: netbox/ipam/forms/filtersets.py:597 netbox/ipam/models/vlans.py:92 -#: netbox/virtualization/forms/bulk_edit.py:253 +#: netbox/virtualization/forms/bulk_edit.py:251 #: netbox/virtualization/forms/bulk_import.py:211 #: netbox/virtualization/forms/model_forms.py:407 msgid "VLAN group" @@ -4709,7 +4709,7 @@ msgstr "" #: netbox/dcim/forms/bulk_edit.py:1526 netbox/dcim/forms/bulk_import.py:1023 #: netbox/dcim/forms/model_forms.py:1590 netbox/dcim/tables/devices.py:627 -#: netbox/dcim/ui/panels.py:498 netbox/virtualization/forms/bulk_edit.py:261 +#: netbox/dcim/ui/panels.py:498 netbox/virtualization/forms/bulk_edit.py:259 #: netbox/virtualization/forms/bulk_import.py:218 #: netbox/virtualization/forms/model_forms.py:412 msgid "Untagged VLAN" @@ -4717,7 +4717,7 @@ msgstr "" #: netbox/dcim/forms/bulk_edit.py:1535 netbox/dcim/forms/bulk_import.py:1030 #: netbox/dcim/forms/model_forms.py:1599 netbox/dcim/tables/devices.py:633 -#: netbox/virtualization/forms/bulk_edit.py:269 +#: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/bulk_import.py:225 #: netbox/virtualization/forms/model_forms.py:421 msgid "Tagged VLANs" @@ -4774,14 +4774,14 @@ msgid "PoE" msgstr "" #: netbox/dcim/forms/bulk_edit.py:1590 netbox/dcim/forms/model_forms.py:1644 -#: netbox/dcim/ui/panels.py:505 netbox/virtualization/forms/bulk_edit.py:285 +#: netbox/dcim/ui/panels.py:505 netbox/virtualization/forms/bulk_edit.py:283 #: netbox/virtualization/forms/model_forms.py:452 msgid "Related Interfaces" msgstr "" #: netbox/dcim/forms/bulk_edit.py:1592 netbox/dcim/forms/filtersets.py:1637 #: netbox/dcim/forms/model_forms.py:1648 -#: netbox/virtualization/forms/bulk_edit.py:288 +#: netbox/virtualization/forms/bulk_edit.py:286 #: netbox/virtualization/forms/filtersets.py:267 #: netbox/virtualization/forms/model_forms.py:455 msgid "802.1Q Switching" @@ -5205,8 +5205,8 @@ msgstr "" #: netbox/dcim/forms/bulk_import.py:1351 netbox/ipam/forms/bulk_import.py:323 #: netbox/virtualization/filtersets.py:354 #: netbox/virtualization/filtersets.py:412 -#: netbox/virtualization/forms/bulk_edit.py:213 -#: netbox/virtualization/forms/bulk_edit.py:355 +#: netbox/virtualization/forms/bulk_edit.py:211 +#: netbox/virtualization/forms/bulk_edit.py:346 #: netbox/virtualization/forms/bulk_import.py:186 #: netbox/virtualization/forms/bulk_import.py:287 #: netbox/virtualization/forms/filtersets.py:282 @@ -5392,7 +5392,7 @@ msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "" #: netbox/dcim/forms/common.py:20 netbox/dcim/models/device_components.py:690 -#: netbox/dcim/ui/panels.py:490 netbox/virtualization/forms/bulk_edit.py:238 +#: netbox/dcim/ui/panels.py:490 netbox/virtualization/forms/bulk_edit.py:236 #: netbox/virtualization/ui/panels.py:94 msgid "MTU" msgstr "" @@ -5594,7 +5594,7 @@ msgstr "" #: netbox/ipam/forms/model_forms.py:232 netbox/ipam/forms/model_forms.py:264 #: netbox/ipam/forms/model_forms.py:633 netbox/ipam/forms/model_forms.py:643 #: netbox/ipam/tables/ip.py:198 netbox/ipam/tables/vlans.py:40 -#: netbox/virtualization/forms/bulk_edit.py:78 +#: netbox/virtualization/forms/bulk_edit.py:76 #: netbox/virtualization/forms/filtersets.py:57 #: netbox/virtualization/forms/model_forms.py:77 #: netbox/virtualization/tables/clusters.py:81 @@ -5777,7 +5777,7 @@ msgstr "" #: netbox/dcim/views.py:3025 netbox/dcim/views.py:3114 #: netbox/dcim/views.py:3559 netbox/dcim/views.py:3660 #: netbox/templates/circuits/circuit_termination/attrs/connection.html:41 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:53 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:57 #: netbox/templates/dcim/panels/interface_connection.html:86 #: netbox/templates/dcim/panels/rear_port_mappings.html:10 msgid "Front Port" @@ -5787,7 +5787,7 @@ msgstr "" #: netbox/dcim/views.py:3026 netbox/dcim/views.py:3115 #: netbox/dcim/views.py:3560 netbox/dcim/views.py:3661 #: netbox/templates/circuits/circuit_termination/attrs/connection.html:42 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:54 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:58 #: netbox/templates/dcim/panels/front_port_mappings.html:10 #: netbox/templates/dcim/panels/interface_connection.html:89 msgid "Rear Port" @@ -5926,138 +5926,138 @@ msgid "" "{positions} positions." msgstr "" -#: netbox/dcim/models/cables.py:60 +#: netbox/dcim/models/cables.py:61 msgid "cable bundle" msgstr "" -#: netbox/dcim/models/cables.py:61 +#: netbox/dcim/models/cables.py:62 msgid "cable bundles" msgstr "" -#: netbox/dcim/models/cables.py:92 +#: netbox/dcim/models/cables.py:93 msgid "profile" msgstr "" -#: netbox/dcim/models/cables.py:105 +#: netbox/dcim/models/cables.py:106 #: netbox/dcim/models/device_component_templates.py:63 #: netbox/dcim/models/device_components.py:61 #: netbox/extras/models/customfields.py:138 msgid "label" msgstr "" -#: netbox/dcim/models/cables.py:114 +#: netbox/dcim/models/cables.py:115 msgid "length" msgstr "" -#: netbox/dcim/models/cables.py:121 +#: netbox/dcim/models/cables.py:122 msgid "length unit" msgstr "" -#: netbox/dcim/models/cables.py:140 +#: netbox/dcim/models/cables.py:141 msgid "bundle" msgstr "" -#: netbox/dcim/models/cables.py:147 +#: netbox/dcim/models/cables.py:148 msgid "cable" msgstr "" -#: netbox/dcim/models/cables.py:148 +#: netbox/dcim/models/cables.py:149 msgid "cables" msgstr "" -#: netbox/dcim/models/cables.py:273 +#: netbox/dcim/models/cables.py:274 msgid "Must specify a unit when setting a cable length" msgstr "" -#: netbox/dcim/models/cables.py:276 +#: netbox/dcim/models/cables.py:277 msgid "Must define A and B terminations when creating a new cable." msgstr "" -#: netbox/dcim/models/cables.py:287 +#: netbox/dcim/models/cables.py:288 msgid "Cannot connect different termination types to same end of cable." msgstr "" -#: netbox/dcim/models/cables.py:295 +#: netbox/dcim/models/cables.py:296 #, python-brace-format msgid "Incompatible termination types: {type_a} and {type_b}" msgstr "" -#: netbox/dcim/models/cables.py:305 +#: netbox/dcim/models/cables.py:306 msgid "A and B terminations cannot connect to the same object." msgstr "" -#: netbox/dcim/models/cables.py:502 netbox/ipam/models/asns.py:38 +#: netbox/dcim/models/cables.py:503 netbox/ipam/models/asns.py:38 msgid "end" msgstr "" -#: netbox/dcim/models/cables.py:573 +#: netbox/dcim/models/cables.py:574 msgid "cable termination" msgstr "" -#: netbox/dcim/models/cables.py:574 +#: netbox/dcim/models/cables.py:575 msgid "cable terminations" msgstr "" -#: netbox/dcim/models/cables.py:587 +#: netbox/dcim/models/cables.py:588 #, python-brace-format msgid "" "Cannot connect a cable to {obj_parent} > {obj} because it is marked as " "connected." msgstr "" -#: netbox/dcim/models/cables.py:604 +#: netbox/dcim/models/cables.py:605 #, python-brace-format msgid "" "Duplicate termination found for {app_label}.{model} {termination_id}: cable " "{cable_pk}" msgstr "" -#: netbox/dcim/models/cables.py:614 +#: netbox/dcim/models/cables.py:615 #, python-brace-format msgid "Cables cannot be terminated to {type_display} interfaces" msgstr "" -#: netbox/dcim/models/cables.py:621 +#: netbox/dcim/models/cables.py:622 msgid "Circuit terminations attached to a provider network may not be cabled." msgstr "" -#: netbox/dcim/models/cables.py:717 netbox/extras/models/configs.py:100 +#: netbox/dcim/models/cables.py:718 netbox/extras/models/configs.py:100 msgid "is active" msgstr "" -#: netbox/dcim/models/cables.py:721 +#: netbox/dcim/models/cables.py:722 msgid "is complete" msgstr "" -#: netbox/dcim/models/cables.py:725 +#: netbox/dcim/models/cables.py:726 msgid "is split" msgstr "" -#: netbox/dcim/models/cables.py:733 +#: netbox/dcim/models/cables.py:739 msgid "cable path" msgstr "" -#: netbox/dcim/models/cables.py:734 +#: netbox/dcim/models/cables.py:740 msgid "cable paths" msgstr "" -#: netbox/dcim/models/cables.py:821 +#: netbox/dcim/models/cables.py:827 msgid "All originating terminations must be attached to the same link" msgstr "" -#: netbox/dcim/models/cables.py:839 +#: netbox/dcim/models/cables.py:845 msgid "All mid-span terminations must have the same termination type" msgstr "" -#: netbox/dcim/models/cables.py:847 +#: netbox/dcim/models/cables.py:853 msgid "All mid-span terminations must have the same parent object" msgstr "" -#: netbox/dcim/models/cables.py:877 +#: netbox/dcim/models/cables.py:883 msgid "All links must be cable or wireless" msgstr "" -#: netbox/dcim/models/cables.py:879 +#: netbox/dcim/models/cables.py:885 msgid "All links must match first link type" msgstr "" @@ -10250,7 +10250,7 @@ msgstr "" #: netbox/extras/tables/tables.py:296 #: netbox/templates/extras/panels/imageattachment_file.html:18 -#: netbox/virtualization/forms/bulk_edit.py:363 +#: netbox/virtualization/forms/bulk_edit.py:354 #: netbox/virtualization/forms/filtersets.py:332 #: netbox/virtualization/tables/virtualmachines.py:210 msgid "Size" @@ -12854,7 +12854,7 @@ msgstr "" #: netbox/netbox/object_actions.py:114 #: netbox/templates/circuits/circuit_termination/attrs/connection.html:25 #: netbox/templates/circuits/inc/circuit_termination.html:15 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:37 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:41 #: netbox/templates/circuits/panels/circuit_circuit_termination.html:15 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 #: netbox/templates/dcim/panels/component_inventory_items.html:22 @@ -13150,92 +13150,92 @@ msgid "" "Invalid max_items value: {max_items}! Must be a positive integer or None." msgstr "" -#: netbox/netbox/ui/attrs.py:461 +#: netbox/netbox/ui/attrs.py:490 msgid "GPS coordinates" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:138 +#: netbox/netbox/views/generic/bulk_views.py:139 #, python-brace-format msgid "" "There was an error rendering the selected export template ({template}): " "{error}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:418 +#: netbox/netbox/views/generic/bulk_views.py:419 msgid "Must be a list." msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:428 +#: netbox/netbox/views/generic/bulk_views.py:429 msgid "Must be a dictionary." msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:485 +#: netbox/netbox/views/generic/bulk_views.py:486 #, python-brace-format msgid "Object with ID {id} does not exist" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:548 +#: netbox/netbox/views/generic/bulk_views.py:549 #, python-brace-format msgid "" "Duplicate objects found: {model} with ID(s) {ids} appears multiple times" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:600 +#: netbox/netbox/views/generic/bulk_views.py:601 #, python-brace-format msgid "Bulk import {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:616 +#: netbox/netbox/views/generic/bulk_views.py:617 #, python-brace-format msgid "Imported {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:806 +#: netbox/netbox/views/generic/bulk_views.py:807 #, python-brace-format msgid "Bulk edit {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:822 +#: netbox/netbox/views/generic/bulk_views.py:823 #, python-brace-format msgid "Updated {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:855 -#: netbox/netbox/views/generic/bulk_views.py:1096 -#: netbox/netbox/views/generic/bulk_views.py:1144 +#: netbox/netbox/views/generic/bulk_views.py:856 +#: netbox/netbox/views/generic/bulk_views.py:1105 +#: netbox/netbox/views/generic/bulk_views.py:1153 #, python-brace-format msgid "No {object_type} were selected." msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:955 +#: netbox/netbox/views/generic/bulk_views.py:964 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:1025 +#: netbox/netbox/views/generic/bulk_views.py:1034 #, python-brace-format msgid "Bulk delete {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:1052 +#: netbox/netbox/views/generic/bulk_views.py:1061 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:1069 +#: netbox/netbox/views/generic/bulk_views.py:1078 msgid "Deletion failed due to the presence of one or more dependent objects." msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:1157 +#: netbox/netbox/views/generic/bulk_views.py:1166 #, python-brace-format msgid "Bulk add {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:1210 +#: netbox/netbox/views/generic/bulk_views.py:1219 msgid "An integrity error occurred while creating components" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:1222 +#: netbox/netbox/views/generic/bulk_views.py:1231 #, python-brace-format msgid "Added {count} {component} to {parent_count} {parent}." msgstr "" @@ -13349,7 +13349,7 @@ msgstr "" #: netbox/templates/account/password.html:19 #: netbox/templates/account/preferences.html:79 -#: netbox/templates/account/usertoken_edit.html:7 +#: netbox/templates/account/usertoken_edit.html:29 #: netbox/templates/core/configrevision_restore.html:63 #: netbox/templates/dcim/devicebay_populate.html:34 #: netbox/templates/dcim/virtualchassis_add_member.html:26 @@ -13369,14 +13369,14 @@ msgstr "" #: netbox/templates/htmx/delete_form.html:68 #: netbox/templates/htmx/quick_add.html:21 #: netbox/templates/ipam/ipaddress_assign.html:28 -#: netbox/templates/users/token_edit.html:14 +#: netbox/templates/users/token_edit.html:32 #: netbox/templates/virtualization/cluster_add_devices.html:30 msgid "Cancel" msgstr "" #: netbox/templates/account/password.html:20 #: netbox/templates/account/preferences.html:80 -#: netbox/templates/account/usertoken_edit.html:9 +#: netbox/templates/account/usertoken_edit.html:31 #: netbox/templates/dcim/devicebay_populate.html:35 #: netbox/templates/dcim/virtualchassis_add_member.html:28 #: netbox/templates/dcim/virtualchassis_edit.html:120 @@ -13384,7 +13384,7 @@ msgstr "" #: netbox/templates/extras/dashboard/widget_config.html:19 #: netbox/templates/extras/object_journal.html:27 #: netbox/templates/generic/object_edit.html:77 -#: netbox/templates/users/token_edit.html:16 +#: netbox/templates/users/token_edit.html:34 #: netbox/utilities/templates/helpers/applied_filters.html:16 #: netbox/utilities/templates/helpers/table_config_form.html:40 msgid "Save" @@ -13482,7 +13482,7 @@ msgstr "" msgid "Add a Token" msgstr "" -#: netbox/templates/account/usertoken_edit.html:11 +#: netbox/templates/account/usertoken_edit.html:33 #: netbox/templates/dcim/virtualchassis_edit.html:122 #: netbox/templates/generic/bulk_add.html:12 #: netbox/templates/generic/bulk_add_component.html:82 @@ -13491,7 +13491,7 @@ msgstr "" #: netbox/templates/htmx/quick_add.html:24 #: netbox/templates/ipam/inc/ipaddress_edit_header.html:7 #: netbox/templates/ipam/inc/prefix_edit_header.html:7 -#: netbox/templates/users/token_edit.html:18 +#: netbox/templates/users/token_edit.html:36 msgid "Create" msgstr "" @@ -13542,21 +13542,21 @@ msgid "Community" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/connection.html:5 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:20 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:24 #: netbox/templates/dcim/panels/connection.html:8 #: netbox/templates/dcim/panels/interface_connection.html:8 msgid "Marked as connected" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/connection.html:9 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:22 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:26 msgid "to" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/connection.html:20 #: netbox/templates/circuits/circuit_termination/attrs/connection.html:21 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:32 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:33 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:36 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:37 #: netbox/templates/dcim/inc/cable_termination.html:26 #: netbox/templates/dcim/inc/cable_termination.html:48 #: netbox/templates/dcim/inc/cable_termination.html:66 @@ -13569,23 +13569,23 @@ msgid "Trace" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/connection.html:24 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:36 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:40 msgid "Edit cable" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/connection.html:29 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:41 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:45 msgid "Remove cable" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/connection.html:30 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:42 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:46 #: netbox/templates/dcim/bulk_disconnect.html:5 msgid "Disconnect" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/connection.html:37 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:49 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/panels/connection.html:78 #: netbox/templates/dcim/panels/connection.html:90 #: netbox/templates/dcim/panels/interface_connection.html:79 @@ -13594,12 +13594,12 @@ msgid "Connect" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/speed.html:3 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:67 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:71 msgid "Downstream" msgstr "" #: netbox/templates/circuits/circuit_termination/attrs/speed.html:5 -#: netbox/templates/circuits/inc/circuit_termination_fields.html:68 +#: netbox/templates/circuits/inc/circuit_termination_fields.html:72 msgid "Upstream" msgstr "" @@ -15343,6 +15343,16 @@ msgstr "" msgid "View All" msgstr "" +#: netbox/templates/users/inc/v1_token_warning.html:8 +msgid "v1 API Tokens Are Deprecated" +msgstr "" + +#: netbox/templates/users/inc/v1_token_warning.html:10 +msgid "" +"v1 API tokens are deprecated and will be removed in a future NetBox release. " +"Please use v2 tokens instead." +msgstr "" + #: netbox/templates/users/objectpermission.html:4 #: netbox/users/forms/filtersets.py:63 msgid "Permission" @@ -15396,7 +15406,7 @@ msgstr "" #: netbox/templates/virtualization/panels/cluster_resources.html:12 #: netbox/templates/virtualization/panels/virtual_machine_resources.html:12 -#: netbox/virtualization/forms/bulk_edit.py:176 +#: netbox/virtualization/forms/bulk_edit.py:174 msgid "Memory" msgstr "" @@ -15406,7 +15416,7 @@ msgid "Disk Space" msgstr "" #: netbox/templates/virtualization/panels/virtual_machine_resources.html:5 -#: netbox/virtualization/forms/bulk_edit.py:191 +#: netbox/virtualization/forms/bulk_edit.py:189 #: netbox/virtualization/forms/model_forms.py:268 msgid "Resources" msgstr "" @@ -16620,69 +16630,69 @@ msgstr "" msgid "Cluster (ID)" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:92 +#: netbox/virtualization/forms/bulk_edit.py:90 #: netbox/virtualization/forms/filtersets.py:127 #: netbox/virtualization/ui/panels.py:28 msgid "Default vCPUs" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:96 +#: netbox/virtualization/forms/bulk_edit.py:94 msgid "Default Memory (MB)" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:102 +#: netbox/virtualization/forms/bulk_edit.py:100 #: netbox/virtualization/forms/model_forms.py:184 msgid "Virtual Machine Type" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:103 +#: netbox/virtualization/forms/bulk_edit.py:101 #: netbox/virtualization/forms/model_forms.py:185 msgid "Defaults" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:112 +#: netbox/virtualization/forms/bulk_edit.py:110 #: netbox/virtualization/forms/bulk_import.py:106 #: netbox/virtualization/forms/filtersets.py:168 msgid "Virtual machine type" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:123 +#: netbox/virtualization/forms/bulk_edit.py:121 #: netbox/virtualization/forms/bulk_import.py:118 #: netbox/virtualization/forms/filtersets.py:227 #: netbox/virtualization/tables/virtualmachines.py:70 msgid "Start on boot" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:172 +#: netbox/virtualization/forms/bulk_edit.py:170 #: netbox/virtualization/models/virtualmachines.py:205 msgid "vCPUs" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:180 +#: netbox/virtualization/forms/bulk_edit.py:178 #: netbox/virtualization/forms/model_forms.py:477 #: netbox/virtualization/tables/virtualmachines.py:118 msgid "Disk" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:190 +#: netbox/virtualization/forms/bulk_edit.py:188 #: netbox/virtualization/forms/model_forms.py:265 #: netbox/virtualization/ui/panels.py:62 msgid "Placement" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:207 +#: netbox/virtualization/forms/bulk_edit.py:205 #: netbox/virtualization/forms/model_forms.py:284 #, python-brace-format msgid "Memory ({unit})" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:208 +#: netbox/virtualization/forms/bulk_edit.py:206 #: netbox/virtualization/forms/model_forms.py:285 #, python-brace-format msgid "Disk ({unit})" msgstr "" -#: netbox/virtualization/forms/bulk_edit.py:381 +#: netbox/virtualization/forms/bulk_edit.py:372 #: netbox/virtualization/forms/filtersets.py:342 #: netbox/virtualization/forms/model_forms.py:490 #, python-brace-format From 523ecba867d19324ae8aad65cfebcbed64b787b6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 8 May 2026 03:35:46 -0400 Subject: [PATCH 021/131] Closes #22114: Split CI into conditional jobs (#22126) --- .github/workflows/ci.yml | 184 ++++++++++++++++++++++++++------------- 1 file changed, 124 insertions(+), 60 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db42fdd06..75bd254e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,14 +7,12 @@ on: - '.github/ISSUE_TEMPLATE/**' - '.github/PULL_REQUEST_TEMPLATE.md' - 'contrib/**' - - 'docs/**' - 'netbox/translations/**' pull_request: paths-ignore: - '.github/ISSUE_TEMPLATE/**' - '.github/PULL_REQUEST_TEMPLATE.md' - 'contrib/**' - - 'docs/**' - 'netbox/translations/**' permissions: @@ -26,22 +24,67 @@ concurrency: cancel-in-progress: true jobs: - build: + + # Detect which areas of the codebase changed so downstream jobs can be skipped + # when their inputs haven't changed. Jobs that don't match any filter are shown + # as "skipped" in GitHub's check list, which satisfies required-status-checks. + changes: + name: Detect changed files + runs-on: ubuntu-latest + outputs: + python: ${{ steps.filter.outputs.python }} + frontend: ${{ steps.filter.outputs.frontend }} + docs: ${{ steps.filter.outputs.docs }} + steps: + - name: Check out repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Detect changed files + uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 + id: filter + with: + filters: | + python: + - 'netbox/**/*.py' + - 'requirements*.txt' + - 'pyproject.toml' + frontend: + - 'netbox/project-static/**' + docs: + - 'docs/**' + - 'mkdocs.yml' + + lint: + name: Lint (Python) + needs: changes + if: needs.changes.result == 'success' && needs.changes.outputs.python == 'true' + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Check Python linting & PEP8 compliance + uses: astral-sh/ruff-action@0ce1b0bf8b818ef400413f810f8a11cdbda0034b # v4.0.0 + with: + version: "0.15.10" + args: "check --output-format=github" + src: "netbox/" + + test: name: >- - Tests (Python ${{ matrix.python-version }}, - Node ${{ matrix.node-version }}${{ matrix.coverage && ', coverage' || '' }}) + Tests (Python ${{ matrix.python-version }}${{ matrix.coverage && ', coverage' || '' }}) + needs: changes + if: needs.changes.result == 'success' && needs.changes.outputs.python == 'true' runs-on: ubuntu-latest env: NETBOX_CONFIGURATION: netbox.configuration_testing strategy: matrix: python-version: ['3.12', '3.13', '3.14'] - node-version: ['20.x'] include: - coverage: false # Run coverage only once, using the Python 3.14 job. - python-version: '3.14' - node-version: '20.x' coverage: true services: redis: @@ -62,72 +105,93 @@ jobs: - 5432:5432 steps: - - name: Check out repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Check out repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Check Python linting & PEP8 compliance - uses: astral-sh/ruff-action@0ce1b0bf8b818ef400413f810f8a11cdbda0034b # v4.0.0 - with: - version: "0.15.10" - args: "check --output-format=github" - src: "netbox/" + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: ${{ matrix.python-version }} - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install coverage tblib - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: ${{ matrix.node-version }} + - name: Check for missing migrations + run: python netbox/manage.py makemigrations --check - - name: Install Yarn Package Manager - run: npm install -g yarn + - name: Run tests + if: ${{ ! matrix.coverage }} + run: python netbox/manage.py test netbox/ --parallel - - name: Setup Node.js with Yarn Caching - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version: ${{ matrix.node-version }} - cache: yarn - cache-dependency-path: netbox/project-static/yarn.lock + - name: Run tests with coverage + if: ${{ matrix.coverage }} + run: coverage run netbox/manage.py test netbox/ --parallel - - name: Install Frontend Dependencies - run: yarn --cwd netbox/project-static + - name: Combine coverage data + if: ${{ matrix.coverage }} + run: coverage combine - - name: Install dependencies & set up configuration - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install coverage tblib + - name: Show coverage report + if: ${{ matrix.coverage }} + run: coverage report - - name: Build documentation - run: zensical build + frontend: + name: Frontend + needs: changes + if: needs.changes.result == 'success' && needs.changes.outputs.frontend == 'true' + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Collect static files - run: python netbox/manage.py collectstatic --no-input + - name: Use Node.js 20.x + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '20.x' - - name: Check for missing migrations - run: python netbox/manage.py makemigrations --check + - name: Install Yarn Package Manager + run: npm install -g yarn - - name: Check UI ESLint, TypeScript, and Prettier Compliance - run: yarn --cwd netbox/project-static validate + - name: Setup Node.js with Yarn Caching + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: '20.x' + cache: yarn + cache-dependency-path: netbox/project-static/yarn.lock - - name: Validate Static Asset Integrity - run: scripts/verify-bundles.sh + - name: Install Frontend Dependencies + run: yarn --cwd netbox/project-static - - name: Run tests - if: ${{ ! matrix.coverage }} - run: python netbox/manage.py test netbox/ --parallel + - name: Validate TypeScript and run ESLint + run: yarn --cwd netbox/project-static validate - - name: Run tests with coverage - if: ${{ matrix.coverage }} - run: coverage run netbox/manage.py test netbox/ --parallel + - name: Validate formatting + run: yarn --cwd netbox/project-static validate:formatting - - name: Combine coverage data - if: ${{ matrix.coverage }} - run: coverage combine + - name: Validate Static Asset Integrity + run: scripts/verify-bundles.sh - - name: Show coverage report - if: ${{ matrix.coverage }} - run: coverage report + docs: + name: Documentation + needs: changes + if: needs.changes.result == 'success' && needs.changes.outputs.docs == 'true' + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up Python 3.12 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.12' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Build documentation + run: zensical build From bf23a0b3fdff85d781d552a371f14146943e9a89 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Fri, 8 May 2026 04:59:44 -0700 Subject: [PATCH 022/131] Fixes #22055: Report API exceptions to Monitoring Services (#22106) Ensure CoreMiddleware emits Django's got_request_exception signal before returning handled 500 responses for API requests and custom error templates. This allows integrations such as Sentry to report exceptions that would otherwise be hidden when middleware returns a custom error response. --- netbox/netbox/middleware.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/netbox/netbox/middleware.py b/netbox/netbox/middleware.py index 45639dd4b..4a36c2d98 100644 --- a/netbox/netbox/middleware.py +++ b/netbox/netbox/middleware.py @@ -5,6 +5,7 @@ from django.conf import settings from django.contrib import auth, messages from django.contrib.auth.middleware import RemoteUserMiddleware as RemoteUserMiddleware_ from django.core.exceptions import ImproperlyConfigured +from django.core.signals import got_request_exception from django.db import ProgrammingError, connection from django.db.utils import InternalError from django.http import Http404, HttpResponseRedirect @@ -103,6 +104,9 @@ class CoreMiddleware: # Cleanly handle exceptions that occur from REST API requests if is_api_request(request): + # Fire Django's got_request_exception signal so error-tracking + # integrations (e.g. Sentry) capture the exception. + got_request_exception.send(sender=self.__class__, request=request) return handle_rest_api_exception(request) # Ignore Http404s (defer to Django's built-in 404 handling) @@ -120,6 +124,9 @@ class CoreMiddleware: # Return a custom error message, or fall back to Django's default 500 error handling if custom_template: + # Fire Django's got_request_exception signal so error-tracking + # integrations (e.g. Sentry) capture the exception. + got_request_exception.send(sender=self.__class__, request=request) return handler_500(request, template_name=custom_template) return None From cd56523cc53080d49f1a89eea94e6d809999cfd9 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Fri, 8 May 2026 14:00:20 +0200 Subject: [PATCH 023/131] chore(ci): Limit CI push trigger to main and feature Restrict the CI workflow's push trigger to the main and feature branches while preserving the existing paths-ignore filters. This avoids unnecessary push-triggered CI runs on topic branches without changing pull request workflow behavior. Fixes #19324 --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 75bd254e8..20955cbc2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,9 @@ name: CI on: push: + branches: + - main + - feature paths-ignore: - '.github/ISSUE_TEMPLATE/**' - '.github/PULL_REQUEST_TEMPLATE.md' From 3e4ad4a5da2f49ab6d538d963a2ed7efd83815b0 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Fri, 8 May 2026 23:55:17 +0200 Subject: [PATCH 024/131] chore(ci): Collect static files before running tests Copy frontend-generated files into STATIC_ROOT before tests run so SVG rendering tests can read their CSS directly. Also add pull-requests read permission to the workflow. Fixes #22150 --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20955cbc2..2a302f223 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,7 @@ on: permissions: contents: read + pull-requests: read # Add concurrency group to control job running concurrency: @@ -125,6 +126,11 @@ jobs: - name: Check for missing migrations run: python netbox/manage.py makemigrations --check + # Copy frontend-generated files into STATIC_ROOT before SVG rendering + # tests read their CSS directly. + - name: Collect static files + run: python netbox/manage.py collectstatic --no-input + - name: Run tests if: ${{ ! matrix.coverage }} run: python netbox/manage.py test netbox/ --parallel From da9568b5483aa939c6073b13293906fc541e6b27 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 8 May 2026 16:32:42 -0400 Subject: [PATCH 025/131] Closes #22061: Add prefetch hints for GraphQL types --- netbox/circuits/graphql/types.py | 4 +- netbox/dcim/graphql/types.py | 71 ++++++++++++++++++++------ netbox/extras/graphql/mixins.py | 21 ++++++-- netbox/ipam/graphql/types.py | 12 ++--- netbox/virtualization/graphql/types.py | 2 +- netbox/vpn/graphql/types.py | 2 +- netbox/wireless/graphql/types.py | 2 +- 7 files changed, 82 insertions(+), 32 deletions(-) diff --git a/netbox/circuits/graphql/types.py b/netbox/circuits/graphql/types.py index 29e7f8de3..d150d2b5c 100644 --- a/netbox/circuits/graphql/types.py +++ b/netbox/circuits/graphql/types.py @@ -74,7 +74,7 @@ class ProviderNetworkType(PrimaryObjectType): class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, ObjectType): circuit: Annotated['CircuitType', strawberry.lazy('circuits.graphql.types')] - @strawberry_django.field + @strawberry_django.field(prefetch_related='termination') def termination(self) -> Annotated[ Annotated['LocationType', strawberry.lazy('dcim.graphql.types')] | Annotated['RegionType', strawberry.lazy('dcim.graphql.types')] @@ -133,7 +133,7 @@ class CircuitGroupType(OrganizationalObjectType): class CircuitGroupAssignmentType(TagsMixin, BaseObjectType): group: Annotated['CircuitGroupType', strawberry.lazy('circuits.graphql.types')] - @strawberry_django.field + @strawberry_django.field(prefetch_related='member') def member(self) -> Annotated[ Annotated['CircuitType', strawberry.lazy('circuits.graphql.types')] | Annotated['VirtualCircuitType', strawberry.lazy('circuits.graphql.types')], diff --git a/netbox/dcim/graphql/types.py b/netbox/dcim/graphql/types.py index 6cbab28f2..6fc66af45 100644 --- a/netbox/dcim/graphql/types.py +++ b/netbox/dcim/graphql/types.py @@ -4,6 +4,7 @@ import strawberry import strawberry_django from django.db.models import Func, IntegerField +from circuits.models import CircuitTermination from core.graphql.mixins import ChangelogMixin from dcim import models from extras.graphql.mixins import ConfigContextMixin, ContactsMixin, ImageAttachmentsMixin @@ -17,6 +18,8 @@ from netbox.graphql.types import ( PrimaryObjectType, ) from users.graphql.mixins import OwnerMixin +from utilities.querysets import RestrictedPrefetch +from virtualization.models import Cluster from .filters import * from .mixins import CabledObjectMixin, PathEndpointMixin @@ -288,11 +291,11 @@ class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, Prima inventoryitems: list[Annotated["InventoryItemType", strawberry.lazy('dcim.graphql.types')]] vdcs: list[Annotated["VirtualDeviceContextType", strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='vc_master_for') def vc_master_for(self) -> Annotated["VirtualChassisType", strawberry.lazy('dcim.graphql.types')] | None: return self.vc_master_for if hasattr(self, 'vc_master_for') else None - @strawberry_django.field + @strawberry_django.field(prefetch_related='parent_bay') def parent_bay(self) -> Annotated["DeviceBayType", strawberry.lazy('dcim.graphql.types')] | None: return self.parent_bay if hasattr(self, 'parent_bay') else None @@ -327,7 +330,7 @@ class InventoryItemTemplateType(ComponentTemplateType): role: Annotated['InventoryItemRoleType', strawberry.lazy('dcim.graphql.types')] | None manufacturer: Annotated['ManufacturerType', strawberry.lazy('dcim.graphql.types')] - @strawberry_django.field + @strawberry_django.field(prefetch_related='parent') def parent(self) -> Annotated['InventoryItemTemplateType', strawberry.lazy('dcim.graphql.types')] | None: return self.parent @@ -430,7 +433,7 @@ class FrontPortTemplateType(ModularComponentTemplateType): class MACAddressType(PrimaryObjectType): mac_address: str - @strawberry_django.field + @strawberry_django.field(prefetch_related='assigned_object') def assigned_object(self) -> Annotated[ Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] | Annotated['VMInterfaceType', strawberry.lazy('virtualization.graphql.types')], @@ -494,7 +497,7 @@ class InventoryItemType(ComponentType): child_items: list[Annotated['InventoryItemType', strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='parent') def parent(self) -> Annotated['InventoryItemType', strawberry.lazy('dcim.graphql.types')] | None: return self.parent @@ -541,11 +544,20 @@ class LocationType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, Nested devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] children: list[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() + ), + ) def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: return self.cluster_set.all() - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'circuit_terminations', info.context.request.user, 'view', + queryset=CircuitTermination.objects.all() + ), + ) def circuit_terminations(self) -> list[ Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] ]: @@ -599,7 +611,7 @@ class ModuleBayType(ModularComponentType): installed_module: Annotated["ModuleType", strawberry.lazy('dcim.graphql.types')] | None children: list[Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='parent') def parent(self) -> Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')] | None: return self.parent @@ -864,15 +876,24 @@ class RegionType(VLANGroupsMixin, ContactsMixin, NestedGroupObjectType): sites: list[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]] children: list[Annotated["RegionType", strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='parent') def parent(self) -> Annotated["RegionType", strawberry.lazy('dcim.graphql.types')] | None: return self.parent - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() + ), + ) def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: return self.cluster_set.all() - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'circuit_terminations', info.context.request.user, 'view', + queryset=CircuitTermination.objects.all() + ), + ) def circuit_terminations(self) -> list[ Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] ]: @@ -903,11 +924,20 @@ class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, PrimaryObj clusters: list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]] vlans: list[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]] - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() + ), + ) def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: return self.cluster_set.all() - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'circuit_terminations', info.context.request.user, 'view', + queryset=CircuitTermination.objects.all() + ), + ) def circuit_terminations(self) -> list[ Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] ]: @@ -925,15 +955,24 @@ class SiteGroupType(VLANGroupsMixin, ContactsMixin, NestedGroupObjectType): sites: list[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]] children: list[Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='parent') def parent(self) -> Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')] | None: return self.parent - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'cluster_set', info.context.request.user, 'view', queryset=Cluster.objects.all() + ), + ) def clusters(self) -> list[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: return self.cluster_set.all() - @strawberry_django.field + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'circuit_terminations', info.context.request.user, 'view', + queryset=CircuitTermination.objects.all() + ), + ) def circuit_terminations(self) -> list[ Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] ]: diff --git a/netbox/extras/graphql/mixins.py b/netbox/extras/graphql/mixins.py index 96f9719a3..3a958d8bc 100644 --- a/netbox/extras/graphql/mixins.py +++ b/netbox/extras/graphql/mixins.py @@ -4,6 +4,9 @@ import strawberry import strawberry_django from strawberry.types import Info +from extras.models import ImageAttachment, JournalEntry +from utilities.querysets import RestrictedPrefetch + __all__ = ( 'ConfigContextMixin', 'ContactsMixin', @@ -50,16 +53,24 @@ class CustomFieldsMixin: @strawberry.type class ImageAttachmentsMixin: - @strawberry_django.field - def image_attachments(self, info: Info) -> list[Annotated['ImageAttachmentType', strawberry.lazy('.types')]]: - return self.images.restrict(info.context.request.user, 'view') + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'images', info.context.request.user, 'view', queryset=ImageAttachment.objects.all() + ), + ) + def image_attachments(self) -> list[Annotated['ImageAttachmentType', strawberry.lazy('.types')]]: + return self.images.all() @strawberry.type class JournalEntriesMixin: - @strawberry_django.field - def journal_entries(self, info: Info) -> list[Annotated['JournalEntryType', strawberry.lazy('.types')]]: + @strawberry_django.field( + prefetch_related=lambda info: RestrictedPrefetch( + 'journal_entries', info.context.request.user, 'view', queryset=JournalEntry.objects.all() + ), + ) + def journal_entries(self) -> list[Annotated['JournalEntryType', strawberry.lazy('.types')]]: return self.journal_entries.all() diff --git a/netbox/ipam/graphql/types.py b/netbox/ipam/graphql/types.py index 2bfdc7d65..31b93b419 100644 --- a/netbox/ipam/graphql/types.py +++ b/netbox/ipam/graphql/types.py @@ -128,7 +128,7 @@ class FHRPGroupType(IPAddressesMixin, PrimaryObjectType): class FHRPGroupAssignmentType(BaseObjectType): group: Annotated['FHRPGroupType', strawberry.lazy('ipam.graphql.types')] - @strawberry_django.field + @strawberry_django.field(prefetch_related='interface') def interface(self) -> Annotated[ Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] | Annotated['VMInterfaceType', strawberry.lazy('virtualization.graphql.types')], @@ -153,7 +153,7 @@ class IPAddressType(ContactsMixin, BaseIPAddressFamilyType, PrimaryObjectType): tunnel_terminations: list[Annotated['TunnelTerminationType', strawberry.lazy('vpn.graphql.types')]] services: list[Annotated['ServiceType', strawberry.lazy('ipam.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='assigned_object') def assigned_object(self) -> Annotated[ Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] | Annotated['FHRPGroupType', strawberry.lazy('ipam.graphql.types')] @@ -190,7 +190,7 @@ class PrefixType(ContactsMixin, BaseIPAddressFamilyType, PrimaryObjectType): vlan: Annotated['VLANType', strawberry.lazy('ipam.graphql.types')] | None role: Annotated['RoleType', strawberry.lazy('ipam.graphql.types')] | None - @strawberry_django.field + @strawberry_django.field(prefetch_related='scope') def scope(self) -> Annotated[ Annotated['LocationType', strawberry.lazy('dcim.graphql.types')] | Annotated['RegionType', strawberry.lazy('dcim.graphql.types')] @@ -252,7 +252,7 @@ class ServiceType(ContactsMixin, PrimaryObjectType): ports: list[int] ipaddresses: list[Annotated['IPAddressType', strawberry.lazy('ipam.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='parent') def parent(self) -> Annotated[ Annotated['DeviceType', strawberry.lazy('dcim.graphql.types')] | Annotated['VirtualMachineType', strawberry.lazy('virtualization.graphql.types')] @@ -291,7 +291,7 @@ class VLANType(PrimaryObjectType): interfaces_as_tagged: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] vminterfaces_as_tagged: list[Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='qinq_svlan') def qinq_svlan(self) -> Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None: return self.qinq_svlan @@ -309,7 +309,7 @@ class VLANGroupType(OrganizationalObjectType): total_vlan_ids: BigInt tenant: Annotated['TenantType', strawberry.lazy('tenancy.graphql.types')] | None - @strawberry_django.field + @strawberry_django.field(prefetch_related='scope') def scope(self) -> Annotated[ Annotated['ClusterType', strawberry.lazy('virtualization.graphql.types')] | Annotated['ClusterGroupType', strawberry.lazy('virtualization.graphql.types')] diff --git a/netbox/virtualization/graphql/types.py b/netbox/virtualization/graphql/types.py index 96563aac8..81ef685a1 100644 --- a/netbox/virtualization/graphql/types.py +++ b/netbox/virtualization/graphql/types.py @@ -59,7 +59,7 @@ class ClusterType(ContactsMixin, VLANGroupsMixin, PrimaryObjectType): virtual_machines: list[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]] devices: list[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='scope') def scope(self) -> Annotated[ Annotated['LocationType', strawberry.lazy('dcim.graphql.types')] | Annotated['RegionType', strawberry.lazy('dcim.graphql.types')] diff --git a/netbox/vpn/graphql/types.py b/netbox/vpn/graphql/types.py index d23c0a13b..40f125e83 100644 --- a/netbox/vpn/graphql/types.py +++ b/netbox/vpn/graphql/types.py @@ -145,7 +145,7 @@ class L2VPNType(ContactsMixin, PrimaryObjectType): class L2VPNTerminationType(NetBoxObjectType): l2vpn: Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')] - @strawberry_django.field + @strawberry_django.field(prefetch_related='assigned_object') def assigned_object(self) -> Annotated[ Annotated['InterfaceType', strawberry.lazy('dcim.graphql.types')] | Annotated['VLANType', strawberry.lazy('ipam.graphql.types')] diff --git a/netbox/wireless/graphql/types.py b/netbox/wireless/graphql/types.py index 2e7930074..557f32ce4 100644 --- a/netbox/wireless/graphql/types.py +++ b/netbox/wireless/graphql/types.py @@ -46,7 +46,7 @@ class WirelessLANType(PrimaryObjectType): interfaces: list[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] - @strawberry_django.field + @strawberry_django.field(prefetch_related='scope') def scope(self) -> Annotated[ Annotated['LocationType', strawberry.lazy('dcim.graphql.types')] | Annotated['RegionType', strawberry.lazy('dcim.graphql.types')] From 2e9c3119cecdbaa6fd03eed52cebd8b0a51e469f Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 11 May 2026 13:54:07 -0400 Subject: [PATCH 026/131] Closes #22060: Introduce a config parameter to enforce GraphQL maximum query depth (#22162) --- docs/best-practices/performance-handbook.md | 4 ++ docs/configuration/graphql-api.md | 10 +++++ netbox/netbox/graphql/schema.py | 18 ++++++--- netbox/netbox/settings.py | 1 + netbox/netbox/tests/test_graphql.py | 44 +++++++++++++++++++++ 5 files changed, 72 insertions(+), 5 deletions(-) diff --git a/docs/best-practices/performance-handbook.md b/docs/best-practices/performance-handbook.md index 9703a08cd..f4e7b8af5 100644 --- a/docs/best-practices/performance-handbook.md +++ b/docs/best-practices/performance-handbook.md @@ -40,6 +40,10 @@ NetBox paginates large result sets to reduce the overall response size. The [`MA By default, NetBox restricts a GraphQL query to 10 aliases. Consider reducing this number by setting [`GRAPHQL_MAX_ALIASES`](../configuration/graphql-api.md#graphql_max_aliases) to a lower value. +#### Limit GraphQL Query Depth + +Deeply nested GraphQL queries can impose substantial overhead, consuming undue server resources and increasing response times. Consider setting [`GRAPHQL_MAX_QUERY_DEPTH`](../configuration/graphql-api.md#graphql_max_query_depth) to limit the maximum nesting depth for any GraphQL query. + #### Designate Isolated Deployments If your NetBox installation does not have Internet access, set [`ISOLATED_DEPLOYMENT`](../configuration/system.md#isolated_deployment) to True. This will prevent the application from attempting routine external requests. diff --git a/docs/configuration/graphql-api.md b/docs/configuration/graphql-api.md index e58bb0576..3fed0482b 100644 --- a/docs/configuration/graphql-api.md +++ b/docs/configuration/graphql-api.md @@ -25,3 +25,13 @@ Setting this to `False` will disable the GraphQL API. Default: `10` The maximum number of queries that a GraphQL API request may contain. + +--- + +## GRAPHQL_MAX_QUERY_DEPTH + +!!! note "This parameter was introduced in NetBox v4.6.1." + +Default: `None` (no limit) + +The maximum allowed depth of any GraphQL query. When set to a positive integer, requests containing queries that exceed this depth will be rejected. Leaving this parameter unset (or setting it to `None` or `0`) disables query depth enforcement. diff --git a/netbox/netbox/graphql/schema.py b/netbox/netbox/graphql/schema.py index 5fb27bf4e..1cce4a7dc 100644 --- a/netbox/netbox/graphql/schema.py +++ b/netbox/netbox/graphql/schema.py @@ -1,6 +1,6 @@ import strawberry from django.conf import settings -from strawberry.extensions import MaxAliasesLimiter +from strawberry.extensions import MaxAliasesLimiter, QueryDepthLimiter, SchemaExtension from strawberry.schema.config import StrawberryConfig from strawberry_django.optimizer import DjangoOptimizerExtension @@ -36,6 +36,17 @@ class Query( pass +def get_schema_extensions() -> list[SchemaExtension]: + extensions: list[SchemaExtension] = [ + DjangoOptimizerExtension(prefetch_custom_queryset=True), + MaxAliasesLimiter(max_alias_count=settings.GRAPHQL_MAX_ALIASES), + ] + max_depth = settings.GRAPHQL_MAX_QUERY_DEPTH + if max_depth and max_depth > 0: + extensions.append(QueryDepthLimiter(max_depth=max_depth)) + return extensions + + schema = strawberry.Schema( query=Query, config=StrawberryConfig( @@ -44,8 +55,5 @@ schema = strawberry.Schema( BigInt: BigIntScalar, }, ), - extensions=[ - DjangoOptimizerExtension(prefetch_custom_queryset=True), - MaxAliasesLimiter(max_alias_count=settings.GRAPHQL_MAX_ALIASES), - ], + extensions=get_schema_extensions(), ) diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 33631f943..ddfe558ea 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -130,6 +130,7 @@ FIELD_CHOICES = getattr(configuration, 'FIELD_CHOICES', {}) FILE_UPLOAD_MAX_MEMORY_SIZE = getattr(configuration, 'FILE_UPLOAD_MAX_MEMORY_SIZE', 2621440) GRAPHQL_DEFAULT_VERSION = getattr(configuration, 'GRAPHQL_DEFAULT_VERSION', 1) GRAPHQL_MAX_ALIASES = getattr(configuration, 'GRAPHQL_MAX_ALIASES', 10) +GRAPHQL_MAX_QUERY_DEPTH = getattr(configuration, 'GRAPHQL_MAX_QUERY_DEPTH', None) HOSTNAME = getattr(configuration, 'HOSTNAME', platform.node()) HTTP_PROXIES = getattr(configuration, 'HTTP_PROXIES', {}) INTERNAL_IPS = getattr(configuration, 'INTERNAL_IPS', ('127.0.0.1', '::1')) diff --git a/netbox/netbox/tests/test_graphql.py b/netbox/netbox/tests/test_graphql.py index 3914a9493..573578e7a 100644 --- a/netbox/netbox/tests/test_graphql.py +++ b/netbox/netbox/tests/test_graphql.py @@ -1,11 +1,16 @@ import json +import strawberry from django.test import override_settings from django.urls import reverse from rest_framework import status +from strawberry.extensions import QueryDepthLimiter +from strawberry.schema.config import StrawberryConfig from dcim.choices import LocationStatusChoices from dcim.models import Device, DeviceRole, DeviceType, Location, Manufacturer, Site, VirtualChassis +from netbox.graphql.scalars import BigInt, BigIntScalar +from netbox.graphql.schema import Query, get_schema_extensions from utilities.testing import APITestCase, TestCase, disable_warnings @@ -20,6 +25,45 @@ class GraphQLTestCase(TestCase): response = self.client.get(url) self.assertHttpStatus(response, 404) + def test_graphql_max_query_depth_disabled_by_default(self): + """ + QueryDepthLimiter should not be installed when GRAPHQL_MAX_QUERY_DEPTH is unset. + """ + self.assertFalse(any(isinstance(ext, QueryDepthLimiter) for ext in get_schema_extensions())) + + @override_settings(GRAPHQL_MAX_QUERY_DEPTH=0) + def test_graphql_max_query_depth_disabled_when_zero(self): + """ + QueryDepthLimiter should not be installed when GRAPHQL_MAX_QUERY_DEPTH is zero. + """ + self.assertFalse(any(isinstance(ext, QueryDepthLimiter) for ext in get_schema_extensions())) + + @override_settings(GRAPHQL_MAX_QUERY_DEPTH=-1) + def test_graphql_max_query_depth_disabled_when_negative(self): + """ + QueryDepthLimiter should not be installed when GRAPHQL_MAX_QUERY_DEPTH is negative. + """ + self.assertFalse(any(isinstance(ext, QueryDepthLimiter) for ext in get_schema_extensions())) + + @override_settings(GRAPHQL_MAX_QUERY_DEPTH=3) + def test_graphql_max_query_depth_enforced(self): + """ + Queries exceeding GRAPHQL_MAX_QUERY_DEPTH should be rejected. + """ + extensions = get_schema_extensions() + self.assertTrue(any(isinstance(ext, QueryDepthLimiter) for ext in extensions)) + + # Build a temporary schema with the configured extensions and execute a deep query + test_schema = strawberry.Schema( + query=Query, + config=StrawberryConfig(auto_camel_case=False, scalar_map={BigInt: BigIntScalar}), + extensions=extensions, + ) + deep_query = '{ site_list { tenant { group { parent { parent { parent { name } } } } } } }' + result = test_schema.execute_sync(deep_query) + self.assertIsNotNone(result.errors) + self.assertIn('exceeds maximum operation depth', str(result.errors[0])) + @override_settings(LOGIN_REQUIRED=True) def test_graphiql_interface(self): """ From 963306f338f7f7bc74c30f43a5d75bf48cc495d9 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Mon, 11 May 2026 18:17:01 +0200 Subject: [PATCH 027/131] refactor(tests): Standardize test class naming to TestCase suffix Rename all test classes from `*Test` to `*TestCase` for consistency with Django conventions. Fixes #22097 --- netbox/circuits/tests/test_api.py | 24 ++--- netbox/circuits/tests/test_tables.py | 22 ++--- netbox/core/tests/test_api.py | 8 +- netbox/core/tests/test_changelog.py | 6 +- netbox/core/tests/test_data_backends.py | 4 +- netbox/core/tests/test_models.py | 4 +- netbox/core/tests/test_tables.py | 10 +- netbox/dcim/tests/test_api.py | 96 +++++++++---------- netbox/dcim/tests/test_cable_profiles.py | 4 +- netbox/dcim/tests/test_cablepaths.py | 2 +- netbox/dcim/tests/test_cablepaths2.py | 2 +- netbox/dcim/tests/test_tables.py | 72 +++++++------- netbox/extras/tests/test_api.py | 44 ++++----- netbox/extras/tests/test_conditions.py | 2 +- netbox/extras/tests/test_custom_validation.py | 8 +- netbox/extras/tests/test_customfields.py | 12 +-- netbox/extras/tests/test_customvalidators.py | 6 +- netbox/extras/tests/test_dashboard.py | 2 +- netbox/extras/tests/test_event_rules.py | 2 +- netbox/extras/tests/test_forms.py | 6 +- netbox/extras/tests/test_models.py | 14 +-- netbox/extras/tests/test_scripts.py | 2 +- netbox/extras/tests/test_tables.py | 36 +++---- netbox/extras/tests/test_tags.py | 2 +- netbox/extras/tests/test_utils.py | 4 +- netbox/extras/tests/test_views.py | 52 +++++----- netbox/ipam/tests/test_api.py | 38 ++++---- netbox/ipam/tests/test_lookups.py | 2 +- netbox/ipam/tests/test_tables.py | 38 ++++---- netbox/netbox/tests/test_api.py | 4 +- netbox/netbox/tests/test_forms.py | 2 +- netbox/netbox/tests/test_jobs.py | 6 +- netbox/netbox/tests/test_models.py | 2 +- netbox/netbox/tests/test_object_actions.py | 2 +- netbox/netbox/tests/test_plugins.py | 4 +- netbox/netbox/tests/test_registry.py | 2 +- netbox/netbox/tests/test_tables.py | 4 +- netbox/netbox/tests/test_ui.py | 22 ++--- netbox/tenancy/tests/test_api.py | 14 +-- netbox/tenancy/tests/test_tables.py | 12 +-- netbox/users/tests/test_api.py | 16 ++-- netbox/users/tests/test_models.py | 4 +- netbox/users/tests/test_preferences.py | 2 +- netbox/users/tests/test_tables.py | 12 +-- netbox/utilities/tests/test_api.py | 2 +- netbox/utilities/tests/test_conversions.py | 2 +- netbox/utilities/tests/test_counters.py | 2 +- .../utilities/tests/test_filter_modifiers.py | 10 +- netbox/utilities/tests/test_filters.py | 6 +- netbox/utilities/tests/test_forms.py | 12 +-- netbox/utilities/tests/test_managers.py | 2 +- netbox/utilities/tests/test_permissions.py | 6 +- netbox/utilities/tests/test_prefetch.py | 2 +- netbox/utilities/tests/test_request.py | 4 +- netbox/utilities/tests/test_templatetags.py | 10 +- netbox/utilities/tests/test_utils.py | 6 +- netbox/virtualization/tests/test_api.py | 16 ++-- netbox/virtualization/tests/test_tables.py | 12 +-- netbox/vpn/tests/test_api.py | 22 ++--- netbox/vpn/tests/test_tables.py | 20 ++-- netbox/wireless/tests/test_api.py | 8 +- netbox/wireless/tests/test_tables.py | 6 +- 62 files changed, 390 insertions(+), 390 deletions(-) diff --git a/netbox/circuits/tests/test_api.py b/netbox/circuits/tests/test_api.py index 3b8280236..81d609847 100644 --- a/netbox/circuits/tests/test_api.py +++ b/netbox/circuits/tests/test_api.py @@ -8,7 +8,7 @@ from ipam.models import ASN, RIR from utilities.testing import APITestCase, APIViewTestCases -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): url = reverse('circuits-api:api-root') @@ -17,7 +17,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class ProviderTest(APIViewTestCases.APIViewTestCase): +class ProviderTestCase(APIViewTestCases.APIViewTestCase): model = Provider brief_fields = ['circuit_count', 'description', 'display', 'id', 'name', 'slug', 'url'] bulk_update_data = { @@ -59,7 +59,7 @@ class ProviderTest(APIViewTestCases.APIViewTestCase): ] -class CircuitTypeTest(APIViewTestCases.APIViewTestCase): +class CircuitTypeTestCase(APIViewTestCases.APIViewTestCase): model = CircuitType brief_fields = ['circuit_count', 'description', 'display', 'id', 'name', 'slug', 'url'] create_data = ( @@ -91,7 +91,7 @@ class CircuitTypeTest(APIViewTestCases.APIViewTestCase): CircuitType.objects.bulk_create(circuit_types) -class CircuitTest(APIViewTestCases.APIViewTestCase): +class CircuitTestCase(APIViewTestCases.APIViewTestCase): model = Circuit brief_fields = ['cid', 'description', 'display', 'id', 'provider', 'url'] bulk_update_data = { @@ -155,7 +155,7 @@ class CircuitTest(APIViewTestCases.APIViewTestCase): ] -class CircuitTerminationTest(APIViewTestCases.APIViewTestCase): +class CircuitTerminationTestCase(APIViewTestCases.APIViewTestCase): model = CircuitTermination brief_fields = ['_occupied', 'cable', 'circuit', 'description', 'display', 'id', 'term_side', 'url'] user_permissions = ('circuits.view_circuit', ) @@ -217,7 +217,7 @@ class CircuitTerminationTest(APIViewTestCases.APIViewTestCase): } -class CircuitGroupTest(APIViewTestCases.APIViewTestCase): +class CircuitGroupTestCase(APIViewTestCases.APIViewTestCase): model = CircuitGroup brief_fields = ['display', 'id', 'name', 'url'] bulk_update_data = { @@ -249,7 +249,7 @@ class CircuitGroupTest(APIViewTestCases.APIViewTestCase): ] -class ProviderAccountTest(APIViewTestCases.APIViewTestCase): +class ProviderAccountTestCase(APIViewTestCases.APIViewTestCase): model = ProviderAccount brief_fields = ['account', 'description', 'display', 'id', 'name', 'url'] user_permissions = ('circuits.view_provider',) @@ -293,7 +293,7 @@ class ProviderAccountTest(APIViewTestCases.APIViewTestCase): } -class CircuitGroupAssignmentTest(APIViewTestCases.APIViewTestCase): +class CircuitGroupAssignmentTestCase(APIViewTestCases.APIViewTestCase): model = CircuitGroupAssignment brief_fields = ['display', 'group', 'id', 'member', 'member_id', 'member_type', 'priority', 'url'] bulk_update_data = { @@ -368,7 +368,7 @@ class CircuitGroupAssignmentTest(APIViewTestCases.APIViewTestCase): ] -class ProviderNetworkTest(APIViewTestCases.APIViewTestCase): +class ProviderNetworkTestCase(APIViewTestCases.APIViewTestCase): model = ProviderNetwork brief_fields = ['description', 'display', 'id', 'name', 'url'] user_permissions = ('circuits.view_provider', ) @@ -409,7 +409,7 @@ class ProviderNetworkTest(APIViewTestCases.APIViewTestCase): } -class VirtualCircuitTypeTest(APIViewTestCases.APIViewTestCase): +class VirtualCircuitTypeTestCase(APIViewTestCases.APIViewTestCase): model = VirtualCircuitType brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url', 'virtual_circuit_count'] create_data = ( @@ -441,7 +441,7 @@ class VirtualCircuitTypeTest(APIViewTestCases.APIViewTestCase): VirtualCircuitType.objects.bulk_create(virtual_circuit_types) -class VirtualCircuitTest(APIViewTestCases.APIViewTestCase): +class VirtualCircuitTestCase(APIViewTestCases.APIViewTestCase): model = VirtualCircuit brief_fields = ['cid', 'description', 'display', 'id', 'provider_network', 'url'] bulk_update_data = { @@ -505,7 +505,7 @@ class VirtualCircuitTest(APIViewTestCases.APIViewTestCase): ] -class VirtualCircuitTerminationTest(APIViewTestCases.APIViewTestCase): +class VirtualCircuitTerminationTestCase(APIViewTestCases.APIViewTestCase): model = VirtualCircuitTermination brief_fields = ['description', 'display', 'id', 'interface', 'role', 'url', 'virtual_circuit'] bulk_update_data = { diff --git a/netbox/circuits/tests/test_tables.py b/netbox/circuits/tests/test_tables.py index 29c104d03..40b09a0d9 100644 --- a/netbox/circuits/tests/test_tables.py +++ b/netbox/circuits/tests/test_tables.py @@ -2,45 +2,45 @@ from circuits.tables import * from utilities.testing import TableTestCases -class CircuitTypeTableTest(TableTestCases.StandardTableTestCase): +class CircuitTypeTableTestCase(TableTestCases.StandardTableTestCase): table = CircuitTypeTable -class CircuitTableTest(TableTestCases.StandardTableTestCase): +class CircuitTableTestCase(TableTestCases.StandardTableTestCase): table = CircuitTable -class CircuitTerminationTableTest(TableTestCases.StandardTableTestCase): +class CircuitTerminationTableTestCase(TableTestCases.StandardTableTestCase): table = CircuitTerminationTable -class CircuitGroupTableTest(TableTestCases.StandardTableTestCase): +class CircuitGroupTableTestCase(TableTestCases.StandardTableTestCase): table = CircuitGroupTable -class CircuitGroupAssignmentTableTest(TableTestCases.StandardTableTestCase): +class CircuitGroupAssignmentTableTestCase(TableTestCases.StandardTableTestCase): table = CircuitGroupAssignmentTable -class ProviderTableTest(TableTestCases.StandardTableTestCase): +class ProviderTableTestCase(TableTestCases.StandardTableTestCase): table = ProviderTable -class ProviderAccountTableTest(TableTestCases.StandardTableTestCase): +class ProviderAccountTableTestCase(TableTestCases.StandardTableTestCase): table = ProviderAccountTable -class ProviderNetworkTableTest(TableTestCases.StandardTableTestCase): +class ProviderNetworkTableTestCase(TableTestCases.StandardTableTestCase): table = ProviderNetworkTable -class VirtualCircuitTypeTableTest(TableTestCases.StandardTableTestCase): +class VirtualCircuitTypeTableTestCase(TableTestCases.StandardTableTestCase): table = VirtualCircuitTypeTable -class VirtualCircuitTableTest(TableTestCases.StandardTableTestCase): +class VirtualCircuitTableTestCase(TableTestCases.StandardTableTestCase): table = VirtualCircuitTable -class VirtualCircuitTerminationTableTest(TableTestCases.StandardTableTestCase): +class VirtualCircuitTerminationTableTestCase(TableTestCases.StandardTableTestCase): table = VirtualCircuitTerminationTable diff --git a/netbox/core/tests/test_api.py b/netbox/core/tests/test_api.py index 3d1857481..4e8292899 100644 --- a/netbox/core/tests/test_api.py +++ b/netbox/core/tests/test_api.py @@ -17,7 +17,7 @@ from utilities.testing.utils import disable_logging from ..models import * -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): url = reverse('core-api:api-root') @@ -26,7 +26,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class DataSourceTest(APIViewTestCases.APIViewTestCase): +class DataSourceTestCase(APIViewTestCases.APIViewTestCase): model = DataSource brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -62,7 +62,7 @@ class DataSourceTest(APIViewTestCases.APIViewTestCase): ] -class DataFileTest( +class DataFileTestCase( APIViewTestCases.GetObjectViewTestCase, APIViewTestCases.ListObjectsViewTestCase, APIViewTestCases.GraphQLTestCase @@ -105,7 +105,7 @@ class DataFileTest( DataFile.objects.bulk_create(data_files) -class ObjectTypeTest(APITestCase): +class ObjectTypeTestCase(APITestCase): def test_list_objects(self): object_type_count = ObjectType.objects.count() diff --git a/netbox/core/tests/test_changelog.py b/netbox/core/tests/test_changelog.py index dc9dbb2dc..0d00972b9 100644 --- a/netbox/core/tests/test_changelog.py +++ b/netbox/core/tests/test_changelog.py @@ -33,7 +33,7 @@ from utilities.testing.utils import create_tags, create_test_device, post_data from utilities.testing.views import ModelViewTestCase -class ChangeLogViewTest(ModelViewTestCase): +class ChangeLogViewTestCase(ModelViewTestCase): model = Site @classmethod @@ -397,7 +397,7 @@ class ChangeLogViewTest(ModelViewTestCase): self.assertEqual(objectchanges.count(), 2) -class ChangeLogAPITest(APITestCase): +class ChangeLogAPITestCase(APITestCase): @classmethod def setUpTestData(cls): @@ -703,7 +703,7 @@ class ChangeLogAPITest(APITestCase): self.assertEqual(changes[3].action, ObjectChangeActionChoices.ACTION_DELETE) -class ChangelogPruneRetentionTest(TestCase): +class ChangelogPruneRetentionTestCase(TestCase): """Test suite for Changelog pruning retention settings.""" @staticmethod diff --git a/netbox/core/tests/test_data_backends.py b/netbox/core/tests/test_data_backends.py index 8020eb76c..51cae6231 100644 --- a/netbox/core/tests/test_data_backends.py +++ b/netbox/core/tests/test_data_backends.py @@ -12,7 +12,7 @@ except ImportError: DULWICH_AVAILABLE = False -class URLEmbeddedCredentialsTests(TestCase): +class URLEmbeddedCredentialsTestCase(TestCase): def test_url_with_embedded_username(self): self.assertTrue(url_has_embedded_credentials('https://myuser@bitbucket.org/workspace/repo.git')) @@ -54,7 +54,7 @@ class URLEmbeddedCredentialsTests(TestCase): @skipIf(not DULWICH_AVAILABLE, "dulwich is not installed") -class GitBackendCredentialIntegrationTests(TestCase): +class GitBackendCredentialIntegrationTestCase(TestCase): """ Integration tests that verify GitBackend correctly applies credential logic. diff --git a/netbox/core/tests/test_models.py b/netbox/core/tests/test_models.py index af342324f..0b6de44c5 100644 --- a/netbox/core/tests/test_models.py +++ b/netbox/core/tests/test_models.py @@ -150,7 +150,7 @@ class DataSourceChangeLoggingTestCase(TestCase): self.assertEqual(objectchange.postchange_data['parameters']['password'], CENSOR_TOKEN) -class ObjectTypeTest(TestCase): +class ObjectTypeTestCase(TestCase): def test_create(self): """ @@ -227,7 +227,7 @@ class ObjectTypeTest(TestCase): self.assertNotIn(ObjectType.objects.get_by_natural_key('dcim', 'cabletermination'), bookmarks_ots) -class JobTest(TestCase): +class JobTestCase(TestCase): def _make_job(self, user, notifications): """ diff --git a/netbox/core/tests/test_tables.py b/netbox/core/tests/test_tables.py index ca28f1830..c938fd057 100644 --- a/netbox/core/tests/test_tables.py +++ b/netbox/core/tests/test_tables.py @@ -3,24 +3,24 @@ from core.tables import * from utilities.testing import TableTestCases -class DataSourceTableTest(TableTestCases.StandardTableTestCase): +class DataSourceTableTestCase(TableTestCases.StandardTableTestCase): table = DataSourceTable -class DataFileTableTest(TableTestCases.StandardTableTestCase): +class DataFileTableTestCase(TableTestCases.StandardTableTestCase): table = DataFileTable -class JobTableTest(TableTestCases.StandardTableTestCase): +class JobTableTestCase(TableTestCases.StandardTableTestCase): table = JobTable -class ObjectChangeTableTest(TableTestCases.StandardTableTestCase): +class ObjectChangeTableTestCase(TableTestCases.StandardTableTestCase): table = ObjectChangeTable queryset_sources = [ ('ObjectChangeListView', ObjectChange.objects.all()), ] -class ConfigRevisionTableTest(TableTestCases.StandardTableTestCase): +class ConfigRevisionTableTestCase(TableTestCases.StandardTableTestCase): table = ConfigRevisionTable diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index 16edb205d..be93b0453 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -29,7 +29,7 @@ from wireless.choices import WirelessChannelChoices from wireless.models import WirelessLAN -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): @@ -76,7 +76,7 @@ class Mixins: self.assertEqual(segment1[2][0]['name'], peer_obj.name) -class RegionTest(APIViewTestCases.APIViewTestCase): +class RegionTestCase(APIViewTestCases.APIViewTestCase): model = Region brief_fields = ['_depth', 'description', 'display', 'id', 'name', 'site_count', 'slug', 'url'] create_data = [ @@ -107,7 +107,7 @@ class RegionTest(APIViewTestCases.APIViewTestCase): Region.objects.create(name='Region 3', slug='region-3') -class SiteGroupTest(APIViewTestCases.APIViewTestCase): +class SiteGroupTestCase(APIViewTestCases.APIViewTestCase): model = SiteGroup brief_fields = ['_depth', 'description', 'display', 'id', 'name', 'site_count', 'slug', 'url'] create_data = [ @@ -140,7 +140,7 @@ class SiteGroupTest(APIViewTestCases.APIViewTestCase): SiteGroup.objects.create(name='Site Group 3', slug='site-group-3', comments='Hi!') -class SiteTest(APIViewTestCases.APIViewTestCase): +class SiteTestCase(APIViewTestCases.APIViewTestCase): model = Site brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url'] bulk_update_data = { @@ -420,7 +420,7 @@ class SiteTest(APIViewTestCases.APIViewTestCase): self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) -class LocationTest(APIViewTestCases.APIViewTestCase): +class LocationTestCase(APIViewTestCases.APIViewTestCase): model = Location brief_fields = ['_depth', 'description', 'display', 'id', 'name', 'rack_count', 'slug', 'url'] bulk_update_data = { @@ -504,7 +504,7 @@ class LocationTest(APIViewTestCases.APIViewTestCase): ] -class RackGroupTest(APIViewTestCases.APIViewTestCase): +class RackGroupTestCase(APIViewTestCases.APIViewTestCase): model = RackGroup brief_fields = ['description', 'display', 'id', 'name', 'rack_count', 'slug', 'url'] create_data = [ @@ -536,7 +536,7 @@ class RackGroupTest(APIViewTestCases.APIViewTestCase): RackGroup.objects.bulk_create(rack_groups) -class RackRoleTest(APIViewTestCases.APIViewTestCase): +class RackRoleTestCase(APIViewTestCases.APIViewTestCase): model = RackRole brief_fields = ['description', 'display', 'id', 'name', 'rack_count', 'slug', 'url'] create_data = [ @@ -571,7 +571,7 @@ class RackRoleTest(APIViewTestCases.APIViewTestCase): RackRole.objects.bulk_create(rack_roles) -class RackTypeTest(APIViewTestCases.APIViewTestCase): +class RackTypeTestCase(APIViewTestCases.APIViewTestCase): model = RackType brief_fields = ['description', 'display', 'id', 'manufacturer', 'model', 'rack_count', 'slug', 'url'] bulk_update_data = { @@ -631,7 +631,7 @@ class RackTypeTest(APIViewTestCases.APIViewTestCase): ] -class RackTest(APIViewTestCases.APIViewTestCase): +class RackTestCase(APIViewTestCases.APIViewTestCase): model = Rack brief_fields = ['description', 'device_count', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -729,7 +729,7 @@ class RackTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response.get('Content-Type'), 'image/svg+xml') -class RackReservationTest(APIViewTestCases.APIViewTestCase): +class RackReservationTestCase(APIViewTestCases.APIViewTestCase): model = RackReservation brief_fields = ['description', 'display', 'id', 'status', 'units', 'url', 'user'] bulk_update_data = { @@ -804,7 +804,7 @@ class RackReservationTest(APIViewTestCases.APIViewTestCase): self.assertEqual(result['unit_count'], len(result['units'])) -class ManufacturerTest(APIViewTestCases.APIViewTestCase): +class ManufacturerTestCase(APIViewTestCases.APIViewTestCase): model = Manufacturer brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url'] create_data = [ @@ -836,7 +836,7 @@ class ManufacturerTest(APIViewTestCases.APIViewTestCase): Manufacturer.objects.bulk_create(manufacturers) -class DeviceTypeTest(APIViewTestCases.APIViewTestCase): +class DeviceTypeTestCase(APIViewTestCases.APIViewTestCase): model = DeviceType brief_fields = ['description', 'device_count', 'display', 'id', 'manufacturer', 'model', 'slug', 'url'] bulk_update_data = { @@ -882,7 +882,7 @@ class DeviceTypeTest(APIViewTestCases.APIViewTestCase): ] -class ModuleTypeTest(APIViewTestCases.APIViewTestCase): +class ModuleTypeTestCase(APIViewTestCases.APIViewTestCase): model = ModuleType brief_fields = ['description', 'display', 'id', 'manufacturer', 'model', 'module_count', 'profile', 'url'] bulk_update_data = { @@ -922,7 +922,7 @@ class ModuleTypeTest(APIViewTestCases.APIViewTestCase): ] -class ModuleTypeProfileTest(APIViewTestCases.APIViewTestCase): +class ModuleTypeProfileTestCase(APIViewTestCases.APIViewTestCase): model = ModuleTypeProfile brief_fields = ['description', 'display', 'id', 'name', 'url'] SCHEMAS = [ @@ -986,7 +986,7 @@ class ModuleTypeProfileTest(APIViewTestCases.APIViewTestCase): ModuleTypeProfile.objects.bulk_create(module_type_profiles) -class ConsolePortTemplateTest(APIViewTestCases.APIViewTestCase): +class ConsolePortTemplateTestCase(APIViewTestCases.APIViewTestCase): model = ConsolePortTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1030,7 +1030,7 @@ class ConsolePortTemplateTest(APIViewTestCases.APIViewTestCase): ] -class ConsoleServerPortTemplateTest(APIViewTestCases.APIViewTestCase): +class ConsoleServerPortTemplateTestCase(APIViewTestCases.APIViewTestCase): model = ConsoleServerPortTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1074,7 +1074,7 @@ class ConsoleServerPortTemplateTest(APIViewTestCases.APIViewTestCase): ] -class PowerPortTemplateTest(APIViewTestCases.APIViewTestCase): +class PowerPortTemplateTestCase(APIViewTestCases.APIViewTestCase): model = PowerPortTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1118,7 +1118,7 @@ class PowerPortTemplateTest(APIViewTestCases.APIViewTestCase): ] -class PowerOutletTemplateTest(APIViewTestCases.APIViewTestCase): +class PowerOutletTemplateTestCase(APIViewTestCases.APIViewTestCase): model = PowerOutletTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1176,7 +1176,7 @@ class PowerOutletTemplateTest(APIViewTestCases.APIViewTestCase): ] -class InterfaceTemplateTest(APIViewTestCases.APIViewTestCase): +class InterfaceTemplateTestCase(APIViewTestCases.APIViewTestCase): model = InterfaceTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1224,7 +1224,7 @@ class InterfaceTemplateTest(APIViewTestCases.APIViewTestCase): ] -class FrontPortTemplateTest(APIViewTestCases.APIViewTestCase): +class FrontPortTemplateTestCase(APIViewTestCases.APIViewTestCase): model = FrontPortTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1341,7 +1341,7 @@ class FrontPortTemplateTest(APIViewTestCases.APIViewTestCase): ) -class RearPortTemplateTest(APIViewTestCases.APIViewTestCase): +class RearPortTemplateTestCase(APIViewTestCases.APIViewTestCase): model = RearPortTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1457,7 +1457,7 @@ class RearPortTemplateTest(APIViewTestCases.APIViewTestCase): ) -class ModuleBayTemplateTest(APIViewTestCases.APIViewTestCase): +class ModuleBayTemplateTestCase(APIViewTestCases.APIViewTestCase): model = ModuleBayTemplate brief_fields = ['description', 'display', 'enabled', 'id', 'name', 'url'] bulk_update_data = { @@ -1499,7 +1499,7 @@ class ModuleBayTemplateTest(APIViewTestCases.APIViewTestCase): ] -class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase): +class DeviceBayTemplateTestCase(APIViewTestCases.APIViewTestCase): model = DeviceBayTemplate brief_fields = ['description', 'display', 'enabled', 'id', 'name', 'url'] bulk_update_data = { @@ -1541,7 +1541,7 @@ class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase): ] -class InventoryItemTemplateTest(APIViewTestCases.APIViewTestCase): +class InventoryItemTemplateTestCase(APIViewTestCases.APIViewTestCase): model = InventoryItemTemplate brief_fields = ['_depth', 'description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -1601,7 +1601,7 @@ class InventoryItemTemplateTest(APIViewTestCases.APIViewTestCase): ] -class DeviceRoleTest(APIViewTestCases.APIViewTestCase): +class DeviceRoleTestCase(APIViewTestCases.APIViewTestCase): model = DeviceRole brief_fields = [ '_depth', 'description', 'device_count', 'display', 'id', 'name', 'slug', 'url', 'virtualmachine_count' @@ -1635,7 +1635,7 @@ class DeviceRoleTest(APIViewTestCases.APIViewTestCase): DeviceRole.objects.create(name='Device Role 3', slug='device-role-3', color='0000ff') -class PlatformTest(APIViewTestCases.APIViewTestCase): +class PlatformTestCase(APIViewTestCases.APIViewTestCase): model = Platform brief_fields = [ '_depth', 'description', 'device_count', 'display', 'id', 'name', 'slug', 'url', 'virtualmachine_count', @@ -1670,7 +1670,7 @@ class PlatformTest(APIViewTestCases.APIViewTestCase): platform.save() -class DeviceTest(APIViewTestCases.APIViewTestCase): +class DeviceTestCase(APIViewTestCases.APIViewTestCase): model = Device brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2020,7 +2020,7 @@ class DeviceTest(APIViewTestCases.APIViewTestCase): self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) -class ModuleTest(APIViewTestCases.APIViewTestCase): +class ModuleTestCase(APIViewTestCases.APIViewTestCase): model = Module brief_fields = ['description', 'device', 'display', 'id', 'module_bay', 'module_type', 'url'] bulk_update_data = { @@ -2355,7 +2355,7 @@ class ModuleTest(APIViewTestCases.APIViewTestCase): self.assertEqual(len(response.data['results']), 1) -class ConsolePortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): +class ConsolePortTestCase(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = ConsolePort brief_fields = ['_occupied', 'cable', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2398,7 +2398,7 @@ class ConsolePortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCa ] -class ConsoleServerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): +class ConsoleServerPortTestCase(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = ConsoleServerPort brief_fields = ['_occupied', 'cable', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2441,7 +2441,7 @@ class ConsoleServerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIView ] -class PowerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): +class PowerPortTestCase(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = PowerPort brief_fields = ['_occupied', 'cable', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2481,7 +2481,7 @@ class PowerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase ] -class PowerOutletTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): +class PowerOutletTestCase(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = PowerOutlet brief_fields = ['_occupied', 'cable', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2530,7 +2530,7 @@ class PowerOutletTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCa ] -class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): +class InterfaceTestCase(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = Interface brief_fields = ['_occupied', 'cable', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2739,7 +2739,7 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase self._perform_interface_test_with_invalid_data(InterfaceModeChoices.MODE_TAGGED_ALL, invalid_data) -class FrontPortTest(APIViewTestCases.APIViewTestCase): +class FrontPortTestCase(APIViewTestCases.APIViewTestCase): model = FrontPort brief_fields = ['_occupied', 'cable', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2858,7 +2858,7 @@ class FrontPortTest(APIViewTestCases.APIViewTestCase): self.assertHttpStatus(response, status.HTTP_200_OK) -class RearPortTest(APIViewTestCases.APIViewTestCase): +class RearPortTestCase(APIViewTestCases.APIViewTestCase): model = RearPort brief_fields = ['_occupied', 'cable', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -2974,7 +2974,7 @@ class RearPortTest(APIViewTestCases.APIViewTestCase): self.assertHttpStatus(response, status.HTTP_200_OK) -class ModuleBayTest(APIViewTestCases.APIViewTestCase): +class ModuleBayTestCase(APIViewTestCases.APIViewTestCase): model = ModuleBay brief_fields = ['_occupied', 'description', 'display', 'enabled', 'id', 'installed_module', 'name', 'url'] bulk_update_data = { @@ -3016,7 +3016,7 @@ class ModuleBayTest(APIViewTestCases.APIViewTestCase): ] -class DeviceBayTest(APIViewTestCases.APIViewTestCase): +class DeviceBayTestCase(APIViewTestCases.APIViewTestCase): model = DeviceBay brief_fields = ['_occupied', 'description', 'device', 'display', 'enabled', 'id', 'name', 'url'] bulk_update_data = { @@ -3080,7 +3080,7 @@ class DeviceBayTest(APIViewTestCases.APIViewTestCase): ] -class InventoryItemTest(APIViewTestCases.APIViewTestCase): +class InventoryItemTestCase(APIViewTestCases.APIViewTestCase): model = InventoryItem brief_fields = ['_depth', 'description', 'device', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -3147,7 +3147,7 @@ class InventoryItemTest(APIViewTestCases.APIViewTestCase): ] -class InventoryItemRoleTest(APIViewTestCases.APIViewTestCase): +class InventoryItemRoleTestCase(APIViewTestCases.APIViewTestCase): model = InventoryItemRole brief_fields = ['description', 'display', 'id', 'inventoryitem_count', 'name', 'slug', 'url'] create_data = [ @@ -3182,7 +3182,7 @@ class InventoryItemRoleTest(APIViewTestCases.APIViewTestCase): InventoryItemRole.objects.bulk_create(roles) -class CableBundleTest(APIViewTestCases.APIViewTestCase): +class CableBundleTestCase(APIViewTestCases.APIViewTestCase): model = CableBundle brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -3236,7 +3236,7 @@ class CableBundleTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response.data['cable_count'], 2) -class CableTest(APIViewTestCases.APIViewTestCase): +class CableTestCase(APIViewTestCases.APIViewTestCase): model = Cable brief_fields = ['description', 'display', 'id', 'label', 'url'] bulk_update_data = { @@ -3445,7 +3445,7 @@ class CableTest(APIViewTestCases.APIViewTestCase): self.assertSetEqual(set(ids), expected) -class CableTerminationTest( +class CableTerminationTestCase( APIViewTestCases.GetObjectViewTestCase, APIViewTestCases.ListObjectsViewTestCase, ): @@ -3474,7 +3474,7 @@ class CableTerminationTest( cable.save() -class ConnectedDeviceTest(APITestCase): +class ConnectedDeviceTestCase(APITestCase): @classmethod def setUpTestData(cls): @@ -3511,7 +3511,7 @@ class ConnectedDeviceTest(APITestCase): self.assertHttpStatus(response, status.HTTP_404_NOT_FOUND) -class VirtualChassisTest(APIViewTestCases.APIViewTestCase): +class VirtualChassisTestCase(APIViewTestCases.APIViewTestCase): model = VirtualChassis brief_fields = ['description', 'display', 'id', 'master', 'member_count', 'name', 'url'] @@ -3592,7 +3592,7 @@ class VirtualChassisTest(APIViewTestCases.APIViewTestCase): } -class PowerPanelTest(APIViewTestCases.APIViewTestCase): +class PowerPanelTestCase(APIViewTestCases.APIViewTestCase): model = PowerPanel brief_fields = ['description', 'display', 'id', 'name', 'powerfeed_count', 'url'] user_permissions = ('dcim.view_site', ) @@ -3642,7 +3642,7 @@ class PowerPanelTest(APIViewTestCases.APIViewTestCase): } -class PowerFeedTest(APIViewTestCases.APIViewTestCase): +class PowerFeedTestCase(APIViewTestCases.APIViewTestCase): model = PowerFeed brief_fields = ['_occupied', 'cable', 'description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -3698,7 +3698,7 @@ class PowerFeedTest(APIViewTestCases.APIViewTestCase): ] -class VirtualDeviceContextTest(APIViewTestCases.APIViewTestCase): +class VirtualDeviceContextTestCase(APIViewTestCases.APIViewTestCase): model = VirtualDeviceContext brief_fields = ['description', 'device', 'display', 'id', 'identifier', 'name', 'url'] bulk_update_data = { @@ -3752,7 +3752,7 @@ class VirtualDeviceContextTest(APIViewTestCases.APIViewTestCase): ] -class MACAddressTest(APIViewTestCases.APIViewTestCase): +class MACAddressTestCase(APIViewTestCases.APIViewTestCase): model = MACAddress brief_fields = ['description', 'display', 'id', 'mac_address', 'url'] bulk_update_data = { diff --git a/netbox/dcim/tests/test_cable_profiles.py b/netbox/dcim/tests/test_cable_profiles.py index 1d504f42b..f480a4b88 100644 --- a/netbox/dcim/tests/test_cable_profiles.py +++ b/netbox/dcim/tests/test_cable_profiles.py @@ -12,7 +12,7 @@ from dcim.models import Cable, Interface, RearPort from dcim.tests.utils import CablePathTestCase -class CableProfileLinkPeerTests(CablePathTestCase): +class CableProfileLinkPeerTestCase(CablePathTestCase): """ Tests for link peer resolution with cable profiles. """ @@ -75,7 +75,7 @@ class CableProfileLinkPeerTests(CablePathTestCase): self.assertEqual(interface.link_peers, [rear_ports[1]]) -class CableProfilePeerTerminationTests(CablePathTestCase): +class CableProfilePeerTerminationTestCase(CablePathTestCase): """ Tests for BaseCableProfile.get_peer_termination() and get_peer_terminations(). Verifies that the batch method produces identical results to calling diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index 08c807280..9d7be50ef 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -6,7 +6,7 @@ from dcim.tests.utils import CablePathTestCase from utilities.exceptions import AbortRequest -class LegacyCablePathTests(CablePathTestCase): +class LegacyCablePathTestCase(CablePathTestCase): """ Test NetBox's ability to trace and retrace CablePaths in response to data model changes, without cable profiles. diff --git a/netbox/dcim/tests/test_cablepaths2.py b/netbox/dcim/tests/test_cablepaths2.py index 68208ad07..bce573b79 100644 --- a/netbox/dcim/tests/test_cablepaths2.py +++ b/netbox/dcim/tests/test_cablepaths2.py @@ -7,7 +7,7 @@ from dcim.svg import CableTraceSVG from dcim.tests.utils import CablePathTestCase -class CablePathTests(CablePathTestCase): +class CablePathTestCase(CablePathTestCase): """ Test the creation of CablePaths for Cables with different profiles applied. diff --git a/netbox/dcim/tests/test_tables.py b/netbox/dcim/tests/test_tables.py index 336aa186c..90de72f7a 100644 --- a/netbox/dcim/tests/test_tables.py +++ b/netbox/dcim/tests/test_tables.py @@ -7,19 +7,19 @@ from utilities.testing import TableTestCases # -class RegionTableTest(TableTestCases.StandardTableTestCase): +class RegionTableTestCase(TableTestCases.StandardTableTestCase): table = RegionTable -class SiteGroupTableTest(TableTestCases.StandardTableTestCase): +class SiteGroupTableTestCase(TableTestCases.StandardTableTestCase): table = SiteGroupTable -class SiteTableTest(TableTestCases.StandardTableTestCase): +class SiteTableTestCase(TableTestCases.StandardTableTestCase): table = SiteTable -class LocationTableTest(TableTestCases.StandardTableTestCase): +class LocationTableTestCase(TableTestCases.StandardTableTestCase): table = LocationTable @@ -27,19 +27,19 @@ class LocationTableTest(TableTestCases.StandardTableTestCase): # Racks # -class RackRoleTableTest(TableTestCases.StandardTableTestCase): +class RackRoleTableTestCase(TableTestCases.StandardTableTestCase): table = RackRoleTable -class RackTypeTableTest(TableTestCases.StandardTableTestCase): +class RackTypeTableTestCase(TableTestCases.StandardTableTestCase): table = RackTypeTable -class RackTableTest(TableTestCases.StandardTableTestCase): +class RackTableTestCase(TableTestCases.StandardTableTestCase): table = RackTable -class RackReservationTableTest(TableTestCases.StandardTableTestCase): +class RackReservationTableTestCase(TableTestCases.StandardTableTestCase): table = RackReservationTable @@ -47,11 +47,11 @@ class RackReservationTableTest(TableTestCases.StandardTableTestCase): # Device types # -class ManufacturerTableTest(TableTestCases.StandardTableTestCase): +class ManufacturerTableTestCase(TableTestCases.StandardTableTestCase): table = ManufacturerTable -class DeviceTypeTableTest(TableTestCases.StandardTableTestCase): +class DeviceTypeTableTestCase(TableTestCases.StandardTableTestCase): table = DeviceTypeTable @@ -59,15 +59,15 @@ class DeviceTypeTableTest(TableTestCases.StandardTableTestCase): # Module types # -class ModuleTypeProfileTableTest(TableTestCases.StandardTableTestCase): +class ModuleTypeProfileTableTestCase(TableTestCases.StandardTableTestCase): table = ModuleTypeProfileTable -class ModuleTypeTableTest(TableTestCases.StandardTableTestCase): +class ModuleTypeTableTestCase(TableTestCases.StandardTableTestCase): table = ModuleTypeTable -class ModuleTableTest(TableTestCases.StandardTableTestCase): +class ModuleTableTestCase(TableTestCases.StandardTableTestCase): table = ModuleTable def test_profile_column_available(self): @@ -78,15 +78,15 @@ class ModuleTableTest(TableTestCases.StandardTableTestCase): # Devices # -class DeviceRoleTableTest(TableTestCases.StandardTableTestCase): +class DeviceRoleTableTestCase(TableTestCases.StandardTableTestCase): table = DeviceRoleTable -class PlatformTableTest(TableTestCases.StandardTableTestCase): +class PlatformTableTestCase(TableTestCases.StandardTableTestCase): table = PlatformTable -class DeviceTableTest(TableTestCases.StandardTableTestCase): +class DeviceTableTestCase(TableTestCases.StandardTableTestCase): table = DeviceTable @@ -94,47 +94,47 @@ class DeviceTableTest(TableTestCases.StandardTableTestCase): # Device components # -class ConsolePortTableTest(TableTestCases.StandardTableTestCase): +class ConsolePortTableTestCase(TableTestCases.StandardTableTestCase): table = ConsolePortTable -class ConsoleServerPortTableTest(TableTestCases.StandardTableTestCase): +class ConsoleServerPortTableTestCase(TableTestCases.StandardTableTestCase): table = ConsoleServerPortTable -class PowerPortTableTest(TableTestCases.StandardTableTestCase): +class PowerPortTableTestCase(TableTestCases.StandardTableTestCase): table = PowerPortTable -class PowerOutletTableTest(TableTestCases.StandardTableTestCase): +class PowerOutletTableTestCase(TableTestCases.StandardTableTestCase): table = PowerOutletTable -class InterfaceTableTest(TableTestCases.StandardTableTestCase): +class InterfaceTableTestCase(TableTestCases.StandardTableTestCase): table = InterfaceTable -class FrontPortTableTest(TableTestCases.StandardTableTestCase): +class FrontPortTableTestCase(TableTestCases.StandardTableTestCase): table = FrontPortTable -class RearPortTableTest(TableTestCases.StandardTableTestCase): +class RearPortTableTestCase(TableTestCases.StandardTableTestCase): table = RearPortTable -class ModuleBayTableTest(TableTestCases.StandardTableTestCase): +class ModuleBayTableTestCase(TableTestCases.StandardTableTestCase): table = ModuleBayTable -class DeviceBayTableTest(TableTestCases.StandardTableTestCase): +class DeviceBayTableTestCase(TableTestCases.StandardTableTestCase): table = DeviceBayTable -class InventoryItemTableTest(TableTestCases.StandardTableTestCase): +class InventoryItemTableTestCase(TableTestCases.StandardTableTestCase): table = InventoryItemTable -class InventoryItemRoleTableTest(TableTestCases.StandardTableTestCase): +class InventoryItemRoleTableTestCase(TableTestCases.StandardTableTestCase): table = InventoryItemRoleTable @@ -142,21 +142,21 @@ class InventoryItemRoleTableTest(TableTestCases.StandardTableTestCase): # Connections # -class ConsoleConnectionTableTest(TableTestCases.StandardTableTestCase): +class ConsoleConnectionTableTestCase(TableTestCases.StandardTableTestCase): table = ConsoleConnectionTable queryset_sources = [ ('ConsoleConnectionsListView', ConsolePort.objects.filter(_path__is_complete=True)), ] -class PowerConnectionTableTest(TableTestCases.StandardTableTestCase): +class PowerConnectionTableTestCase(TableTestCases.StandardTableTestCase): table = PowerConnectionTable queryset_sources = [ ('PowerConnectionsListView', PowerPort.objects.filter(_path__is_complete=True)), ] -class InterfaceConnectionTableTest(TableTestCases.StandardTableTestCase): +class InterfaceConnectionTableTestCase(TableTestCases.StandardTableTestCase): table = InterfaceConnectionTable queryset_sources = [ ('InterfaceConnectionsListView', Interface.objects.filter(_path__is_complete=True)), @@ -167,7 +167,7 @@ class InterfaceConnectionTableTest(TableTestCases.StandardTableTestCase): # Cables # -class CableTableTest(TableTestCases.StandardTableTestCase): +class CableTableTestCase(TableTestCases.StandardTableTestCase): table = CableTable @@ -175,11 +175,11 @@ class CableTableTest(TableTestCases.StandardTableTestCase): # Power # -class PowerPanelTableTest(TableTestCases.StandardTableTestCase): +class PowerPanelTableTestCase(TableTestCases.StandardTableTestCase): table = PowerPanelTable -class PowerFeedTableTest(TableTestCases.StandardTableTestCase): +class PowerFeedTableTestCase(TableTestCases.StandardTableTestCase): table = PowerFeedTable @@ -187,7 +187,7 @@ class PowerFeedTableTest(TableTestCases.StandardTableTestCase): # Virtual chassis # -class VirtualChassisTableTest(TableTestCases.StandardTableTestCase): +class VirtualChassisTableTestCase(TableTestCases.StandardTableTestCase): table = VirtualChassisTable @@ -195,7 +195,7 @@ class VirtualChassisTableTest(TableTestCases.StandardTableTestCase): # Virtual device contexts # -class VirtualDeviceContextTableTest(TableTestCases.StandardTableTestCase): +class VirtualDeviceContextTableTestCase(TableTestCases.StandardTableTestCase): table = VirtualDeviceContextTable @@ -203,5 +203,5 @@ class VirtualDeviceContextTableTest(TableTestCases.StandardTableTestCase): # MAC addresses # -class MACAddressTableTest(TableTestCases.StandardTableTestCase): +class MACAddressTableTestCase(TableTestCases.StandardTableTestCase): table = MACAddressTable diff --git a/netbox/extras/tests/test_api.py b/netbox/extras/tests/test_api.py index 22fea092c..d9456c128 100644 --- a/netbox/extras/tests/test_api.py +++ b/netbox/extras/tests/test_api.py @@ -22,7 +22,7 @@ from users.models import Group, Token, User from utilities.testing import APITestCase, APIViewTestCases -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): @@ -32,7 +32,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class WebhookTest(APIViewTestCases.APIViewTestCase): +class WebhookTestCase(APIViewTestCases.APIViewTestCase): model = Webhook brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -74,7 +74,7 @@ class WebhookTest(APIViewTestCases.APIViewTestCase): Webhook.objects.bulk_create(webhooks) -class EventRuleTest(APIViewTestCases.APIViewTestCase): +class EventRuleTestCase(APIViewTestCases.APIViewTestCase): model = EventRule brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -152,7 +152,7 @@ class EventRuleTest(APIViewTestCases.APIViewTestCase): ] -class CustomFieldTest(APIViewTestCases.APIViewTestCase): +class CustomFieldTestCase(APIViewTestCases.APIViewTestCase): model = CustomField brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -204,7 +204,7 @@ class CustomFieldTest(APIViewTestCases.APIViewTestCase): cf.object_types.add(site_ct) -class CustomFieldChoiceSetTest(APIViewTestCases.APIViewTestCase): +class CustomFieldChoiceSetTestCase(APIViewTestCases.APIViewTestCase): model = CustomFieldChoiceSet brief_fields = ['choices_count', 'description', 'display', 'id', 'name', 'url'] create_data = [ @@ -325,7 +325,7 @@ class CustomFieldChoiceSetTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response.status_code, 400) -class CustomLinkTest(APIViewTestCases.APIViewTestCase): +class CustomLinkTestCase(APIViewTestCases.APIViewTestCase): model = CustomLink brief_fields = ['display', 'id', 'name', 'url'] create_data = [ @@ -385,7 +385,7 @@ class CustomLinkTest(APIViewTestCases.APIViewTestCase): custom_link.object_types.set([site_type]) -class SavedFilterTest(APIViewTestCases.APIViewTestCase): +class SavedFilterTestCase(APIViewTestCases.APIViewTestCase): model = SavedFilter brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url'] create_data = [ @@ -458,7 +458,7 @@ class SavedFilterTest(APIViewTestCases.APIViewTestCase): savedfilter.object_types.set([site_type]) -class BookmarkTest( +class BookmarkTestCase( APIViewTestCases.GetObjectViewTestCase, APIViewTestCases.ListObjectsViewTestCase, APIViewTestCases.CreateObjectViewTestCase, @@ -510,7 +510,7 @@ class BookmarkTest( ] -class ExportTemplateTest(APIViewTestCases.APIViewTestCase): +class ExportTemplateTestCase(APIViewTestCases.APIViewTestCase): model = ExportTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -560,7 +560,7 @@ class ExportTemplateTest(APIViewTestCases.APIViewTestCase): et.object_types.set([device_object_type]) -class TagTest(APIViewTestCases.APIViewTestCase): +class TagTestCase(APIViewTestCases.APIViewTestCase): model = Tag brief_fields = ['color', 'description', 'display', 'id', 'name', 'slug', 'url'] create_data = [ @@ -593,7 +593,7 @@ class TagTest(APIViewTestCases.APIViewTestCase): Tag.objects.bulk_create(tags) -class TaggedItemTest( +class TaggedItemTestCase( APIViewTestCases.GetObjectViewTestCase, APIViewTestCases.ListObjectsViewTestCase ): @@ -622,7 +622,7 @@ class TaggedItemTest( # TODO: Standardize to APIViewTestCase (needs create & update tests) -class ImageAttachmentTest( +class ImageAttachmentTestCase( APIViewTestCases.GetObjectViewTestCase, APIViewTestCases.ListObjectsViewTestCase, APIViewTestCases.DeleteObjectViewTestCase, @@ -666,7 +666,7 @@ class ImageAttachmentTest( ImageAttachment.objects.bulk_create(image_attachments) -class JournalEntryTest(APIViewTestCases.APIViewTestCase): +class JournalEntryTestCase(APIViewTestCases.APIViewTestCase): model = JournalEntry brief_fields = ['created', 'display', 'id', 'url'] bulk_update_data = { @@ -716,7 +716,7 @@ class JournalEntryTest(APIViewTestCases.APIViewTestCase): ] -class ConfigContextProfileTest(APIViewTestCases.APIViewTestCase): +class ConfigContextProfileTestCase(APIViewTestCases.APIViewTestCase): model = ConfigContextProfile brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -825,7 +825,7 @@ class ConfigContextProfileTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response.data['data_file']['id'], datafile.pk) -class ConfigContextTest(APIViewTestCases.APIViewTestCase): +class ConfigContextTestCase(APIViewTestCases.APIViewTestCase): model = ConfigContext brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -951,7 +951,7 @@ class ConfigContextTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response.data['data_file']['id'], datafile.pk) -class ConfigTemplateTest(APIViewTestCases.APIViewTestCase): +class ConfigTemplateTestCase(APIViewTestCases.APIViewTestCase): model = ConfigTemplate brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -1036,7 +1036,7 @@ class ConfigTemplateTest(APIViewTestCases.APIViewTestCase): self.assertHttpStatus(response, status.HTTP_200_OK) -class ScriptTest(APITestCase): +class ScriptTestCase(APITestCase): class TestScriptClass(PythonClass): class Meta: @@ -1162,7 +1162,7 @@ class ScriptTest(APITestCase): self.TestScriptClass.Meta.scheduling_enabled = original -class CreatedUpdatedFilterTest(APITestCase): +class CreatedUpdatedFilterTestCase(APITestCase): @classmethod def setUpTestData(cls): @@ -1236,7 +1236,7 @@ class CreatedUpdatedFilterTest(APITestCase): self.assertEqual(response.data['results'][0]['id'], rack2.pk) -class SubscriptionTest(APIViewTestCases.APIViewTestCase): +class SubscriptionTestCase(APIViewTestCases.APIViewTestCase): model = Subscription brief_fields = ['display', 'id', 'object_id', 'object_type', 'url', 'user'] @@ -1295,7 +1295,7 @@ class SubscriptionTest(APIViewTestCases.APIViewTestCase): } -class NotificationGroupTest(APIViewTestCases.APIViewTestCase): +class NotificationGroupTestCase(APIViewTestCases.APIViewTestCase): model = NotificationGroup brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -1372,7 +1372,7 @@ class NotificationGroupTest(APIViewTestCases.APIViewTestCase): ] -class NotificationTest(APIViewTestCases.APIViewTestCase): +class NotificationTestCase(APIViewTestCases.APIViewTestCase): model = Notification brief_fields = ['display', 'event_type', 'id', 'object_id', 'object_type', 'read', 'url', 'user'] bulk_update_data = { @@ -1436,7 +1436,7 @@ class NotificationTest(APIViewTestCases.APIViewTestCase): ] -class ScriptModuleTest(APITestCase): +class ScriptModuleTestCase(APITestCase): """ Tests for the POST /api/extras/scripts/upload/ endpoint. diff --git a/netbox/extras/tests/test_conditions.py b/netbox/extras/tests/test_conditions.py index d705ba6ae..53b3c6ac3 100644 --- a/netbox/extras/tests/test_conditions.py +++ b/netbox/extras/tests/test_conditions.py @@ -134,7 +134,7 @@ class ConditionTestCase(TestCase): self.assertTrue(c.eval({'x': '123'})) -class ConditionSetTest(TestCase): +class ConditionSetTestCase(TestCase): def test_empty(self): with self.assertRaises(ValueError): diff --git a/netbox/extras/tests/test_custom_validation.py b/netbox/extras/tests/test_custom_validation.py index f76864a7d..d6fa0afd4 100644 --- a/netbox/extras/tests/test_custom_validation.py +++ b/netbox/extras/tests/test_custom_validation.py @@ -8,7 +8,7 @@ from netbox.choices import CSVDelimiterChoices, ImportFormatChoices from utilities.testing import APITestCase, ModelViewTestCase, create_tags, post_data -class ModelFormCustomValidationTest(TestCase): +class ModelFormCustomValidationTestCase(TestCase): @override_settings(CUSTOM_VALIDATORS={ 'circuits.provider': [ @@ -58,7 +58,7 @@ class ModelFormCustomValidationTest(TestCase): self.assertTrue(form.is_valid()) -class BulkEditCustomValidationTest(ModelViewTestCase): +class BulkEditCustomValidationTestCase(ModelViewTestCase): model = Provider @classmethod @@ -155,7 +155,7 @@ class BulkEditCustomValidationTest(ModelViewTestCase): self.assertTrue(provider.asns.exists()) -class BulkImportCustomValidationTest(ModelViewTestCase): +class BulkImportCustomValidationTestCase(ModelViewTestCase): model = Provider @classmethod @@ -214,7 +214,7 @@ class BulkImportCustomValidationTest(ModelViewTestCase): self.assertTrue(Provider.objects.exists()) -class APISerializerCustomValidationTest(APITestCase): +class APISerializerCustomValidationTestCase(APITestCase): @override_settings(CUSTOM_VALIDATORS={ 'circuits.provider': [ diff --git a/netbox/extras/tests/test_customfields.py b/netbox/extras/tests/test_customfields.py index 0b9382701..8c695d382 100644 --- a/netbox/extras/tests/test_customfields.py +++ b/netbox/extras/tests/test_customfields.py @@ -19,7 +19,7 @@ from utilities.testing import APITestCase, TestCase from virtualization.models import VirtualMachine -class CustomFieldTest(TestCase): +class CustomFieldTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -762,7 +762,7 @@ class CustomFieldTest(TestCase): ).full_clean() -class CustomFieldManagerTest(TestCase): +class CustomFieldManagerTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -776,7 +776,7 @@ class CustomFieldManagerTest(TestCase): self.assertEqual(CustomField.objects.get_for_model(VirtualMachine).count(), 0) -class CustomFieldAPITest(APITestCase): +class CustomFieldAPITestCase(APITestCase): @classmethod def setUpTestData(cls): @@ -1564,7 +1564,7 @@ class CustomFieldAPITest(APITestCase): self.assertHttpStatus(response, status.HTTP_200_OK) -class CustomFieldImportTest(TestCase): +class CustomFieldImportTestCase(TestCase): user_permissions = ( 'dcim.view_site', 'dcim.add_site', @@ -1694,7 +1694,7 @@ class CustomFieldImportTest(TestCase): self.assertIn('cf_select', form.errors) -class CustomFieldModelTest(TestCase): +class CustomFieldModelTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -1755,7 +1755,7 @@ class CustomFieldModelTest(TestCase): site.clean() -class CustomFieldModelFilterTest(TestCase): +class CustomFieldModelFilterTestCase(TestCase): queryset = Site.objects.all() filterset = SiteFilterSet diff --git a/netbox/extras/tests/test_customvalidators.py b/netbox/extras/tests/test_customvalidators.py index f7aafb61a..8fc22a6c3 100644 --- a/netbox/extras/tests/test_customvalidators.py +++ b/netbox/extras/tests/test_customvalidators.py @@ -98,7 +98,7 @@ request_validator = CustomValidator({ custom_validator = MyValidator() -class CustomValidatorTest(TestCase): +class CustomValidatorTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -207,7 +207,7 @@ class CustomValidatorTest(TestCase): request_validator(site, request) -class CustomValidatorConfigTest(TestCase): +class CustomValidatorConfigTestCase(TestCase): @override_settings( CUSTOM_VALIDATORS={ @@ -242,7 +242,7 @@ class CustomValidatorConfigTest(TestCase): Site(name='bar', slug='bar').clean() -class ProtectionRulesConfigTest(TestCase): +class ProtectionRulesConfigTestCase(TestCase): @override_settings( PROTECTION_RULES={ diff --git a/netbox/extras/tests/test_dashboard.py b/netbox/extras/tests/test_dashboard.py index ac3a1afe5..866b46477 100644 --- a/netbox/extras/tests/test_dashboard.py +++ b/netbox/extras/tests/test_dashboard.py @@ -3,7 +3,7 @@ from django.test import TestCase, tag from extras.dashboard.widgets import ObjectListWidget -class ObjectListWidgetTests(TestCase): +class ObjectListWidgetTestCase(TestCase): def test_widget_config_form_validates_model(self): model_info = 'extras.notification' form = ObjectListWidget.ConfigForm({'model': model_info}) diff --git a/netbox/extras/tests/test_event_rules.py b/netbox/extras/tests/test_event_rules.py index 50095df22..b36138f49 100644 --- a/netbox/extras/tests/test_event_rules.py +++ b/netbox/extras/tests/test_event_rules.py @@ -24,7 +24,7 @@ from netbox.context_managers import event_tracking from utilities.testing import APITestCase -class EventRuleTest(APITestCase): +class EventRuleTestCase(APITestCase): def setUp(self): super().setUp() diff --git a/netbox/extras/tests/test_forms.py b/netbox/extras/tests/test_forms.py index aea84e92c..b71938456 100644 --- a/netbox/extras/tests/test_forms.py +++ b/netbox/extras/tests/test_forms.py @@ -9,7 +9,7 @@ from extras.forms.model_forms import CustomFieldChoiceSetForm from extras.models import CustomField, CustomFieldChoiceSet -class CustomFieldModelFormTest(TestCase): +class CustomFieldModelFormTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -91,7 +91,7 @@ class CustomFieldModelFormTest(TestCase): self.assertIsNone(instance.custom_field_data[field_type]) -class CustomFieldChoiceSetFormTest(TestCase): +class CustomFieldChoiceSetFormTestCase(TestCase): def test_escaped_colons_preserved_on_edit(self): choice_set = CustomFieldChoiceSet.objects.create( @@ -142,7 +142,7 @@ class CustomFieldChoiceSetFormTest(TestCase): self.assertEqual(updated.choice_colors, {'choice2': 'green', 'foo:bar': 'red'}) -class SavedFilterFormTest(TestCase): +class SavedFilterFormTestCase(TestCase): def test_basic_submit(self): """ diff --git a/netbox/extras/tests/test_models.py b/netbox/extras/tests/test_models.py index a58bf0bca..938e1ae35 100644 --- a/netbox/extras/tests/test_models.py +++ b/netbox/extras/tests/test_models.py @@ -67,7 +67,7 @@ class OverwriteStyleMemoryStorage(Storage): return f'https://example.invalid/{name}' -class ImageAttachmentTests(TestCase): +class ImageAttachmentTestCase(TestCase): @classmethod def setUpTestData(cls): cls.ct_rack = ContentType.objects.get_by_natural_key('dcim', 'rack') @@ -185,7 +185,7 @@ class ImageAttachmentTests(TestCase): self.assertCountEqual(storage.files.keys(), {base_name, suffixed_name}) -class TagTest(TestCase): +class TagTestCase(TestCase): def test_default_ordering_weight_then_name_is_set(self): Tag.objects.create(name='Tag 1', slug='tag-1', weight=3000) @@ -244,7 +244,7 @@ class TagTest(TestCase): sitegroup.tags.add(tag) -class ConfigContextTest(TestCase): +class ConfigContextTestCase(TestCase): """ These test cases deal with the weighting, ordering, and deep merge logic of config context data. @@ -792,7 +792,7 @@ class ConfigContextTest(TestCase): self.assertTrue(distinct_subqueries[0].distinct) -class ConfigTemplateTest(TestCase): +class ConfigTemplateTestCase(TestCase): """ TODO: These test cases deal with the weighting, ordering, and deep merge logic of config context data. """ @@ -905,7 +905,7 @@ class ConfigTemplateTest(TestCase): self.assertEqual(autosync_records.count(), 0, "AutoSyncRecord should be deleted after detaching") -class ConfigTemplateDebugTest(TestCase): +class ConfigTemplateDebugTestCase(TestCase): """ Tests for the ConfigTemplate debug field and its effect on template rendering error output. """ @@ -953,7 +953,7 @@ class ConfigTemplateDebugTest(TestCase): render_jinja2("{% debug %}", {}, debug=False) -class ExportTemplateContextTest(TestCase): +class ExportTemplateContextTestCase(TestCase): """ Tests for ExportTemplate.get_context() including public model population. """ @@ -986,7 +986,7 @@ class ExportTemplateContextTest(TestCase): self.assertIs(ctx['dcim']['Site'], Site) -class EventRuleTest(TestCase): +class EventRuleTestCase(TestCase): def test_action_data_clean_accepts_dict(self): """ diff --git a/netbox/extras/tests/test_scripts.py b/netbox/extras/tests/test_scripts.py index bd4033e92..fab047484 100644 --- a/netbox/extras/tests/test_scripts.py +++ b/netbox/extras/tests/test_scripts.py @@ -32,7 +32,7 @@ JSON_DATA = """ """ -class ScriptVariablesTest(TestCase): +class ScriptVariablesTestCase(TestCase): def test_stringvar(self): diff --git a/netbox/extras/tests/test_tables.py b/netbox/extras/tests/test_tables.py index fb20a7e2e..1fbd1fe2b 100644 --- a/netbox/extras/tests/test_tables.py +++ b/netbox/extras/tests/test_tables.py @@ -3,31 +3,31 @@ from extras.tables import * from utilities.testing import TableTestCases -class CustomFieldTableTest(TableTestCases.StandardTableTestCase): +class CustomFieldTableTestCase(TableTestCases.StandardTableTestCase): table = CustomFieldTable -class CustomFieldChoiceSetTableTest(TableTestCases.StandardTableTestCase): +class CustomFieldChoiceSetTableTestCase(TableTestCases.StandardTableTestCase): table = CustomFieldChoiceSetTable -class CustomLinkTableTest(TableTestCases.StandardTableTestCase): +class CustomLinkTableTestCase(TableTestCases.StandardTableTestCase): table = CustomLinkTable -class ExportTemplateTableTest(TableTestCases.StandardTableTestCase): +class ExportTemplateTableTestCase(TableTestCases.StandardTableTestCase): table = ExportTemplateTable -class SavedFilterTableTest(TableTestCases.StandardTableTestCase): +class SavedFilterTableTestCase(TableTestCases.StandardTableTestCase): table = SavedFilterTable -class TableConfigTableTest(TableTestCases.StandardTableTestCase): +class TableConfigTableTestCase(TableTestCases.StandardTableTestCase): table = TableConfigTable -class BookmarkTableTest(TableTestCases.StandardTableTestCase): +class BookmarkTableTestCase(TableTestCases.StandardTableTestCase): table = BookmarkTable # The list view for this table lives in account.views (not extras.views), @@ -37,11 +37,11 @@ class BookmarkTableTest(TableTestCases.StandardTableTestCase): ] -class NotificationGroupTableTest(TableTestCases.StandardTableTestCase): +class NotificationGroupTableTestCase(TableTestCases.StandardTableTestCase): table = NotificationGroupTable -class NotificationTableTest(TableTestCases.StandardTableTestCase): +class NotificationTableTestCase(TableTestCases.StandardTableTestCase): table = NotificationTable # The list view for this table lives in account.views (not extras.views), @@ -51,7 +51,7 @@ class NotificationTableTest(TableTestCases.StandardTableTestCase): ] -class SubscriptionTableTest(TableTestCases.StandardTableTestCase): +class SubscriptionTableTestCase(TableTestCases.StandardTableTestCase): table = SubscriptionTable # The list view for this table lives in account.views (not extras.views), @@ -61,33 +61,33 @@ class SubscriptionTableTest(TableTestCases.StandardTableTestCase): ] -class WebhookTableTest(TableTestCases.StandardTableTestCase): +class WebhookTableTestCase(TableTestCases.StandardTableTestCase): table = WebhookTable -class EventRuleTableTest(TableTestCases.StandardTableTestCase): +class EventRuleTableTestCase(TableTestCases.StandardTableTestCase): table = EventRuleTable -class TagTableTest(TableTestCases.StandardTableTestCase): +class TagTableTestCase(TableTestCases.StandardTableTestCase): table = TagTable -class ConfigContextProfileTableTest(TableTestCases.StandardTableTestCase): +class ConfigContextProfileTableTestCase(TableTestCases.StandardTableTestCase): table = ConfigContextProfileTable -class ConfigContextTableTest(TableTestCases.StandardTableTestCase): +class ConfigContextTableTestCase(TableTestCases.StandardTableTestCase): table = ConfigContextTable -class ConfigTemplateTableTest(TableTestCases.StandardTableTestCase): +class ConfigTemplateTableTestCase(TableTestCases.StandardTableTestCase): table = ConfigTemplateTable -class ImageAttachmentTableTest(TableTestCases.StandardTableTestCase): +class ImageAttachmentTableTestCase(TableTestCases.StandardTableTestCase): table = ImageAttachmentTable -class JournalEntryTableTest(TableTestCases.StandardTableTestCase): +class JournalEntryTableTestCase(TableTestCases.StandardTableTestCase): table = JournalEntryTable diff --git a/netbox/extras/tests/test_tags.py b/netbox/extras/tests/test_tags.py index b827b28d9..7de2b4889 100644 --- a/netbox/extras/tests/test_tags.py +++ b/netbox/extras/tests/test_tags.py @@ -5,7 +5,7 @@ from dcim.models import Site from utilities.testing import APITestCase, create_tags -class TaggedItemTest(APITestCase): +class TaggedItemTestCase(APITestCase): """ Test the application of Tags to and item (a Site, for example) upon creation (POST) and modification (PATCH). """ diff --git a/netbox/extras/tests/test_utils.py b/netbox/extras/tests/test_utils.py index 1a80c8121..b4ff32563 100644 --- a/netbox/extras/tests/test_utils.py +++ b/netbox/extras/tests/test_utils.py @@ -11,7 +11,7 @@ from tenancy.models import ContactGroup, TenantGroup from wireless.models import WirelessLANGroup -class FilenameFromModelTests(TestCase): +class FilenameFromModelTestCase(TestCase): def test_expected_output(self): cases = ( (ExportTemplate, 'netbox_export_templates'), @@ -43,7 +43,7 @@ class OverwriteStyleStorage(Storage): return f'{file_root}_sdmmer4{file_ext}' -class ImageUploadTests(TestCase): +class ImageUploadTestCase(TestCase): @classmethod def setUpTestData(cls): # We only need a ContentType with model="rack" for the prefix; diff --git a/netbox/extras/tests/test_views.py b/netbox/extras/tests/test_views.py index 8d28f4602..42ea6ce16 100644 --- a/netbox/extras/tests/test_views.py +++ b/netbox/extras/tests/test_views.py @@ -181,6 +181,27 @@ class CustomLinkTestCase(ViewTestCases.PrimaryObjectViewTestCase): } +class CustomLinkRenderingTestCase(TestCase): + user_permissions = ['dcim.view_site'] + + def test_view_object_with_custom_link(self): + customlink = CustomLink( + name='Test', + link_text='FOO {{ object.name }} BAR', + link_url='http://example.com/?site={{ object.slug }}', + new_window=False + ) + customlink.save() + customlink.object_types.set([ObjectType.objects.get_for_model(Site)]) + + site = Site(name='Test Site', slug='test-site') + site.save() + + response = self.client.get(site.get_absolute_url(), follow=True) + self.assertEqual(response.status_code, 200) + self.assertIn(f'FOO {site.name} BAR', str(response.content)) + + class SavedFilterTestCase(ViewTestCases.PrimaryObjectViewTestCase): model = SavedFilter @@ -703,27 +724,6 @@ class JournalEntryTestCase( } -class CustomLinkTest(TestCase): - user_permissions = ['dcim.view_site'] - - def test_view_object_with_custom_link(self): - customlink = CustomLink( - name='Test', - link_text='FOO {{ object.name }} BAR', - link_url='http://example.com/?site={{ object.slug }}', - new_window=False - ) - customlink.save() - customlink.object_types.set([ObjectType.objects.get_for_model(Site)]) - - site = Site(name='Test Site', slug='test-site') - site.save() - - response = self.client.get(site.get_absolute_url(), follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn(f'FOO {site.name} BAR', str(response.content)) - - class SubscriptionTestCase( ViewTestCases.CreateObjectViewTestCase, ViewTestCases.DeleteObjectViewTestCase, @@ -887,7 +887,7 @@ class NotificationTestCase( return -class ScriptListViewTest(TestCase): +class ScriptListViewTestCase(TestCase): user_permissions = ['extras.view_script'] def test_script_list_embedded_parameter(self): @@ -905,7 +905,7 @@ class ScriptListViewTest(TestCase): self.assertTemplateUsed(response, 'extras/inc/script_list_content.html') -class ScriptValidationErrorTest(TestCase): +class ScriptValidationErrorTestCase(TestCase): user_permissions = ['extras.view_script', 'extras.run_script'] class TestScriptMixin: @@ -936,7 +936,7 @@ class ScriptValidationErrorTest(TestCase): def setUp(self): super().setUp() - Script.python_class = property(lambda self: ScriptValidationErrorTest.TestScriptClass) + Script.python_class = property(lambda self: ScriptValidationErrorTestCase.TestScriptClass) @tag('regression') def test_script_validation_error_displays_message(self): @@ -975,7 +975,7 @@ class ScriptValidationErrorTest(TestCase): self.assertEqual(len(messages), 0) -class ScriptDefaultValuesTest(TestCase): +class ScriptDefaultValuesTestCase(TestCase): user_permissions = ['extras.view_script', 'extras.run_script'] class TestScriptClass(PythonClass): @@ -1005,7 +1005,7 @@ class ScriptDefaultValuesTest(TestCase): def setUp(self): super().setUp() - Script.python_class = property(lambda self: ScriptDefaultValuesTest.TestScriptClass) + Script.python_class = property(lambda self: ScriptDefaultValuesTestCase.TestScriptClass) def test_default_values_are_used(self): url = reverse('extras:script', kwargs={'pk': self.script.pk}) diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py index 87bfa54fb..eff18e8f0 100644 --- a/netbox/ipam/tests/test_api.py +++ b/netbox/ipam/tests/test_api.py @@ -14,7 +14,7 @@ from utilities.data import string_to_ranges from utilities.testing import APITestCase, APIViewTestCases, create_test_device, disable_logging -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): @@ -24,7 +24,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class ASNRangeTest(APIViewTestCases.APIViewTestCase): +class ASNRangeTestCase(APIViewTestCases.APIViewTestCase): model = ASNRange brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -136,7 +136,7 @@ class ASNRangeTest(APIViewTestCases.APIViewTestCase): self.assertEqual(len(response.data), 10) -class ASNTest(APIViewTestCases.APIViewTestCase): +class ASNTestCase(APIViewTestCases.APIViewTestCase): model = ASN brief_fields = ['asn', 'description', 'display', 'id', 'url'] bulk_update_data = { @@ -200,7 +200,7 @@ class ASNTest(APIViewTestCases.APIViewTestCase): ] -class VRFTest(APIViewTestCases.APIViewTestCase): +class VRFTestCase(APIViewTestCases.APIViewTestCase): model = VRF brief_fields = ['description', 'display', 'id', 'name', 'prefix_count', 'rd', 'url'] create_data = [ @@ -232,7 +232,7 @@ class VRFTest(APIViewTestCases.APIViewTestCase): VRF.objects.bulk_create(vrfs) -class RouteTargetTest(APIViewTestCases.APIViewTestCase): +class RouteTargetTestCase(APIViewTestCases.APIViewTestCase): model = RouteTarget brief_fields = ['description', 'display', 'id', 'name', 'url'] create_data = [ @@ -261,7 +261,7 @@ class RouteTargetTest(APIViewTestCases.APIViewTestCase): RouteTarget.objects.bulk_create(route_targets) -class RIRTest(APIViewTestCases.APIViewTestCase): +class RIRTestCase(APIViewTestCases.APIViewTestCase): model = RIR brief_fields = ['aggregate_count', 'description', 'display', 'id', 'name', 'slug', 'url'] create_data = [ @@ -293,7 +293,7 @@ class RIRTest(APIViewTestCases.APIViewTestCase): RIR.objects.bulk_create(rirs) -class AggregateTest(APIViewTestCases.APIViewTestCase): +class AggregateTestCase(APIViewTestCases.APIViewTestCase): model = Aggregate brief_fields = ['description', 'display', 'family', 'id', 'prefix', 'url'] bulk_update_data = { @@ -381,7 +381,7 @@ class AggregateTest(APIViewTestCases.APIViewTestCase): # No exception occurred; invalid entries were ignored -class RoleTest(APIViewTestCases.APIViewTestCase): +class RoleTestCase(APIViewTestCases.APIViewTestCase): model = Role brief_fields = ['asn_count', 'description', 'display', 'id', 'name', 'prefix_count', 'slug', 'url', 'vlan_count'] create_data = [ @@ -424,7 +424,7 @@ class RoleTest(APIViewTestCases.APIViewTestCase): ASN.objects.bulk_create(asns) -class PrefixTest(APIViewTestCases.APIViewTestCase): +class PrefixTestCase(APIViewTestCases.APIViewTestCase): model = Prefix brief_fields = ['_depth', 'description', 'display', 'family', 'id', 'prefix', 'url'] create_data = [ @@ -664,7 +664,7 @@ class PrefixTest(APIViewTestCases.APIViewTestCase): self.assertTrue(data['data']['tenant_list']) # tenant returned -class IPRangeTest(APIViewTestCases.APIViewTestCase): +class IPRangeTestCase(APIViewTestCases.APIViewTestCase): model = IPRange brief_fields = ['description', 'display', 'end_address', 'family', 'id', 'start_address', 'url'] create_data = [ @@ -822,7 +822,7 @@ class IPRangeTest(APIViewTestCases.APIViewTestCase): # No exception occurred; invalid entries were ignored -class IPAddressTest(APIViewTestCases.APIViewTestCase): +class IPAddressTestCase(APIViewTestCases.APIViewTestCase): model = IPAddress brief_fields = ['address', 'description', 'display', 'family', 'id', 'url'] create_data = [ @@ -977,7 +977,7 @@ class IPAddressTest(APIViewTestCases.APIViewTestCase): self.assertIn(str(device1.pk), ids) -class FHRPGroupTest(APIViewTestCases.APIViewTestCase): +class FHRPGroupTestCase(APIViewTestCases.APIViewTestCase): model = FHRPGroup brief_fields = ['description', 'display', 'group_id', 'id', 'protocol', 'url'] bulk_update_data = { @@ -1028,7 +1028,7 @@ class FHRPGroupTest(APIViewTestCases.APIViewTestCase): ] -class FHRPGroupAssignmentTest(APIViewTestCases.APIViewTestCase): +class FHRPGroupAssignmentTestCase(APIViewTestCases.APIViewTestCase): model = FHRPGroupAssignment brief_fields = ['display', 'group', 'id', 'interface_id', 'interface_type', 'priority', 'url'] bulk_update_data = { @@ -1108,7 +1108,7 @@ class FHRPGroupAssignmentTest(APIViewTestCases.APIViewTestCase): ] -class VLANGroupTest(APIViewTestCases.APIViewTestCase): +class VLANGroupTestCase(APIViewTestCases.APIViewTestCase): model = VLANGroup brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url', 'vlan_count'] create_data = [ @@ -1231,7 +1231,7 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response.data[2]['vid'], 6) -class VLANTest(APIViewTestCases.APIViewTestCase): +class VLANTestCase(APIViewTestCases.APIViewTestCase): model = VLAN brief_fields = ['description', 'display', 'id', 'name', 'url', 'vid'] bulk_update_data = { @@ -1298,7 +1298,7 @@ class VLANTest(APIViewTestCases.APIViewTestCase): self.assertTrue(content['detail'].startswith('Unable to delete object.')) -class VLANTranslationPolicyTest(APIViewTestCases.APIViewTestCase): +class VLANTranslationPolicyTestCase(APIViewTestCases.APIViewTestCase): model = VLANTranslationPolicy brief_fields = ['description', 'display', 'id', 'name', 'url',] bulk_update_data = { @@ -1340,7 +1340,7 @@ class VLANTranslationPolicyTest(APIViewTestCases.APIViewTestCase): ] -class VLANTranslationRuleTest(APIViewTestCases.APIViewTestCase): +class VLANTranslationRuleTestCase(APIViewTestCases.APIViewTestCase): model = VLANTranslationRule brief_fields = ['description', 'display', 'id', 'local_vid', 'policy', 'remote_vid', 'url'] @@ -1409,7 +1409,7 @@ class VLANTranslationRuleTest(APIViewTestCases.APIViewTestCase): } -class ServiceTemplateTest(APIViewTestCases.APIViewTestCase): +class ServiceTemplateTestCase(APIViewTestCases.APIViewTestCase): model = ServiceTemplate brief_fields = ['description', 'display', 'id', 'name', 'ports', 'protocol', 'url'] bulk_update_data = { @@ -1445,7 +1445,7 @@ class ServiceTemplateTest(APIViewTestCases.APIViewTestCase): ] -class ServiceTest(APIViewTestCases.APIViewTestCase): +class ServiceTestCase(APIViewTestCases.APIViewTestCase): model = Service brief_fields = ['description', 'display', 'id', 'name', 'ports', 'protocol', 'url'] bulk_update_data = { diff --git a/netbox/ipam/tests/test_lookups.py b/netbox/ipam/tests/test_lookups.py index 8383cac31..c23c910cf 100644 --- a/netbox/ipam/tests/test_lookups.py +++ b/netbox/ipam/tests/test_lookups.py @@ -4,7 +4,7 @@ from django.test import TestCase from ipam.models import VLANGroup -class VLANGroupRangeContainsLookupTests(TestCase): +class VLANGroupRangeContainsLookupTestCase(TestCase): @classmethod def setUpTestData(cls): # Two ranges: [1,11) and [20,31) diff --git a/netbox/ipam/tests/test_tables.py b/netbox/ipam/tests/test_tables.py index d9d4ffab1..80391e973 100644 --- a/netbox/ipam/tests/test_tables.py +++ b/netbox/ipam/tests/test_tables.py @@ -7,7 +7,7 @@ from ipam.utils import annotate_ip_space from utilities.testing import TableTestCases -class AnnotatedIPAddressTableTest(TestCase): +class AnnotatedIPAddressTableTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -180,43 +180,43 @@ class AnnotatedIPAddressTableTest(TestCase): # Table ordering tests # -class VRFTableTest(TableTestCases.StandardTableTestCase): +class VRFTableTestCase(TableTestCases.StandardTableTestCase): table = VRFTable -class RouteTargetTableTest(TableTestCases.StandardTableTestCase): +class RouteTargetTableTestCase(TableTestCases.StandardTableTestCase): table = RouteTargetTable -class RIRTableTest(TableTestCases.StandardTableTestCase): +class RIRTableTestCase(TableTestCases.StandardTableTestCase): table = RIRTable -class AggregateTableTest(TableTestCases.StandardTableTestCase): +class AggregateTableTestCase(TableTestCases.StandardTableTestCase): table = AggregateTable -class RoleTableTest(TableTestCases.StandardTableTestCase): +class RoleTableTestCase(TableTestCases.StandardTableTestCase): table = RoleTable -class PrefixTableTest(TableTestCases.StandardTableTestCase): +class PrefixTableTestCase(TableTestCases.StandardTableTestCase): table = PrefixTable -class IPRangeTableTest(TableTestCases.StandardTableTestCase): +class IPRangeTableTestCase(TableTestCases.StandardTableTestCase): table = IPRangeTable -class IPAddressTableTest(TableTestCases.StandardTableTestCase): +class IPAddressTableTestCase(TableTestCases.StandardTableTestCase): table = IPAddressTable -class FHRPGroupTableTest(TableTestCases.StandardTableTestCase): +class FHRPGroupTableTestCase(TableTestCases.StandardTableTestCase): table = FHRPGroupTable -class FHRPGroupAssignmentTableTest(TableTestCases.StandardTableTestCase): +class FHRPGroupAssignmentTableTestCase(TableTestCases.StandardTableTestCase): table = FHRPGroupAssignmentTable # No ObjectListView exists for this table; it is only rendered inline on @@ -226,33 +226,33 @@ class FHRPGroupAssignmentTableTest(TableTestCases.StandardTableTestCase): ] -class VLANGroupTableTest(TableTestCases.StandardTableTestCase): +class VLANGroupTableTestCase(TableTestCases.StandardTableTestCase): table = VLANGroupTable -class VLANTableTest(TableTestCases.StandardTableTestCase): +class VLANTableTestCase(TableTestCases.StandardTableTestCase): table = VLANTable -class VLANTranslationPolicyTableTest(TableTestCases.StandardTableTestCase): +class VLANTranslationPolicyTableTestCase(TableTestCases.StandardTableTestCase): table = VLANTranslationPolicyTable -class VLANTranslationRuleTableTest(TableTestCases.StandardTableTestCase): +class VLANTranslationRuleTableTestCase(TableTestCases.StandardTableTestCase): table = VLANTranslationRuleTable -class ASNRangeTableTest(TableTestCases.StandardTableTestCase): +class ASNRangeTableTestCase(TableTestCases.StandardTableTestCase): table = ASNRangeTable -class ASNTableTest(TableTestCases.StandardTableTestCase): +class ASNTableTestCase(TableTestCases.StandardTableTestCase): table = ASNTable -class ServiceTemplateTableTest(TableTestCases.StandardTableTestCase): +class ServiceTemplateTableTestCase(TableTestCases.StandardTableTestCase): table = ServiceTemplateTable -class ServiceTableTest(TableTestCases.StandardTableTestCase): +class ServiceTableTestCase(TableTestCases.StandardTableTestCase): table = ServiceTable diff --git a/netbox/netbox/tests/test_api.py b/netbox/netbox/tests/test_api.py index 0cff906a4..8d0ad633f 100644 --- a/netbox/netbox/tests/test_api.py +++ b/netbox/netbox/tests/test_api.py @@ -11,7 +11,7 @@ from users.models import Token from utilities.testing import APITestCase -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_http_headers(self): response = self.client.get(reverse('api-root'), **self.header) @@ -46,7 +46,7 @@ class AppTest(APITestCase): self.assertEqual(response.data['id'], self.user.pk) -class OptionalLimitOffsetPaginationTest(TestCase): +class OptionalLimitOffsetPaginationTestCase(TestCase): def setUp(self): self.paginator = NetBoxPagination() diff --git a/netbox/netbox/tests/test_forms.py b/netbox/netbox/tests/test_forms.py index f375d82ff..8a01c393a 100644 --- a/netbox/netbox/tests/test_forms.py +++ b/netbox/netbox/tests/test_forms.py @@ -5,7 +5,7 @@ from dcim.forms import InterfaceImportForm from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Site -class NetBoxModelImportFormCleanTest(TestCase): +class NetBoxModelImportFormCleanTestCase(TestCase): """ Test the clean() method of NetBoxModelImportForm to ensure it properly converts empty strings to None for nullable fields during CSV import. diff --git a/netbox/netbox/tests/test_jobs.py b/netbox/netbox/tests/test_jobs.py index 5bb073951..f3d026790 100644 --- a/netbox/netbox/tests/test_jobs.py +++ b/netbox/netbox/tests/test_jobs.py @@ -39,7 +39,7 @@ class JobRunnerTestCase(TestCase): return timezone.now() + timedelta(weeks=offset) -class JobRunnerTest(JobRunnerTestCase): +class JobRunnerTestCase(JobRunnerTestCase): """ Test internal logic of `JobRunner`. """ @@ -92,7 +92,7 @@ class JobRunnerTest(JobRunnerTestCase): self.assertNotIn(_INSTALL_ROOT, tb_message) -class EnqueueTest(JobRunnerTestCase): +class EnqueueTestCase(JobRunnerTestCase): """ Test enqueuing of `JobRunner`. """ @@ -168,7 +168,7 @@ class EnqueueTest(JobRunnerTestCase): self.assertEqual(TestJobRunner.get_jobs(instance).count(), 1) -class SystemJobTest(JobRunnerTestCase): +class SystemJobTestCase(JobRunnerTestCase): """ Test that system jobs can be scheduled. diff --git a/netbox/netbox/tests/test_models.py b/netbox/netbox/tests/test_models.py index 3da4144c2..0351aea82 100644 --- a/netbox/netbox/tests/test_models.py +++ b/netbox/netbox/tests/test_models.py @@ -7,7 +7,7 @@ from core.models import ObjectChange from netbox.tests.dummy_plugin.models import DummyNetBoxModel -class ModelTest(TestCase): +class ModelTestCase(TestCase): def test_get_absolute_url(self): m = ObjectChange() diff --git a/netbox/netbox/tests/test_object_actions.py b/netbox/netbox/tests/test_object_actions.py index fc195d4e5..e99a83c6c 100644 --- a/netbox/netbox/tests/test_object_actions.py +++ b/netbox/netbox/tests/test_object_actions.py @@ -7,7 +7,7 @@ from dcim.models import Device, DeviceType, Manufacturer from netbox.object_actions import AddObject, BulkEdit, BulkImport -class ObjectActionTest(TestCase): +class ObjectActionTestCase(TestCase): def test_get_url_core_model(self): """Test URL generation for core NetBox models""" diff --git a/netbox/netbox/tests/test_plugins.py b/netbox/netbox/tests/test_plugins.py index c0eecd09d..e9a70ae54 100644 --- a/netbox/netbox/tests/test_plugins.py +++ b/netbox/netbox/tests/test_plugins.py @@ -18,7 +18,7 @@ from netbox.tests.dummy_plugin.webhook_callbacks import set_context @skipIf('netbox.tests.dummy_plugin' not in settings.PLUGINS, "dummy_plugin not in settings.PLUGINS") -class PluginTest(TestCase): +class PluginTestCase(TestCase): def test_config(self): @@ -229,7 +229,7 @@ class PluginTest(TestCase): self.assertIn(set_context, registry['webhook_callbacks']) -class PluginNavigationTest(TestCase): +class PluginNavigationTestCase(TestCase): def test_plugin_menu_item_independent_permissions(self): item1 = PluginMenuItem(link='test1', link_text='Test 1') diff --git a/netbox/netbox/tests/test_registry.py b/netbox/netbox/tests/test_registry.py index e834c4356..bb2ed1713 100644 --- a/netbox/netbox/tests/test_registry.py +++ b/netbox/netbox/tests/test_registry.py @@ -3,7 +3,7 @@ from django.test import TestCase from netbox.registry import Registry -class RegistryTest(TestCase): +class RegistryTestCase(TestCase): def test_set_store(self): reg = Registry({ diff --git a/netbox/netbox/tests/test_tables.py b/netbox/netbox/tests/test_tables.py index fcab9fd79..aa6fd5ad2 100644 --- a/netbox/netbox/tests/test_tables.py +++ b/netbox/netbox/tests/test_tables.py @@ -8,7 +8,7 @@ from netbox.tables import NetBoxTable, columns from utilities.testing import create_tags, create_test_device, create_test_user -class BaseTableTest(TestCase): +class BaseTableTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -99,7 +99,7 @@ class TagColumnTable(NetBoxTable): default_columns = fields -class TagColumnTest(TestCase): +class TagColumnTestCase(TestCase): @classmethod def setUpTestData(cls): diff --git a/netbox/netbox/tests/test_ui.py b/netbox/netbox/tests/test_ui.py index a1cd6fab6..6727e532a 100644 --- a/netbox/netbox/tests/test_ui.py +++ b/netbox/netbox/tests/test_ui.py @@ -29,7 +29,7 @@ from vpn.choices import ( from vpn.models import IKEPolicy, IKEProposal, IPSecPolicy, IPSecProfile -class ChoiceAttrTest(TestCase): +class ChoiceAttrTestCase(TestCase): """ Test class for validating the behavior of ChoiceAttr attribute accessor. @@ -112,7 +112,7 @@ class ChoiceAttrTest(TestCase): ) -class RelatedObjectListAttrTest(TestCase): +class RelatedObjectListAttrTestCase(TestCase): """ Test suite for RelatedObjectListAttr functionality. @@ -222,7 +222,7 @@ class RelatedObjectListAttrTest(TestCase): self.assertIn('…', rendered) -class TextAttrTest(TestCase): +class TextAttrTestCase(TestCase): def test_get_value_with_format_string(self): attr = attrs.TextAttr('asn', format_string='AS{}') @@ -247,7 +247,7 @@ class TextAttrTest(TestCase): self.assertTrue(context['copy_button']) -class NumericAttrTest(TestCase): +class NumericAttrTestCase(TestCase): def test_get_context_with_unit_accessor(self): attr = attrs.NumericAttr('speed', unit_accessor='speed_unit') @@ -268,7 +268,7 @@ class NumericAttrTest(TestCase): self.assertTrue(context['copy_button']) -class BooleanAttrTest(TestCase): +class BooleanAttrTestCase(TestCase): def test_false_value_shown_by_default(self): attr = attrs.BooleanAttr('enabled') @@ -286,7 +286,7 @@ class BooleanAttrTest(TestCase): self.assertIs(attr.get_value(obj), True) -class ImageAttrTest(TestCase): +class ImageAttrTestCase(TestCase): def test_invalid_decoding_raises_value_error(self): with self.assertRaises(ValueError): @@ -314,7 +314,7 @@ class ImageAttrTest(TestCase): self.assertFalse(context['load_lazy']) -class RelatedObjectAttrTest(TestCase): +class RelatedObjectAttrTestCase(TestCase): def test_get_context_with_grouped_by(self): region = SimpleNamespace(name='Region 1') @@ -339,7 +339,7 @@ class RelatedObjectAttrTest(TestCase): self.assertTrue(context['linkify']) -class GenericForeignKeyAttrTest(TestCase): +class GenericForeignKeyAttrTestCase(TestCase): class TreeNode: def __init__(self, name, ancestors=()): @@ -422,7 +422,7 @@ class GenericForeignKeyAttrTest(TestCase): self.assertIsNone(context['nodes']) -class GPSCoordinatesAttrTest(TestCase): +class GPSCoordinatesAttrTestCase(TestCase): def test_missing_latitude_returns_placeholder(self): attr = attrs.GPSCoordinatesAttr() @@ -440,7 +440,7 @@ class GPSCoordinatesAttrTest(TestCase): self.assertEqual(attr.render(obj, {'name': 'coordinates'}), attr.placeholder) -class DateTimeAttrTest(TestCase): +class DateTimeAttrTestCase(TestCase): def test_default_spec(self): attr = attrs.DateTimeAttr('created') @@ -461,7 +461,7 @@ class DateTimeAttrTest(TestCase): self.assertEqual(context['spec'], 'minutes') -class ObjectsTablePanelTest(TestCase): +class ObjectsTablePanelTestCase(TestCase): """ Verify that ObjectsTablePanel.should_render() hides the panel when the requesting user lacks view permission for the panel's model. diff --git a/netbox/tenancy/tests/test_api.py b/netbox/tenancy/tests/test_api.py index 55a54c91f..36235a56b 100644 --- a/netbox/tenancy/tests/test_api.py +++ b/netbox/tenancy/tests/test_api.py @@ -6,7 +6,7 @@ from tenancy.models import * from utilities.testing import APITestCase, APIViewTestCases -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): @@ -16,7 +16,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class TenantGroupTest(APIViewTestCases.APIViewTestCase): +class TenantGroupTestCase(APIViewTestCases.APIViewTestCase): model = TenantGroup brief_fields = ['_depth', 'description', 'display', 'id', 'name', 'slug', 'tenant_count', 'url'] bulk_update_data = { @@ -61,7 +61,7 @@ class TenantGroupTest(APIViewTestCases.APIViewTestCase): ] -class TenantTest(APIViewTestCases.APIViewTestCase): +class TenantTestCase(APIViewTestCases.APIViewTestCase): model = Tenant brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url'] bulk_update_data = { @@ -103,7 +103,7 @@ class TenantTest(APIViewTestCases.APIViewTestCase): ] -class ContactGroupTest(APIViewTestCases.APIViewTestCase): +class ContactGroupTestCase(APIViewTestCases.APIViewTestCase): model = ContactGroup brief_fields = ['_depth', 'contact_count', 'description', 'display', 'id', 'name', 'slug', 'url'] bulk_update_data = { @@ -148,7 +148,7 @@ class ContactGroupTest(APIViewTestCases.APIViewTestCase): ] -class ContactRoleTest(APIViewTestCases.APIViewTestCase): +class ContactRoleTestCase(APIViewTestCases.APIViewTestCase): model = ContactRole brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url'] create_data = [ @@ -180,7 +180,7 @@ class ContactRoleTest(APIViewTestCases.APIViewTestCase): ContactRole.objects.bulk_create(contact_roles) -class ContactTest(APIViewTestCases.APIViewTestCase): +class ContactTestCase(APIViewTestCases.APIViewTestCase): model = Contact brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -220,7 +220,7 @@ class ContactTest(APIViewTestCases.APIViewTestCase): ] -class ContactAssignmentTest(APIViewTestCases.APIViewTestCase): +class ContactAssignmentTestCase(APIViewTestCases.APIViewTestCase): model = ContactAssignment brief_fields = ['contact', 'display', 'id', 'priority', 'role', 'url'] bulk_update_data = { diff --git a/netbox/tenancy/tests/test_tables.py b/netbox/tenancy/tests/test_tables.py index 102d38e4a..04f16a0e2 100644 --- a/netbox/tenancy/tests/test_tables.py +++ b/netbox/tenancy/tests/test_tables.py @@ -2,25 +2,25 @@ from tenancy.tables import * from utilities.testing import TableTestCases -class TenantGroupTableTest(TableTestCases.StandardTableTestCase): +class TenantGroupTableTestCase(TableTestCases.StandardTableTestCase): table = TenantGroupTable -class TenantTableTest(TableTestCases.StandardTableTestCase): +class TenantTableTestCase(TableTestCases.StandardTableTestCase): table = TenantTable -class ContactGroupTableTest(TableTestCases.StandardTableTestCase): +class ContactGroupTableTestCase(TableTestCases.StandardTableTestCase): table = ContactGroupTable -class ContactRoleTableTest(TableTestCases.StandardTableTestCase): +class ContactRoleTableTestCase(TableTestCases.StandardTableTestCase): table = ContactRoleTable -class ContactTableTest(TableTestCases.StandardTableTestCase): +class ContactTableTestCase(TableTestCases.StandardTableTestCase): table = ContactTable -class ContactAssignmentTableTest(TableTestCases.StandardTableTestCase): +class ContactAssignmentTableTestCase(TableTestCases.StandardTableTestCase): table = ContactAssignmentTable diff --git a/netbox/users/tests/test_api.py b/netbox/users/tests/test_api.py index 1a66df67a..e05e7f33b 100644 --- a/netbox/users/tests/test_api.py +++ b/netbox/users/tests/test_api.py @@ -8,7 +8,7 @@ from utilities.data import deepmerge from utilities.testing import APITestCase, APIViewTestCases, create_test_user -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): @@ -17,7 +17,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class UserTest(APIViewTestCases.APIViewTestCase): +class UserTestCase(APIViewTestCases.APIViewTestCase): model = User brief_fields = ['display', 'id', 'url', 'username'] validation_excluded_fields = ['password'] @@ -137,7 +137,7 @@ class UserTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response.status_code, 400) -class GroupTest(APIViewTestCases.APIViewTestCase): +class GroupTestCase(APIViewTestCases.APIViewTestCase): model = Group brief_fields = ['description', 'display', 'id', 'name', 'url'] @@ -189,7 +189,7 @@ class GroupTest(APIViewTestCases.APIViewTestCase): return -class TokenTest( +class TokenTestCase( # No GraphQL support for Token APIViewTestCases.GetObjectViewTestCase, APIViewTestCases.ListObjectsViewTestCase, @@ -330,7 +330,7 @@ class TokenTest( self.assertEqual(token1.user, user1, "Token's user should not have changed") -class ObjectPermissionTest( +class ObjectPermissionTestCase( # No GraphQL support for ObjectPermission APIViewTestCases.GetObjectViewTestCase, APIViewTestCases.ListObjectsViewTestCase, @@ -403,7 +403,7 @@ class ObjectPermissionTest( } -class UserConfigTest(APITestCase): +class UserConfigTestCase(APITestCase): def test_get(self): """ @@ -456,7 +456,7 @@ class UserConfigTest(APITestCase): self.assertDictEqual(userconfig.data, new_data) -class OwnerGroupTest(APIViewTestCases.APIViewTestCase): +class OwnerGroupTestCase(APIViewTestCases.APIViewTestCase): model = OwnerGroup brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -488,7 +488,7 @@ class OwnerGroupTest(APIViewTestCases.APIViewTestCase): ] -class OwnerTest(APIViewTestCases.APIViewTestCase): +class OwnerTestCase(APIViewTestCases.APIViewTestCase): model = Owner brief_fields = ['description', 'display', 'id', 'name', 'url'] diff --git a/netbox/users/tests/test_models.py b/netbox/users/tests/test_models.py index b62ddc9d2..7c1f5556e 100644 --- a/netbox/users/tests/test_models.py +++ b/netbox/users/tests/test_models.py @@ -9,7 +9,7 @@ from users.models import Token, User from utilities.testing import create_test_user -class TokenTest(TestCase): +class TokenTestCase(TestCase): """ Test class for testing the functionality of the Token model. """ @@ -105,7 +105,7 @@ class TokenTest(TestCase): token.clean() -class UserConfigTest(TestCase): +class UserConfigTestCase(TestCase): @classmethod def setUpTestData(cls): diff --git a/netbox/users/tests/test_preferences.py b/netbox/users/tests/test_preferences.py index 81757fb31..5acb84905 100644 --- a/netbox/users/tests/test_preferences.py +++ b/netbox/users/tests/test_preferences.py @@ -15,7 +15,7 @@ DEFAULT_USER_PREFERENCES = { } -class UserPreferencesTest(TestCase): +class UserPreferencesTestCase(TestCase): user_permissions = ['dcim.view_site'] def test_userpreference(self): diff --git a/netbox/users/tests/test_tables.py b/netbox/users/tests/test_tables.py index 336561cbc..4079ea285 100644 --- a/netbox/users/tests/test_tables.py +++ b/netbox/users/tests/test_tables.py @@ -2,25 +2,25 @@ from users.tables import * from utilities.testing import TableTestCases -class TokenTableTest(TableTestCases.StandardTableTestCase): +class TokenTableTestCase(TableTestCases.StandardTableTestCase): table = TokenTable -class UserTableTest(TableTestCases.StandardTableTestCase): +class UserTableTestCase(TableTestCases.StandardTableTestCase): table = UserTable -class GroupTableTest(TableTestCases.StandardTableTestCase): +class GroupTableTestCase(TableTestCases.StandardTableTestCase): table = GroupTable -class ObjectPermissionTableTest(TableTestCases.StandardTableTestCase): +class ObjectPermissionTableTestCase(TableTestCases.StandardTableTestCase): table = ObjectPermissionTable -class OwnerGroupTableTest(TableTestCases.StandardTableTestCase): +class OwnerGroupTableTestCase(TableTestCases.StandardTableTestCase): table = OwnerGroupTable -class OwnerTableTest(TableTestCases.StandardTableTestCase): +class OwnerTableTestCase(TableTestCases.StandardTableTestCase): table = OwnerTable diff --git a/netbox/utilities/tests/test_api.py b/netbox/utilities/tests/test_api.py index 61727190a..a56f495dc 100644 --- a/netbox/utilities/tests/test_api.py +++ b/netbox/utilities/tests/test_api.py @@ -14,7 +14,7 @@ from utilities.api import get_prefetches_for_serializer, get_view_name from utilities.testing import APITestCase, disable_warnings -class WritableNestedSerializerTest(APITestCase): +class WritableNestedSerializerTestCase(APITestCase): """ Test the operation of WritableNestedSerializer using VLANSerializer as our test subject. """ diff --git a/netbox/utilities/tests/test_conversions.py b/netbox/utilities/tests/test_conversions.py index 2338a7ac2..f84d6499e 100644 --- a/netbox/utilities/tests/test_conversions.py +++ b/netbox/utilities/tests/test_conversions.py @@ -6,7 +6,7 @@ from utilities.conversion import to_grams, to_meters from utilities.testing.base import TestCase -class ConversionsTest(TestCase): +class ConversionsTestCase(TestCase): def test_to_grams(self): self.assertEqual( diff --git a/netbox/utilities/tests/test_counters.py b/netbox/utilities/tests/test_counters.py index 6948923d7..dfb0a3f39 100644 --- a/netbox/utilities/tests/test_counters.py +++ b/netbox/utilities/tests/test_counters.py @@ -7,7 +7,7 @@ from utilities.testing.base import TestCase from utilities.testing.utils import create_test_device -class CountersTest(TestCase): +class CountersTestCase(TestCase): """ Validate the operation of the CounterCacheField (tracking counters). """ diff --git a/netbox/utilities/tests/test_filter_modifiers.py b/netbox/utilities/tests/test_filter_modifiers.py index 4bf2e88ab..58bf1245d 100644 --- a/netbox/utilities/tests/test_filter_modifiers.py +++ b/netbox/utilities/tests/test_filter_modifiers.py @@ -43,7 +43,7 @@ class TestFilterSet(BaseFilterSet): fields = ['char_field', 'integer_field', 'decimal_field', 'date_field', 'boolean_field'] -class FilterModifierWidgetTest(TestCase): +class FilterModifierWidgetTestCase(TestCase): """Tests for FilterModifierWidget value extraction and rendering.""" def test_value_from_datadict_finds_value_in_lookup_variant(self): @@ -170,7 +170,7 @@ class FilterModifierWidgetTest(TestCase): self.assertIn('value="test"', html) -class FilterModifierMixinTest(TestCase): +class FilterModifierMixinTestCase(TestCase): """Tests for FilterModifierMixin form field enhancement.""" def test_mixin_enhances_char_field_with_modifiers(self): @@ -250,7 +250,7 @@ class FilterModifierMixinTest(TestCase): self.assertEqual(lookup_codes, expected_lookups) -class ExtendedLookupFilterPillsTest(TestCase): +class ExtendedLookupFilterPillsTestCase(TestCase): """Tests for filter pill rendering of extended lookups.""" @classmethod @@ -307,7 +307,7 @@ class ExtendedLookupFilterPillsTest(TestCase): self.assertIn('ABC123', filter_pill['link_text']) -class EmptyLookupTest(TestCase): +class EmptyLookupTestCase(TestCase): """Tests for empty (is empty/not empty) lookup support.""" @classmethod @@ -343,7 +343,7 @@ class EmptyLookupTest(TestCase): self.assertIn('not empty', filter_pill['link_text'].lower()) -class ObjectCustomFieldEmptyLookupTest(TestCase): +class ObjectCustomFieldEmptyLookupTestCase(TestCase): """ Regression test for https://github.com/netbox-community/netbox/issues/21535. diff --git a/netbox/utilities/tests/test_filters.py b/netbox/utilities/tests/test_filters.py index 1c64f8d28..591934aee 100644 --- a/netbox/utilities/tests/test_filters.py +++ b/netbox/utilities/tests/test_filters.py @@ -37,7 +37,7 @@ from utilities.filters import ( from wireless.choices import WirelessRoleChoices -class TreeNodeMultipleChoiceFilterTest(TestCase): +class TreeNodeMultipleChoiceFilterTestCase(TestCase): class SiteFilterSet(django_filters.FilterSet): region = TreeNodeMultipleChoiceFilter( @@ -121,7 +121,7 @@ class DummyModel(models.Model): tags = TaggableManager(through=TaggedItem) -class BaseFilterSetTest(TestCase): +class BaseFilterSetTestCase(TestCase): """ Ensure that a BaseFilterSet automatically creates the expected set of filters for each filter type. """ @@ -387,7 +387,7 @@ class BaseFilterSetTest(TestCase): self.assertEqual(self.filters['treeforeignkeyfield__n'].exclude, True) -class DynamicFilterLookupExpressionTest(TestCase): +class DynamicFilterLookupExpressionTestCase(TestCase): """ Validate function of automatically generated filters using the Device model as an example. """ diff --git a/netbox/utilities/tests/test_forms.py b/netbox/utilities/tests/test_forms.py index b29cbadf6..efeb422b9 100644 --- a/netbox/utilities/tests/test_forms.py +++ b/netbox/utilities/tests/test_forms.py @@ -304,7 +304,7 @@ class ExpandAlphanumeric(TestCase): sorted(expand_alphanumeric_pattern('r[a,,b]a')) -class ImportFormTest(TestCase): +class ImportFormTestCase(TestCase): def test_format_detection(self): form = BulkImportForm() @@ -384,7 +384,7 @@ class ImportFormTest(TestCase): ]) -class BulkRenameFormTest(TestCase): +class BulkRenameFormTestCase(TestCase): def test_no_strip_whitespace(self): # Tests to make sure Bulk Rename Form isn't stripping whitespaces # See: https://github.com/netbox-community/netbox/issues/13791 @@ -397,7 +397,7 @@ class BulkRenameFormTest(TestCase): self.assertEqual(form.cleaned_data["replace"], " world ") -class GetFieldValueTest(TestCase): +class GetFieldValueTestCase(TestCase): @classmethod def setUpTestData(cls): @@ -457,7 +457,7 @@ class GetFieldValueTest(TestCase): ) -class CSVSelectWidgetTest(TestCase): +class CSVSelectWidgetTestCase(TestCase): """ Validate that CSVSelectWidget treats blank values as omitted. This allows model defaults to be applied when CSV fields are present but empty. @@ -489,7 +489,7 @@ class CSVSelectWidgetTest(TestCase): self.assertFalse(widget.value_omitted_from_data(data, {}, 'test_field')) -class SelectMultipleWidgetTest(TestCase): +class SelectMultipleWidgetTestCase(TestCase): """ Validate filtering behavior of AvailableOptions and SelectedOptions widgets. """ @@ -557,7 +557,7 @@ class SelectMultipleWidgetTest(TestCase): self.assertEqual(widget.choices[1][1], [(3, 'Option 3')]) -class GetCapacityUnitLabelTest(TestCase): +class GetCapacityUnitLabelTestCase(TestCase): """ Test the get_capacity_unit_label function for correct base unit label. """ diff --git a/netbox/utilities/tests/test_managers.py b/netbox/utilities/tests/test_managers.py index 7ff23b69d..368da980f 100644 --- a/netbox/utilities/tests/test_managers.py +++ b/netbox/utilities/tests/test_managers.py @@ -3,7 +3,7 @@ from django.test import TestCase from dcim.models import Site -class NaturalOrderByManagerTest(TestCase): +class NaturalOrderByManagerTestCase(TestCase): """ Ensure consistent natural ordering given myriad sample data. We use dcim.Site as our guinea pig because it's simple. """ diff --git a/netbox/utilities/tests/test_permissions.py b/netbox/utilities/tests/test_permissions.py index dd4dd7cad..c98627044 100644 --- a/netbox/utilities/tests/test_permissions.py +++ b/netbox/utilities/tests/test_permissions.py @@ -9,7 +9,7 @@ from utilities.permissions import ModelAction, register_model_actions from virtualization.models import VirtualMachine -class ModelActionTest(TestCase): +class ModelActionTestCase(TestCase): def test_hash(self): action1 = ModelAction(name='sync') @@ -36,7 +36,7 @@ class ModelActionTest(TestCase): self.assertEqual(len(actions), 2) -class RegisterModelActionsTest(TestCase): +class RegisterModelActionsTestCase(TestCase): def setUp(self): self._original_actions = dict(registry['model_actions']) @@ -107,7 +107,7 @@ class RegisterModelActionsTest(TestCase): self.assertEqual(action_fields.count('action_render_config'), 1) -class ObjectPermissionFormTest(TestCase): +class ObjectPermissionFormTestCase(TestCase): def setUp(self): self._original_actions = dict(registry['model_actions']) diff --git a/netbox/utilities/tests/test_prefetch.py b/netbox/utilities/tests/test_prefetch.py index 9da35c12e..534fd3313 100644 --- a/netbox/utilities/tests/test_prefetch.py +++ b/netbox/utilities/tests/test_prefetch.py @@ -3,7 +3,7 @@ from utilities.prefetch import get_prefetchable_fields from utilities.testing.base import TestCase -class GetPrefetchableFieldsTest(TestCase): +class GetPrefetchableFieldsTestCase(TestCase): """ Verify the operation of get_prefetchable_fields() """ diff --git a/netbox/utilities/tests/test_request.py b/netbox/utilities/tests/test_request.py index 3ab8d6e1c..075bf2aaa 100644 --- a/netbox/utilities/tests/test_request.py +++ b/netbox/utilities/tests/test_request.py @@ -5,7 +5,7 @@ from netaddr import IPAddress from utilities.request import copy_safe_request, get_client_ip -class CopySafeRequestTests(TestCase): +class CopySafeRequestTestCase(TestCase): def setUp(self): self.factory = RequestFactory() @@ -39,7 +39,7 @@ class CopySafeRequestTests(TestCase): self.assertNotIn('HTTP_X_CUSTOM_INT', fake.META) -class GetClientIPTests(TestCase): +class GetClientIPTestCase(TestCase): def setUp(self): self.factory = RequestFactory() diff --git a/netbox/utilities/tests/test_templatetags.py b/netbox/utilities/tests/test_templatetags.py index 667ea064a..02f24862e 100644 --- a/netbox/utilities/tests/test_templatetags.py +++ b/netbox/utilities/tests/test_templatetags.py @@ -11,7 +11,7 @@ from utilities.templatetags.builtins.tags import badge, customfield_value, stati from utilities.templatetags.helpers import _humanize_capacity, humanize_speed -class CustomFieldValueTagTest(TestCase): +class CustomFieldValueTagTestCase(TestCase): @classmethod def setUpTestData(cls): object_type = ObjectType.objects.get_for_model(Site) @@ -60,7 +60,7 @@ class CustomFieldValueTagTest(TestCase): self.assertEqual(context['value'], ['Option B']) -class StaticWithParamsTest(TestCase): +class StaticWithParamsTestCase(TestCase): """ Test the static_with_params template tag functionality. """ @@ -103,7 +103,7 @@ class StaticWithParamsTest(TestCase): self.assertNotIn('v=old_version', result) -class BadgeTest(TestCase): +class BadgeTestCase(TestCase): """ Test the badge template tag functionality. """ @@ -117,7 +117,7 @@ class BadgeTest(TestCase): self.assertIn('>Role<', html) -class HumanizeCapacityTest(TestCase): +class HumanizeCapacityTestCase(TestCase): """ Test the _humanize_capacity function for correct SI/IEC unit label selection. """ @@ -160,7 +160,7 @@ class HumanizeCapacityTest(TestCase): self.assertEqual(_humanize_capacity(2000), '2.00 GB') -class HumanizeSpeedTest(TestCase): +class HumanizeSpeedTestCase(TestCase): """ Test the humanize_speed filter for correct unit selection and decimal formatting. """ diff --git a/netbox/utilities/tests/test_utils.py b/netbox/utilities/tests/test_utils.py index 3943a3044..4858f511c 100644 --- a/netbox/utilities/tests/test_utils.py +++ b/netbox/utilities/tests/test_utils.py @@ -6,7 +6,7 @@ from utilities.query import dict_to_filter_params from utilities.querydict import normalize_querydict -class DictToFilterParamsTest(TestCase): +class DictToFilterParamsTestCase(TestCase): """ Validate the operation of dict_to_filter_params(). """ @@ -39,7 +39,7 @@ class DictToFilterParamsTest(TestCase): self.assertNotEqual(dict_to_filter_params(input), output) -class NormalizeQueryDictTest(TestCase): +class NormalizeQueryDictTestCase(TestCase): """ Validate normalize_querydict() utility function. """ @@ -50,7 +50,7 @@ class NormalizeQueryDictTest(TestCase): ) -class DeepMergeTest(TestCase): +class DeepMergeTestCase(TestCase): """ Validate the behavior of the deepmerge() utility. """ diff --git a/netbox/virtualization/tests/test_api.py b/netbox/virtualization/tests/test_api.py index 3e3112a87..341e8c26d 100644 --- a/netbox/virtualization/tests/test_api.py +++ b/netbox/virtualization/tests/test_api.py @@ -26,7 +26,7 @@ from virtualization.choices import * from virtualization.models import * -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): @@ -36,7 +36,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class ClusterTypeTest(APIViewTestCases.APIViewTestCase): +class ClusterTypeTestCase(APIViewTestCases.APIViewTestCase): model = ClusterType brief_fields = ['cluster_count', 'description', 'display', 'id', 'name', 'slug', 'url'] create_data = [ @@ -68,7 +68,7 @@ class ClusterTypeTest(APIViewTestCases.APIViewTestCase): ClusterType.objects.bulk_create(cluster_types) -class ClusterGroupTest(APIViewTestCases.APIViewTestCase): +class ClusterGroupTestCase(APIViewTestCases.APIViewTestCase): model = ClusterGroup brief_fields = ['cluster_count', 'description', 'display', 'id', 'name', 'slug', 'url'] create_data = [ @@ -100,7 +100,7 @@ class ClusterGroupTest(APIViewTestCases.APIViewTestCase): ClusterGroup.objects.bulk_create(cluster_Groups) -class ClusterTest(APIViewTestCases.APIViewTestCase): +class ClusterTestCase(APIViewTestCases.APIViewTestCase): model = Cluster brief_fields = ['description', 'display', 'id', 'name', 'url', 'virtualmachine_count'] bulk_update_data = { @@ -168,7 +168,7 @@ class ClusterTest(APIViewTestCases.APIViewTestCase): ] -class VirtualMachineTypeTest(APIViewTestCases.APIViewTestCase): +class VirtualMachineTypeTestCase(APIViewTestCases.APIViewTestCase): model = VirtualMachineType brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url'] user_permissions = ('dcim.view_platform', 'virtualization.view_virtualmachine') @@ -237,7 +237,7 @@ class VirtualMachineTypeTest(APIViewTestCases.APIViewTestCase): } -class VirtualMachineTest(APIViewTestCases.APIViewTestCase): +class VirtualMachineTestCase(APIViewTestCases.APIViewTestCase): model = VirtualMachine brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -596,7 +596,7 @@ class VirtualMachineTest(APIViewTestCases.APIViewTestCase): self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) -class VMInterfaceTest(APIViewTestCases.APIViewTestCase): +class VMInterfaceTestCase(APIViewTestCases.APIViewTestCase): model = VMInterface brief_fields = ['description', 'display', 'id', 'name', 'url', 'virtual_machine'] bulk_update_data = { @@ -727,7 +727,7 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase): self.assertEqual(virtual_machine.interfaces.count(), 2) # Child & parent were both deleted -class VirtualDiskTest(APIViewTestCases.APIViewTestCase): +class VirtualDiskTestCase(APIViewTestCases.APIViewTestCase): model = VirtualDisk brief_fields = ['description', 'display', 'id', 'name', 'size', 'url', 'virtual_machine'] bulk_update_data = { diff --git a/netbox/virtualization/tests/test_tables.py b/netbox/virtualization/tests/test_tables.py index c443672e5..26ab03062 100644 --- a/netbox/virtualization/tests/test_tables.py +++ b/netbox/virtualization/tests/test_tables.py @@ -2,25 +2,25 @@ from utilities.testing import TableTestCases from virtualization.tables import * -class ClusterTypeTableTest(TableTestCases.StandardTableTestCase): +class ClusterTypeTableTestCase(TableTestCases.StandardTableTestCase): table = ClusterTypeTable -class ClusterGroupTableTest(TableTestCases.StandardTableTestCase): +class ClusterGroupTableTestCase(TableTestCases.StandardTableTestCase): table = ClusterGroupTable -class ClusterTableTest(TableTestCases.StandardTableTestCase): +class ClusterTableTestCase(TableTestCases.StandardTableTestCase): table = ClusterTable -class VirtualMachineTableTest(TableTestCases.StandardTableTestCase): +class VirtualMachineTableTestCase(TableTestCases.StandardTableTestCase): table = VirtualMachineTable -class VMInterfaceTableTest(TableTestCases.StandardTableTestCase): +class VMInterfaceTableTestCase(TableTestCases.StandardTableTestCase): table = VMInterfaceTable -class VirtualDiskTableTest(TableTestCases.StandardTableTestCase): +class VirtualDiskTableTestCase(TableTestCases.StandardTableTestCase): table = VirtualDiskTable diff --git a/netbox/vpn/tests/test_api.py b/netbox/vpn/tests/test_api.py index 19fdf1136..25695bbf0 100644 --- a/netbox/vpn/tests/test_api.py +++ b/netbox/vpn/tests/test_api.py @@ -9,7 +9,7 @@ from vpn.choices import * from vpn.models import * -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): url = reverse('vpn-api:api-root') @@ -18,7 +18,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class TunnelGroupTest(APIViewTestCases.APIViewTestCase): +class TunnelGroupTestCase(APIViewTestCases.APIViewTestCase): model = TunnelGroup brief_fields = ['description', 'display', 'id', 'name', 'slug', 'tunnel_count', 'url'] create_data = ( @@ -50,7 +50,7 @@ class TunnelGroupTest(APIViewTestCases.APIViewTestCase): TunnelGroup.objects.bulk_create(tunnel_groups) -class TunnelTest(APIViewTestCases.APIViewTestCase): +class TunnelTestCase(APIViewTestCases.APIViewTestCase): model = Tunnel brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -111,7 +111,7 @@ class TunnelTest(APIViewTestCases.APIViewTestCase): ] -class TunnelTerminationTest(APIViewTestCases.APIViewTestCase): +class TunnelTerminationTestCase(APIViewTestCases.APIViewTestCase): model = TunnelTermination brief_fields = ['display', 'id', 'url'] bulk_update_data = { @@ -179,7 +179,7 @@ class TunnelTerminationTest(APIViewTestCases.APIViewTestCase): ] -class IKEProposalTest(APIViewTestCases.APIViewTestCase): +class IKEProposalTestCase(APIViewTestCases.APIViewTestCase): model = IKEProposal brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -243,7 +243,7 @@ class IKEProposalTest(APIViewTestCases.APIViewTestCase): ] -class IKEPolicyTest(APIViewTestCases.APIViewTestCase): +class IKEPolicyTestCase(APIViewTestCases.APIViewTestCase): model = IKEPolicy brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -317,7 +317,7 @@ class IKEPolicyTest(APIViewTestCases.APIViewTestCase): ] -class IPSecProposalTest(APIViewTestCases.APIViewTestCase): +class IPSecProposalTestCase(APIViewTestCases.APIViewTestCase): model = IPSecProposal brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -367,7 +367,7 @@ class IPSecProposalTest(APIViewTestCases.APIViewTestCase): ] -class IPSecPolicyTest(APIViewTestCases.APIViewTestCase): +class IPSecPolicyTestCase(APIViewTestCases.APIViewTestCase): model = IPSecPolicy brief_fields = ['description', 'display', 'id', 'name', 'url'] bulk_update_data = { @@ -429,7 +429,7 @@ class IPSecPolicyTest(APIViewTestCases.APIViewTestCase): ] -class IPSecProfileTest(APIViewTestCases.APIViewTestCase): +class IPSecProfileTestCase(APIViewTestCases.APIViewTestCase): model = IPSecProfile brief_fields = ['description', 'display', 'id', 'name', 'url'] user_permissions = ('vpn.view_ikepolicy', 'vpn.view_ipsecpolicy') @@ -520,7 +520,7 @@ class IPSecProfileTest(APIViewTestCases.APIViewTestCase): } -class L2VPNTest(APIViewTestCases.APIViewTestCase): +class L2VPNTestCase(APIViewTestCases.APIViewTestCase): model = L2VPN brief_fields = ['description', 'display', 'id', 'identifier', 'name', 'slug', 'type', 'url'] create_data = [ @@ -602,7 +602,7 @@ class L2VPNTest(APIViewTestCases.APIViewTestCase): self.assertEqual(response_data['count'], 1) -class L2VPNTerminationTest(APIViewTestCases.APIViewTestCase): +class L2VPNTerminationTestCase(APIViewTestCases.APIViewTestCase): model = L2VPNTermination brief_fields = ['display', 'id', 'l2vpn', 'url'] user_permissions = ('dcim.view_location', 'vpn.view_l2vpn') diff --git a/netbox/vpn/tests/test_tables.py b/netbox/vpn/tests/test_tables.py index b1f2e65ed..44c8fd24a 100644 --- a/netbox/vpn/tests/test_tables.py +++ b/netbox/vpn/tests/test_tables.py @@ -2,41 +2,41 @@ from utilities.testing import TableTestCases from vpn.tables import * -class TunnelGroupTableTest(TableTestCases.StandardTableTestCase): +class TunnelGroupTableTestCase(TableTestCases.StandardTableTestCase): table = TunnelGroupTable -class TunnelTableTest(TableTestCases.StandardTableTestCase): +class TunnelTableTestCase(TableTestCases.StandardTableTestCase): table = TunnelTable -class TunnelTerminationTableTest(TableTestCases.StandardTableTestCase): +class TunnelTerminationTableTestCase(TableTestCases.StandardTableTestCase): table = TunnelTerminationTable -class IKEProposalTableTest(TableTestCases.StandardTableTestCase): +class IKEProposalTableTestCase(TableTestCases.StandardTableTestCase): table = IKEProposalTable -class IKEPolicyTableTest(TableTestCases.StandardTableTestCase): +class IKEPolicyTableTestCase(TableTestCases.StandardTableTestCase): table = IKEPolicyTable -class IPSecProposalTableTest(TableTestCases.StandardTableTestCase): +class IPSecProposalTableTestCase(TableTestCases.StandardTableTestCase): table = IPSecProposalTable -class IPSecPolicyTableTest(TableTestCases.StandardTableTestCase): +class IPSecPolicyTableTestCase(TableTestCases.StandardTableTestCase): table = IPSecPolicyTable -class IPSecProfileTableTest(TableTestCases.StandardTableTestCase): +class IPSecProfileTableTestCase(TableTestCases.StandardTableTestCase): table = IPSecProfileTable -class L2VPNTableTest(TableTestCases.StandardTableTestCase): +class L2VPNTableTestCase(TableTestCases.StandardTableTestCase): table = L2VPNTable -class L2VPNTerminationTableTest(TableTestCases.StandardTableTestCase): +class L2VPNTerminationTableTestCase(TableTestCases.StandardTableTestCase): table = L2VPNTerminationTable diff --git a/netbox/wireless/tests/test_api.py b/netbox/wireless/tests/test_api.py index 0fe5e45f6..b5671db32 100644 --- a/netbox/wireless/tests/test_api.py +++ b/netbox/wireless/tests/test_api.py @@ -8,7 +8,7 @@ from wireless.choices import * from wireless.models import * -class AppTest(APITestCase): +class AppTestCase(APITestCase): def test_root(self): url = reverse('wireless-api:api-root') @@ -17,7 +17,7 @@ class AppTest(APITestCase): self.assertEqual(response.status_code, 200) -class WirelessLANGroupTest(APIViewTestCases.APIViewTestCase): +class WirelessLANGroupTestCase(APIViewTestCases.APIViewTestCase): model = WirelessLANGroup brief_fields = ['_depth', 'description', 'display', 'id', 'name', 'slug', 'url', 'wirelesslan_count'] create_data = [ @@ -49,7 +49,7 @@ class WirelessLANGroupTest(APIViewTestCases.APIViewTestCase): WirelessLANGroup.objects.create(name='Wireless LAN Group 3', slug='wireless-lan-group-3') -class WirelessLANTest(APIViewTestCases.APIViewTestCase): +class WirelessLANTestCase(APIViewTestCases.APIViewTestCase): model = WirelessLAN brief_fields = ['description', 'display', 'id', 'ssid', 'url'] @@ -119,7 +119,7 @@ class WirelessLANTest(APIViewTestCases.APIViewTestCase): } -class WirelessLinkTest(APIViewTestCases.APIViewTestCase): +class WirelessLinkTestCase(APIViewTestCases.APIViewTestCase): model = WirelessLink brief_fields = ['description', 'display', 'id', 'ssid', 'url'] bulk_update_data = { diff --git a/netbox/wireless/tests/test_tables.py b/netbox/wireless/tests/test_tables.py index a815d327a..ac5ff5384 100644 --- a/netbox/wireless/tests/test_tables.py +++ b/netbox/wireless/tests/test_tables.py @@ -2,13 +2,13 @@ from utilities.testing import TableTestCases from wireless.tables import * -class WirelessLANGroupTableTest(TableTestCases.StandardTableTestCase): +class WirelessLANGroupTableTestCase(TableTestCases.StandardTableTestCase): table = WirelessLANGroupTable -class WirelessLANTableTest(TableTestCases.StandardTableTestCase): +class WirelessLANTableTestCase(TableTestCases.StandardTableTestCase): table = WirelessLANTable -class WirelessLinkTableTest(TableTestCases.StandardTableTestCase): +class WirelessLinkTableTestCase(TableTestCases.StandardTableTestCase): table = WirelessLinkTable From c27c47049936f537576b290dc75502147c2dd0d5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 11 May 2026 17:29:51 -0400 Subject: [PATCH 028/131] Closes #19971: Expand test coverage for config & export templates (#22164) --- netbox/extras/models/mixins.py | 3 +- netbox/extras/tests/test_models.py | 187 ++++++++++++++++++++++++++++- netbox/extras/tests/test_views.py | 53 ++++++++ 3 files changed, 236 insertions(+), 7 deletions(-) diff --git a/netbox/extras/models/mixins.py b/netbox/extras/models/mixins.py index 805916d9f..79df67a11 100644 --- a/netbox/extras/models/mixins.py +++ b/netbox/extras/models/mixins.py @@ -138,7 +138,8 @@ class RenderTemplateMixin(models.Model): """ Pre-processing of any defined Jinja environment parameters (e.g. to support path resolution). """ - params = self.environment_params or {} + # Shallow-copy so resolved imports don't replace the string values on the model field itself. + params = dict(self.environment_params or {}) for name, value in params.items(): if name in JINJA_ENV_PARAMS_WITH_PATH_IMPORT and type(value) is str: params[name] = import_string(value) diff --git a/netbox/extras/tests/test_models.py b/netbox/extras/tests/test_models.py index 938e1ae35..d3a2ad6fd 100644 --- a/netbox/extras/tests/test_models.py +++ b/netbox/extras/tests/test_models.py @@ -1,6 +1,7 @@ import io import tempfile from pathlib import Path +from types import SimpleNamespace from unittest.mock import patch from django.contrib.contenttypes.models import ContentType @@ -9,11 +10,13 @@ from django.core.files.storage import Storage from django.core.files.uploadedfile import SimpleUploadedFile from django.forms import ValidationError from django.test import TestCase, tag +from jinja2 import StrictUndefined, TemplateError, TemplateSyntaxError, UndefinedError from PIL import Image from core.events import OBJECT_CREATED from core.models import AutoSyncRecord, DataSource, ObjectType from dcim.models import Device, DeviceRole, DeviceType, Location, Manufacturer, Platform, Region, Site, SiteGroup +from extras.constants import DEFAULT_MIME_TYPE from extras.models import ( ConfigContext, ConfigContextProfile, @@ -26,6 +29,7 @@ from extras.models import ( ) from tenancy.models import Tenant, TenantGroup from utilities.exceptions import AbortRequest +from utilities.jinja2 import render_jinja2 from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine @@ -925,30 +929,24 @@ class ConfigTemplateDebugTestCase(TestCase): def test_template_error_non_debug_no_traceback(self): """In non-debug mode, a TemplateError raises with no traceback exposure.""" - from jinja2 import TemplateError t = self._make_template("{{ unclosed", debug=False) with self.assertRaises(TemplateError): t.render({}) def test_template_error_debug_mode_raises(self): """In debug mode, a TemplateError still raises (callers handle display).""" - from jinja2 import TemplateError t = self._make_template("{{ unclosed", debug=True) with self.assertRaises(TemplateError): t.render({}) def test_render_jinja2_debug_extension_enabled(self): """When debug=True, the Jinja2 debug extension is loaded in the environment.""" - from utilities.jinja2 import render_jinja2 # The {% debug %} tag is only available when the debug extension is loaded. output = render_jinja2("{% debug %}", {}, debug=True) self.assertIsInstance(output, str) def test_render_jinja2_debug_extension_not_loaded_by_default(self): """When debug=False, the {% debug %} tag is not available.""" - from jinja2 import TemplateSyntaxError - - from utilities.jinja2 import render_jinja2 with self.assertRaises(TemplateSyntaxError): render_jinja2("{% debug %}", {}, debug=False) @@ -986,6 +984,183 @@ class ExportTemplateContextTestCase(TestCase): self.assertIs(ctx['dcim']['Site'], Site) +def finalize_none_to_dash(value): + """ + Module-level helper used by RenderTemplateMixinRenderTest.test_environment_params_finalize_path_import. + Exported so it can be referenced by dotted path from a Jinja environment_params value. + """ + return '-' if value is None else value + + +class RenderTemplateMixinRenderTest(TestCase): + """ + Tests for RenderTemplateMixin.render() and get_environment_params(), exercised via ConfigTemplate. + """ + + def test_render_basic_context(self): + t = ConfigTemplate(name='basic', template_code='Hello {{ name }}') + self.assertEqual(t.render({'name': 'world'}), 'Hello world') + + def test_render_normalizes_crlf(self): + t = ConfigTemplate(name='crlf', template_code='line1\r\nline2\r\nline3') + self.assertEqual(t.render({}), 'line1\nline2\nline3') + + def test_render_passes_environment_params(self): + # With trim_blocks + lstrip_blocks, block tags don't emit their surrounding whitespace. + template_code = '{% if x %}\n {% if y %}\n VALUE\n {% endif %}\n{% endif %}' + plain = ConfigTemplate(name='plain', template_code=template_code) + trimmed = ConfigTemplate( + name='trimmed', + template_code=template_code, + environment_params={'trim_blocks': True, 'lstrip_blocks': True}, + ) + ctx = {'x': True, 'y': True} + self.assertNotEqual(plain.render(ctx), trimmed.render(ctx)) + self.assertEqual(trimmed.render(ctx).strip(), 'VALUE') + + def test_environment_params_undefined_path_import(self): + # Default Undefined renders nothing for a missing variable. + default = ConfigTemplate(name='default', template_code='{{ missing }}') + self.assertEqual(default.render({}), '') + + # StrictUndefined (resolved from its dotted path) raises on access. + strict = ConfigTemplate( + name='strict', + template_code='{{ missing }}', + environment_params={'undefined': 'jinja2.StrictUndefined'}, + ) + with self.assertRaises(UndefinedError): + strict.render({}) + + def test_environment_params_finalize_path_import(self): + t = ConfigTemplate( + name='finalize', + template_code='{{ v }}', + environment_params={'finalize': 'extras.tests.test_models.finalize_none_to_dash'}, + ) + self.assertEqual(t.render({'v': None}), '-') + self.assertEqual(t.render({'v': 'abc'}), 'abc') + + def test_get_environment_params_handles_none(self): + # The environment_params field may be cleared; ensure the mixin returns a dict (not None). + t = ConfigTemplate(name='empty', template_code='ok', environment_params=None) + self.assertEqual(t.get_environment_params(), {}) + + def test_get_environment_params_resolves_path_imports(self): + t = ConfigTemplate( + name='resolve', + template_code='ok', + environment_params={'undefined': 'jinja2.StrictUndefined', 'trim_blocks': True}, + ) + params = t.get_environment_params() + self.assertIs(params['undefined'], StrictUndefined) + self.assertIs(params['trim_blocks'], True) + + def test_get_environment_params_does_not_mutate_field(self): + # Resolving path imports must not replace the string values stored on the model field. + t = ConfigTemplate( + name='no-mutate', + template_code='ok', + environment_params={'undefined': 'jinja2.StrictUndefined'}, + ) + t.get_environment_params() + t.get_environment_params() + self.assertEqual(t.environment_params, {'undefined': 'jinja2.StrictUndefined'}) + + +class RenderTemplateMixinResponseTest(TestCase): + """ + Tests for RenderTemplateMixin.render_to_response() HTTP behavior. + """ + + def test_response_default_mime_type(self): + t = ConfigTemplate(name='t', template_code='ok') + response = t.render_to_response({}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response['Content-Type'], DEFAULT_MIME_TYPE) + + def test_response_custom_mime_type(self): + t = ConfigTemplate(name='t', template_code='{}', mime_type='application/json') + response = t.render_to_response({}) + self.assertEqual(response['Content-Type'], 'application/json') + + def test_response_attachment_with_file_name(self): + t = ConfigTemplate( + name='t', template_code='ok', file_name='router1', file_extension='cfg', as_attachment=True, + ) + response = t.render_to_response({}) + self.assertEqual(response['Content-Disposition'], 'attachment; filename="router1.cfg"') + + def test_response_attachment_filename_from_queryset(self): + Site.objects.create(name='Site 1', slug='site-1') + t = ExportTemplate( + name='t', + template_code='{% for obj in queryset %}{{ obj.name }}{% endfor %}', + file_extension='txt', + as_attachment=True, + ) + response = t.render_to_response(queryset=Site.objects.all()) + self.assertEqual(response['Content-Disposition'], 'attachment; filename="netbox_sites.txt"') + + def test_response_attachment_filename_from_device_context(self): + t = ConfigTemplate(name='t', template_code='ok', as_attachment=True) + device = SimpleNamespace(name='router1') + response = t.render_to_response(context={'device': device}) + self.assertEqual(response['Content-Disposition'], 'attachment; filename="router1"') + + def test_response_attachment_fallback_filename(self): + # No file_name, no queryset, no device/vm key in context: filename falls back to "output". + t = ConfigTemplate(name='t', template_code='ok', as_attachment=True) + response = t.render_to_response({}) + self.assertEqual(response['Content-Disposition'], 'attachment; filename="output"') + + def test_response_as_attachment_false_omits_disposition(self): + t = ConfigTemplate(name='t', template_code='ok', file_name='router1', as_attachment=False) + response = t.render_to_response({}) + self.assertNotIn('Content-Disposition', response) + + def test_response_body_matches_render(self): + t = ConfigTemplate(name='t', template_code='Hello {{ name }}') + rendered = t.render({'name': 'world'}) + response = t.render_to_response({'name': 'world'}) + self.assertEqual(response.content.decode(), rendered) + + +class ExportTemplateRenderTest(TestCase): + """ + Tests for ExportTemplate.render() with a queryset bound into the template context. + """ + + @classmethod + def setUpTestData(cls): + Site.objects.bulk_create([ + Site(name='Site A', slug='site-a'), + Site(name='Site B', slug='site-b'), + Site(name='Site C', slug='site-c'), + ]) + + def test_render_iterates_queryset(self): + t = ExportTemplate( + name='sites', + template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', + ) + queryset = Site.objects.order_by('name') + output = t.render(queryset=queryset) + self.assertEqual(output, 'Site A\nSite B\nSite C\n') + + def test_render_to_response_for_queryset(self): + t = ExportTemplate( + name='sites', + template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', + file_extension='txt', + ) + response = t.render_to_response(queryset=Site.objects.order_by('name')) + self.assertEqual(response.status_code, 200) + self.assertEqual(response['Content-Type'], DEFAULT_MIME_TYPE) + self.assertEqual(response['Content-Disposition'], 'attachment; filename="netbox_sites.txt"') + self.assertEqual(response.content.decode(), 'Site A\nSite B\nSite C\n') + + class EventRuleTestCase(TestCase): def test_action_data_clean_accepts_dict(self): diff --git a/netbox/extras/tests/test_views.py b/netbox/extras/tests/test_views.py index 42ea6ce16..3d5bd48d1 100644 --- a/netbox/extras/tests/test_views.py +++ b/netbox/extras/tests/test_views.py @@ -370,6 +370,59 @@ class ExportTemplateTestCase(ViewTestCases.PrimaryObjectViewTestCase): } +class ExportTemplateExportFlowTest(TestCase): + """ + End-to-end test for ExportTemplate invocation via a list view's ?export= query param. + """ + + @classmethod + def setUpTestData(cls): + Site.objects.bulk_create([ + Site(name='Site A', slug='site-a'), + Site(name='Site B', slug='site-b'), + ]) + + site_type = ObjectType.objects.get_for_model(Site) + + ok_template = ExportTemplate.objects.create( + name='Sites Export', + template_code='{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', + mime_type='text/plain', + file_extension='txt', + ) + ok_template.object_types.set([site_type]) + + broken_template = ExportTemplate.objects.create( + name='Broken Export', + template_code='{% for obj in queryset %}{{ obj.name ', # unterminated expression + ) + broken_template.object_types.set([site_type]) + + def test_export_template_invocation(self): + self.add_permissions('dcim.view_site') + url = reverse('dcim:site_list') + + response = self.client.get(f'{url}?export=Sites Export') + self.assertEqual(response.status_code, 200) + self.assertEqual(response['Content-Type'], 'text/plain') + self.assertEqual(response['Content-Disposition'], 'attachment; filename="netbox_sites.txt"') + # The rendered queryset reflects whatever ordering the list view applies. Assert on set + # membership rather than line order so the test isn't coupled to Site's natural ordering. + rendered_names = set(filter(None, response.content.decode().split('\n'))) + self.assertEqual(rendered_names, {'Site A', 'Site B'}) + + def test_export_template_render_error_redirects(self): + self.add_permissions('dcim.view_site') + url = reverse('dcim:site_list') + + # A broken template surfaces an exception during render; the view catches it and redirects + # back to the (filtered) list view rather than returning a 500. + response = self.client.get(f'{url}?export=Broken Export') + self.assertEqual(response.status_code, 302) + self.assertTrue(response['Location'].startswith(url)) + self.assertNotIn('export=', response['Location']) + + class WebhookTestCase(ViewTestCases.PrimaryObjectViewTestCase): model = Webhook From 7b948af4b6e6a3261694b9742000567b34a0d56d Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 06:01:27 +0000 Subject: [PATCH 029/131] Update source translation strings --- netbox/translations/en/LC_MESSAGES/django.po | 34 ++++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/netbox/translations/en/LC_MESSAGES/django.po b/netbox/translations/en/LC_MESSAGES/django.po index 21371e7f3..757321fab 100644 --- a/netbox/translations/en/LC_MESSAGES/django.po +++ b/netbox/translations/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-08 05:41+0000\n" +"POT-Creation-Date: 2026-05-12 06:01+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -13037,67 +13037,67 @@ msgstr "" msgid "Cannot delete stores from registry" msgstr "" -#: netbox/netbox/settings.py:859 +#: netbox/netbox/settings.py:860 msgid "Czech" msgstr "" -#: netbox/netbox/settings.py:860 +#: netbox/netbox/settings.py:861 msgid "Danish" msgstr "" -#: netbox/netbox/settings.py:861 +#: netbox/netbox/settings.py:862 msgid "German" msgstr "" -#: netbox/netbox/settings.py:862 +#: netbox/netbox/settings.py:863 msgid "English" msgstr "" -#: netbox/netbox/settings.py:863 +#: netbox/netbox/settings.py:864 msgid "Spanish" msgstr "" -#: netbox/netbox/settings.py:864 +#: netbox/netbox/settings.py:865 msgid "French" msgstr "" -#: netbox/netbox/settings.py:865 +#: netbox/netbox/settings.py:866 msgid "Italian" msgstr "" -#: netbox/netbox/settings.py:866 +#: netbox/netbox/settings.py:867 msgid "Japanese" msgstr "" -#: netbox/netbox/settings.py:867 +#: netbox/netbox/settings.py:868 msgid "Latvian" msgstr "" -#: netbox/netbox/settings.py:868 +#: netbox/netbox/settings.py:869 msgid "Dutch" msgstr "" -#: netbox/netbox/settings.py:869 +#: netbox/netbox/settings.py:870 msgid "Polish" msgstr "" -#: netbox/netbox/settings.py:870 +#: netbox/netbox/settings.py:871 msgid "Portuguese" msgstr "" -#: netbox/netbox/settings.py:871 +#: netbox/netbox/settings.py:872 msgid "Russian" msgstr "" -#: netbox/netbox/settings.py:872 +#: netbox/netbox/settings.py:873 msgid "Turkish" msgstr "" -#: netbox/netbox/settings.py:873 +#: netbox/netbox/settings.py:874 msgid "Ukrainian" msgstr "" -#: netbox/netbox/settings.py:874 +#: netbox/netbox/settings.py:875 msgid "Chinese" msgstr "" From baeead17189054a8bb8ca4004bdb1dc9a2e2186b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 7 May 2026 16:27:47 -0400 Subject: [PATCH 030/131] Closes #22146: Avoid renumbering MPTT trees when creating module bays --- netbox/dcim/models/device_components.py | 61 ++++++- netbox/dcim/tests/test_models.py | 208 ++++++++++++++++++++++++ 2 files changed, 268 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index e3691fd6c..cf80b94c4 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -1313,6 +1313,29 @@ class RearPort(ModularComponentModel, CabledObjectModel, TrackingModelMixin): # Bays # +class ModuleBayManager(TreeManager): + """ + Order ModuleBays by the natural-sort name of each tree's root, then by MPTT + left value within the tree. Combined with the root-insert bypass in + ModuleBay.save(), this lets us keep MPTTMeta.order_insertion_by for cheap + intra-tree sibling placement while skipping the global tree_id renumbering + it would otherwise perform on every root insert. + """ + def get_queryset(self, *args, **kwargs): + # Use the raw manager to avoid recursing through this get_queryset() when + # building the annotation subquery. + root_name = self.model._objects_raw.filter( + tree_id=models.OuterRef('tree_id'), + level=0, + ).values('name')[:1] + return super().get_queryset(*args, **kwargs).annotate( + _root_name=models.Subquery( + root_name, + output_field=models.CharField(db_collation='natural_sort'), + ) + ).order_by('_root_name', 'lft') + + class ModuleBay(ModularComponentModel, TrackingModelMixin, MPTTModel): """ An empty space within a Device which can house a child device @@ -1337,7 +1360,10 @@ class ModuleBay(ModularComponentModel, TrackingModelMixin, MPTTModel): default=True, ) - objects = TreeManager() + objects = ModuleBayManager() + # Plain TreeManager used by ModuleBayManager to build the _root_name subquery + # without recursing through our annotated get_queryset(). + _objects_raw = TreeManager() clone_fields = ('device', 'enabled') @@ -1355,6 +1381,9 @@ class ModuleBay(ModularComponentModel, TrackingModelMixin, MPTTModel): verbose_name_plural = _('module bays') class MPTTMeta: + # Used for placing siblings within a single tree at insert time. Costs + # are bounded to that tree's rows. Cross-tree (root) insertion is + # handled in save() to avoid the O(N) tree_id shift this would trigger. order_insertion_by = ('name',) def clean(self): @@ -1376,6 +1405,36 @@ class ModuleBay(ModularComponentModel, TrackingModelMixin, MPTTModel): self.parent = self.module.module_bay else: self.parent = None + opts = self._mptt_meta + # For new root nodes, allocate the next tree_id and pre-set MPTT fields + # so super().save() skips MPTT's order_insertion_by-driven insertion + # path. That path would otherwise UPDATE every later tree_id on each + # root insert (NB-2800). Children still go through MPTT, which keeps + # siblings in name order via the same order_insertion_by setting. + if self._state.adding and self.parent_id is None and not self.lft and not self.rght: + max_tree_id = ModuleBay._objects_raw.aggregate( + models.Max('tree_id') + )['tree_id__max'] or 0 + self.tree_id = max_tree_id + 1 + self.lft = 1 + self.rght = 2 + self.level = 0 + elif ( + not self._state.adding + and self.parent_id is None + and self._mptt_cached_fields.get(opts.parent_attr) is None + ): + # Existing root being updated. Spoof the cached order_insertion_by + # values so MPTT's same_order check passes and it skips its reorder + # path, which would UPDATE every later tree_id on each root rename. + # ModuleBayManager._root_name recovers display order at query time, + # so the tree_id reshuffling would be wasted work. Child renames + # and root<->child transitions intentionally fall through to MPTT. + for field_name in opts.order_insertion_by: + field_name = field_name.lstrip('-') + self._mptt_cached_fields[field_name] = opts.get_raw_field_value( + self, field_name + ) super().save(*args, **kwargs) @property diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index 3e3d1c526..5462257e1 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -915,6 +915,214 @@ class ModuleBayTestCase(TestCase): module_1.clean() module_1.save() + @tag('regression') # #22146 + def test_module_bay_ordering_after_recreate(self): + """ + Module bays must remain in name order after a delete-and-recreate cycle, + even though MPTT no longer renumbers tree_ids on root insertion. + """ + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + site = Site.objects.first() + device = Device.objects.create( + name='Ordering Test Device', + device_type=device_type, + role=device_role, + site=site, + ) + for name in ('Bay 1', 'Bay 2', 'Bay 3', 'Bay 4'): + ModuleBay.objects.create(device=device, name=name) + + ModuleBay.objects.get(device=device, name='Bay 3').delete() + ModuleBay.objects.create(device=device, name='Bay 3') + + names = list(ModuleBay.objects.filter(device=device).values_list('name', flat=True)) + self.assertEqual(names, ['Bay 1', 'Bay 2', 'Bay 3', 'Bay 4']) + + @tag('regression') # #22146 + def test_module_bay_natural_ordering(self): + """ + Module bays must be returned in natural (numeric-aware) order, e.g. + "Bay 2" before "Bay 10". + """ + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + site = Site.objects.first() + device = Device.objects.create( + name='Natural Sort Device', + device_type=device_type, + role=device_role, + site=site, + ) + # Insert in non-natural order to confirm sort is not insertion-driven. + for name in ('Bay 10', 'Bay 1', 'Bay 2', 'Bay 11'): + ModuleBay.objects.create(device=device, name=name) + + names = list(ModuleBay.objects.filter(device=device).values_list('name', flat=True)) + self.assertEqual(names, ['Bay 1', 'Bay 2', 'Bay 10', 'Bay 11']) + + @tag('regression') # #22146 + def test_child_module_bay_ordering(self): + """ + Child module bays inside a module must be returned in name order even + when inserted out of order. + """ + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + site = Site.objects.first() + device = Device.objects.create( + name='Child Ordering Device', + device_type=device_type, + role=device_role, + site=site, + ) + root_bay = ModuleBay.objects.create(device=device, name='Bay 1') + manufacturer = Manufacturer.objects.first() + module_type = ModuleType.objects.create( + manufacturer=manufacturer, model='Child Ordering Type' + ) + module = Module.objects.create( + device=device, module_bay=root_bay, module_type=module_type + ) + # Insert children out of name order. + for name in ('Bay 1.1', 'Bay 1.3', 'Bay 1.2'): + ModuleBay.objects.create(device=device, module=module, name=name) + + names = list(ModuleBay.objects.filter(device=device).values_list('name', flat=True)) + self.assertEqual(names, ['Bay 1', 'Bay 1.1', 'Bay 1.2', 'Bay 1.3']) + + @tag('regression') # #22146 + def test_root_module_bay_rename_preserves_tree_ids(self): + """ + Renaming a root module bay must not renumber any other root tree's + tree_id. The renamed bay's own tree_id is also expected to remain + stable, but the load-bearing assertion is that the *other* bays are + not shifted. + """ + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + site = Site.objects.first() + device = Device.objects.create( + name='Rename TreeID Device', + device_type=device_type, + role=device_role, + site=site, + ) + for name in ('Bay 1', 'Bay 2', 'Bay 3', 'Bay 4'): + ModuleBay.objects.create(device=device, name=name) + + tree_ids_before = { + bay.name: bay.tree_id + for bay in ModuleBay.objects.filter(device=device) + } + + bay = ModuleBay.objects.get(device=device, name='Bay 2') + bay.name = 'Bay 99' + bay.save() + + tree_ids_after = { + bay.name: bay.tree_id + for bay in ModuleBay.objects.filter(device=device) + } + for name in ('Bay 1', 'Bay 3', 'Bay 4'): + self.assertEqual(tree_ids_after[name], tree_ids_before[name]) + self.assertEqual(tree_ids_after['Bay 99'], tree_ids_before['Bay 2']) + + @tag('regression') # #22146 + def test_root_module_bay_rename_updates_display_order(self): + """ + Even though renaming a root module bay does not renumber tree_ids, + the manager's _root_name annotation must reflect the new name so the + display ordering is correct. + """ + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + site = Site.objects.first() + device = Device.objects.create( + name='Rename Order Device', + device_type=device_type, + role=device_role, + site=site, + ) + for name in ('Bay 1', 'Bay 2', 'Bay 3'): + ModuleBay.objects.create(device=device, name=name) + + bay = ModuleBay.objects.get(device=device, name='Bay 1') + bay.name = 'Bay 4' + bay.save() + + names = list(ModuleBay.objects.filter(device=device).values_list('name', flat=True)) + self.assertEqual(names, ['Bay 2', 'Bay 3', 'Bay 4']) + + @tag('regression') # #22146 + def test_child_module_bay_rename_preserves_intra_tree_ordering(self): + """ + Renaming a *child* module bay must still trigger MPTT's intra-tree + reorder, so siblings appear in name order after the rename. The + rename-bypass only covers root bays. + """ + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + site = Site.objects.first() + device = Device.objects.create( + name='Child Rename Device', + device_type=device_type, + role=device_role, + site=site, + ) + root_bay = ModuleBay.objects.create(device=device, name='Bay 1') + manufacturer = Manufacturer.objects.first() + module_type = ModuleType.objects.create( + manufacturer=manufacturer, model='Child Rename Type' + ) + module = Module.objects.create( + device=device, module_bay=root_bay, module_type=module_type + ) + for name in ('Bay 1.1', 'Bay 1.2', 'Bay 1.3'): + ModuleBay.objects.create(device=device, module=module, name=name) + + child = ModuleBay.objects.get(device=device, name='Bay 1.1') + child.name = 'Bay 1.4' + child.save() + + names = list(ModuleBay.objects.filter(device=device).values_list('name', flat=True)) + self.assertEqual(names, ['Bay 1', 'Bay 1.2', 'Bay 1.3', 'Bay 1.4']) + + @tag('regression') # #22146 + def test_root_to_child_transition_still_relocates(self): + """ + Promoting an existing root module bay to a child (by assigning a + module) must still flow through MPTT's normal move logic. The + rename-bypass must not suppress legitimate parent changes. + """ + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + site = Site.objects.first() + device = Device.objects.create( + name='Root To Child Device', + device_type=device_type, + role=device_role, + site=site, + ) + host_bay = ModuleBay.objects.create(device=device, name='Host Bay') + movable_bay = ModuleBay.objects.create(device=device, name='Movable Bay') + + manufacturer = Manufacturer.objects.first() + module_type = ModuleType.objects.create( + manufacturer=manufacturer, model='Root To Child Type' + ) + host_module = Module.objects.create( + device=device, module_bay=host_bay, module_type=module_type + ) + + movable_bay.module = host_module + movable_bay.save() + + movable_bay.refresh_from_db() + host_bay.refresh_from_db() + self.assertEqual(movable_bay.parent_id, host_bay.pk) + self.assertEqual(movable_bay.tree_id, host_bay.tree_id) + def test_single_module_token(self): device_type = DeviceType.objects.first() device_role = DeviceRole.objects.first() From b1412514f1eb7cda94eddcb6839159d90de093b7 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 13 May 2026 09:50:32 -0400 Subject: [PATCH 031/131] Closes #22104: Avoid retracing paths when deleting Cables (#22167) --- netbox/dcim/models/cables.py | 26 ++++++++++++++++++++++++++ netbox/dcim/signals.py | 6 ++++++ netbox/dcim/tests/test_cablepaths.py | 12 ++++++++++++ 3 files changed, 44 insertions(+) diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index fb0d87067..dd067ee2c 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -1,5 +1,6 @@ import itertools import logging +import threading from collections import Counter from django.contrib.contenttypes.fields import GenericForeignKey @@ -76,6 +77,11 @@ class Cable(PrimaryModel): """ A physical connection between two endpoints. """ + # Per-thread tracking of Cable PKs currently in delete(); referenced by + # dcim.signals.nullify_connected_endpoints to skip per-CableTermination + # cable path retracing during cascade (retrace_cable_paths handles it once). + _deletion_tracking = threading.local() + type = models.CharField( verbose_name=_('type'), max_length=50, @@ -343,6 +349,26 @@ class Cable(PrimaryModel): except UnsupportedCablePath as e: raise AbortRequest(e) + def delete(self, *args, **kwargs): + # Track this Cable as being deleted so the post_delete signal handler + # for cascaded CableTerminations can skip redundant path retracing; + # retrace_cable_paths() will retrace each affected path once after the + # Cable itself is deleted. Cache the PK locally because super().delete() + # clears self.pk before the finally block runs. The tracking set lives + # on a threading.local() to isolate concurrent deletions across threads. + if not hasattr(Cable._deletion_tracking, 'pks'): + Cable._deletion_tracking.pks = set() + pk = self.pk + Cable._deletion_tracking.pks.add(pk) + try: + return super().delete(*args, **kwargs) + finally: + Cable._deletion_tracking.pks.discard(pk) + + @classmethod + def _is_being_deleted(cls, pk): + return pk in getattr(cls._deletion_tracking, 'pks', ()) + def clone(self): """ Return attributes suitable for cloning this cable. diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index dd37817d1..8d5baf6d1 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -185,6 +185,12 @@ def nullify_connected_endpoints(instance, **kwargs): model = instance.termination_type.model_class() model.objects.filter(pk=instance.termination_id).update(cable=None, cable_end='') + # If the parent Cable is being deleted in this same operation, skip the + # per-termination retrace; retrace_cable_paths() will retrace each affected + # path once after the Cable is deleted. + if Cable._is_being_deleted(instance.cable_id): + return + for cablepath in CablePath.objects.filter(_nodes__contains=instance.cable): # Remove the deleted CableTermination if it's one of the path's originating nodes if instance.termination in cablepath.origins: diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index 9d7be50ef..9221d00ce 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -55,6 +55,18 @@ class LegacyCablePathTestCase(CablePathTestCase): # Check that all CablePaths have been deleted self.assertEqual(CablePath.objects.count(), 0) + # Check that connected interfaces are fully cleaned up + interface1.refresh_from_db() + interface2.refresh_from_db() + + self.assertIsNone(interface1.cable_id) + self.assertEqual(interface1.cable_end, '') + self.assertPathIsNotSet(interface1) + + self.assertIsNone(interface2.cable_id) + self.assertEqual(interface2.cable_end, '') + self.assertPathIsNotSet(interface2) + def test_102_consoleport_to_consoleserverport(self): """ [CP1] --C1-- [CSP1] From 0ee59d7371e93a98bcf1c691e0499bf4275fe651 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 13 May 2026 11:38:17 -0400 Subject: [PATCH 032/131] Closes #22081: Include plaintext when creating v2 tokens via REST API (#22160) --- netbox/users/api/serializers_/tokens.py | 18 ++++++++++ netbox/users/tests/test_api.py | 47 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/netbox/users/api/serializers_/tokens.py b/netbox/users/api/serializers_/tokens.py index 60f094239..ce467e1a6 100644 --- a/netbox/users/api/serializers_/tokens.py +++ b/netbox/users/api/serializers_/tokens.py @@ -57,6 +57,24 @@ class TokenSerializer(ValidatedModelSerializer): return super().validate(data) + def create(self, validated_data): + instance = super().create(validated_data) + # The plaintext token is only available in memory after save(); v2 tokens persist only an + # HMAC digest, so it can't be recovered later. Stash it on the request so to_representation() + # can return it even after the viewset re-fetches the instance from the database. + if request := self.context.get('request'): + if not hasattr(request, '_token_plaintexts'): + request._token_plaintexts = {} + request._token_plaintexts[instance.pk] = instance.token + return instance + + def to_representation(self, instance): + data = super().to_representation(instance) + if not data.get('token') and (request := self.context.get('request')): + if plaintext := getattr(request, '_token_plaintexts', {}).get(instance.pk): + data['token'] = plaintext + return data + class TokenProvisionSerializer(TokenSerializer): user = UserSerializer( diff --git a/netbox/users/tests/test_api.py b/netbox/users/tests/test_api.py index e05e7f33b..a50ce74bc 100644 --- a/netbox/users/tests/test_api.py +++ b/netbox/users/tests/test_api.py @@ -310,6 +310,53 @@ class TokenTestCase( response = self.client.post(url, data, format='json', **self.header) self.assertEqual(response.status_code, 201) + def test_create_token_returns_plaintext(self): + """ + Creating a Token via the REST API must return the usable plaintext value in the response. + For v2 tokens this value cannot be recovered later because the database stores only an + HMAC digest. + """ + self.add_permissions('users.add_token') + user = User.objects.create_user(username='token_plaintext_user') + url = reverse('users-api:token-list') + + response = self.client.post(url, {'user': user.pk}, format='json', **self.header) + self.assertEqual(response.status_code, 201) + self.assertIsNotNone(response.data['token']) + self.assertEqual(len(response.data['token']), TOKEN_DEFAULT_LENGTH) + + # The returned plaintext must authenticate against the stored token + token = Token.objects.get(pk=response.data['id']) + self.assertTrue(token.validate(response.data['token'])) + + def test_bulk_create_tokens_returns_plaintexts(self): + """ + Bulk-creating Tokens via the REST API must return the plaintext value for each created + Token in the response. + """ + self.add_permissions('users.add_token') + users = [ + User.objects.create_user(username='token_bulk_user1'), + User.objects.create_user(username='token_bulk_user2'), + ] + data = [{'user': u.pk} for u in users] + url = reverse('users-api:token-list') + + response = self.client.post(url, data, format='json', **self.header) + self.assertEqual(response.status_code, 201) + self.assertEqual(len(response.data), len(data)) + + plaintexts = set() + for obj in response.data: + self.assertIsNotNone(obj['token']) + self.assertEqual(len(obj['token']), TOKEN_DEFAULT_LENGTH) + plaintexts.add(obj['token']) + token = Token.objects.get(pk=obj['id']) + self.assertTrue(token.validate(obj['token'])) + + # Each token should be unique + self.assertEqual(len(plaintexts), len(data)) + def test_reassign_token(self): """ Check that a Token cannot be reassigned to another User. From eeca184cb882d978ddd3f2c68fe9540124b4736a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 13 May 2026 11:45:59 -0400 Subject: [PATCH 033/131] Closes #22057: Add GraphQL filters for notifications and subscriptions (#22175) --- netbox/extras/graphql/filters.py | 34 ++++++++++++++++++++++++++++++-- netbox/extras/graphql/types.py | 4 ++-- netbox/extras/tests/test_api.py | 6 ++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/netbox/extras/graphql/filters.py b/netbox/extras/graphql/filters.py index 30de07f05..2f5ea4dee 100644 --- a/netbox/extras/graphql/filters.py +++ b/netbox/extras/graphql/filters.py @@ -1,15 +1,16 @@ +from datetime import datetime from typing import TYPE_CHECKING, Annotated import strawberry import strawberry_django from django.db.models import Q, QuerySet from strawberry.scalars import ID -from strawberry_django import BaseFilterLookup, FilterLookup, StrFilterLookup +from strawberry_django import BaseFilterLookup, DatetimeFilterLookup, FilterLookup, StrFilterLookup from extras import models from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin from netbox.graphql.filter_mixins import SyncedDataFilterMixin -from netbox.graphql.filters import ChangeLoggedModelFilter, PrimaryModelFilter +from netbox.graphql.filters import BaseModelFilter, ChangeLoggedModelFilter, PrimaryModelFilter if TYPE_CHECKING: from core.graphql.filters import ContentTypeFilter @@ -41,8 +42,10 @@ __all__ = ( 'ExportTemplateFilter', 'ImageAttachmentFilter', 'JournalEntryFilter', + 'NotificationFilter', 'NotificationGroupFilter', 'SavedFilterFilter', + 'SubscriptionFilter', 'TableConfigFilter', 'TagFilter', 'WebhookFilter', @@ -291,6 +294,21 @@ class JournalEntryFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedM comments: StrFilterLookup[str] | None = strawberry_django.filter_field() +@strawberry_django.filter_type(models.Notification, lookups=True) +class NotificationFilter(BaseModelFilter): + created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + read: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() + user_id: ID | None = strawberry_django.filter_field() + object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( + strawberry_django.filter_field() + ) + object_type_id: ID | None = strawberry_django.filter_field() + object_id: ID | None = strawberry_django.filter_field() + object_repr: StrFilterLookup[str] | None = strawberry_django.filter_field() + event_type: StrFilterLookup[str] | None = strawberry_django.filter_field() + + @strawberry_django.filter_type(models.NotificationGroup, lookups=True) class NotificationGroupFilter(ChangeLoggedModelFilter): name: StrFilterLookup[str] | None = strawberry_django.filter_field() @@ -316,6 +334,18 @@ class SavedFilterFilter(ChangeLoggedModelFilter): ) +@strawberry_django.filter_type(models.Subscription, lookups=True) +class SubscriptionFilter(BaseModelFilter): + created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() + user_id: ID | None = strawberry_django.filter_field() + object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( + strawberry_django.filter_field() + ) + object_type_id: ID | None = strawberry_django.filter_field() + object_id: ID | None = strawberry_django.filter_field() + + @strawberry_django.filter_type(models.TableConfig, lookups=True) class TableConfigFilter(ChangeLoggedModelFilter): name: StrFilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/extras/graphql/types.py b/netbox/extras/graphql/types.py index bed77aad0..42241543c 100644 --- a/netbox/extras/graphql/types.py +++ b/netbox/extras/graphql/types.py @@ -161,7 +161,7 @@ class JournalEntryType(CustomFieldsMixin, TagsMixin, ObjectType): @strawberry_django.type( models.Notification, - # filters=NotificationFilter + filters=NotificationFilter, pagination=True ) class NotificationType(ObjectType): @@ -190,7 +190,7 @@ class SavedFilterType(OwnerMixin, ObjectType): @strawberry_django.type( models.Subscription, - # filters=NotificationFilter + filters=SubscriptionFilter, pagination=True ) class SubscriptionType(ObjectType): diff --git a/netbox/extras/tests/test_api.py b/netbox/extras/tests/test_api.py index d9456c128..17d80f08f 100644 --- a/netbox/extras/tests/test_api.py +++ b/netbox/extras/tests/test_api.py @@ -1239,6 +1239,9 @@ class CreatedUpdatedFilterTestCase(APITestCase): class SubscriptionTestCase(APIViewTestCases.APIViewTestCase): model = Subscription brief_fields = ['display', 'id', 'object_id', 'object_type', 'url', 'user'] + graphql_filter = { + 'id': {'lookup': 'gt', 'value': '0'}, + } @classmethod def setUpTestData(cls): @@ -1378,6 +1381,9 @@ class NotificationTestCase(APIViewTestCases.APIViewTestCase): bulk_update_data = { 'read': now(), } + graphql_filter = { + 'event_type': {'lookup': 'exact', 'value': OBJECT_CREATED}, + } @classmethod def setUpTestData(cls): From e60ba2859dffe953d4f59670e9b991e03ccf3206 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Wed, 13 May 2026 18:06:07 +0200 Subject: [PATCH 034/131] test(signals): Add signal handler test coverage Add comprehensive test coverage for signal handlers in circuits, core, dcim, extras, ipam, users, virtualization, and wireless, including cable path rebuilding, change logging, data source sync, scope propagation, and notification dispatch logic. Fixes #22098 --- netbox/circuits/tests/test_signals.py | 92 ++++ netbox/core/tests/test_signals.py | 505 ++++++++++++++++++++ netbox/dcim/tests/test_signals.py | 488 +++++++++++++++++++ netbox/extras/tests/test_signals.py | 297 ++++++++++++ netbox/ipam/tests/test_signals.py | 231 +++++++++ netbox/users/tests/test_signals.py | 128 +++++ netbox/virtualization/tests/test_signals.py | 85 ++++ netbox/wireless/tests/test_signals.py | 97 ++++ 8 files changed, 1923 insertions(+) create mode 100644 netbox/circuits/tests/test_signals.py create mode 100644 netbox/core/tests/test_signals.py create mode 100644 netbox/dcim/tests/test_signals.py create mode 100644 netbox/extras/tests/test_signals.py create mode 100644 netbox/ipam/tests/test_signals.py create mode 100644 netbox/users/tests/test_signals.py create mode 100644 netbox/virtualization/tests/test_signals.py create mode 100644 netbox/wireless/tests/test_signals.py diff --git a/netbox/circuits/tests/test_signals.py b/netbox/circuits/tests/test_signals.py new file mode 100644 index 000000000..e553bcf92 --- /dev/null +++ b/netbox/circuits/tests/test_signals.py @@ -0,0 +1,92 @@ +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +from django.test import SimpleTestCase, TestCase + +from circuits import signals +from circuits.models import Circuit, CircuitTermination, CircuitType, Provider +from dcim.models import ( + Cable, + CablePath, + Device, + DeviceRole, + DeviceType, + Interface, + Manufacturer, + Site, +) + + +class RebuildCablepathsSignalTestCase(TestCase): + """ + Verify circuits.signals.rebuild_cablepaths retraces paths that cross the peer termination + when a CircuitTermination is saved or deleted. + """ + + @classmethod + def setUpTestData(cls): + cls.site = Site.objects.create(name='Site', slug='site') + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type') + device_role = DeviceRole.objects.create(name='Device Role', slug='device-role') + cls.device = Device.objects.create(site=cls.site, device_type=device_type, role=device_role, name='Device 1') + provider = Provider.objects.create(name='Provider', slug='provider') + circuit_type = CircuitType.objects.create(name='Circuit Type', slug='circuit-type') + cls.circuit = Circuit.objects.create(provider=provider, type=circuit_type, cid='Circuit 1') + + def test_saving_termination_rebuilds_peer_path(self): + interface = Interface.objects.create(device=self.device, name='Interface 1') + site_z = Site.objects.create(name='Site Z', slug='site-z') + termination_a = CircuitTermination.objects.create(circuit=self.circuit, termination=self.site, term_side='A') + termination_z = CircuitTermination.objects.create(circuit=self.circuit, termination=site_z, term_side='Z') + Cable(a_terminations=[interface], b_terminations=[termination_a]).save() + original_path = CablePath.objects.get() + + # Saving the Z (peer) termination should cause rebuild_paths to run for the A peer. + with patch('circuits.signals.rebuild_paths') as rebuild_paths: + termination_z.save() + + rebuild_paths.assert_called_once() + rebuilt_for = rebuild_paths.call_args.args[0] + self.assertEqual([t.pk for t in rebuilt_for], [termination_a.pk]) + + # Without patching, the real signal should retrace the path successfully. + termination_z.save() + self.assertEqual(CablePath.objects.count(), 1) + self.assertNotEqual(CablePath.objects.get().pk, original_path.pk) + + def test_deleting_termination_rebuilds_peer_path(self): + site_z = Site.objects.create(name='Site Z', slug='site-z') + termination_a = CircuitTermination.objects.create(circuit=self.circuit, termination=self.site, term_side='A') + termination_z = CircuitTermination.objects.create(circuit=self.circuit, termination=site_z, term_side='Z') + + with patch('circuits.signals.rebuild_paths') as rebuild_paths: + termination_z.delete() + + rebuild_paths.assert_called_once() + rebuilt_for = rebuild_paths.call_args.args[0] + self.assertEqual([t.pk for t in rebuilt_for], [termination_a.pk]) + + def test_saving_termination_without_peer_does_not_rebuild(self): + termination = CircuitTermination.objects.create(circuit=self.circuit, termination=self.site, term_side='A') + + with patch('circuits.signals.rebuild_paths') as rebuild_paths: + termination.save() + + rebuild_paths.assert_not_called() + + +class RebuildCablepathsDirectHandlerTestCase(SimpleTestCase): + """ + Direct-call tests for rebuild_cablepaths branches that are not reachable through + normal model operations (e.g. raw=True is only set by Django's loaddata pathway). + """ + + def test_raw_import_skips_peer_lookup_and_rebuild(self): + instance = SimpleNamespace(get_peer_termination=MagicMock()) + + with patch.object(signals, 'rebuild_paths') as rebuild_paths: + signals.rebuild_cablepaths(instance=instance, raw=True) + + instance.get_peer_termination.assert_not_called() + rebuild_paths.assert_not_called() diff --git a/netbox/core/tests/test_signals.py b/netbox/core/tests/test_signals.py new file mode 100644 index 000000000..9a78a04f2 --- /dev/null +++ b/netbox/core/tests/test_signals.py @@ -0,0 +1,505 @@ +import uuid +from types import SimpleNamespace +from unittest.mock import MagicMock, Mock, patch + +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ValidationError +from django.core.signals import request_finished +from django.db import transaction +from django.test import RequestFactory, SimpleTestCase, TestCase, override_settings + +from core import signals +from core.choices import DataSourceStatusChoices, JobStatusChoices, ObjectChangeActionChoices +from core.models import ConfigRevision, DataSource, ObjectChange, ObjectType +from core.signals import _signals_received, clear_events, post_sync +from dcim.models import Site, SiteGroup +from extras.models import Tag +from extras.validators import CustomValidator +from netbox.context import events_queue +from netbox.context_managers import event_tracking +from users.models import User +from utilities.exceptions import AbortRequest + + +def _build_request(user): + request = RequestFactory().get('/') + request.id = uuid.uuid4() + request.user = user + return request + + +class UpdateObjectTypesSignalTestCase(TestCase): + """ + Verify core.signals.update_object_types has registered an ObjectType for known + models, with the expected public flag and feature set. + """ + + def test_public_model_object_type_is_registered(self): + ot = ObjectType.objects.get(app_label='dcim', model='site') + self.assertTrue(ot.public) + # Site supports several features — verify a couple representative ones. + self.assertIn('custom_fields', ot.features) + self.assertIn('tags', ot.features) + + def test_private_model_object_type_is_registered_as_non_public(self): + ot = ObjectType.objects.get(app_label='dcim', model='cablepath') + self.assertFalse(ot.public) + + +class HandleChangedObjectSignalTestCase(TestCase): + """ + Verify core.signals.handle_changed_object writes an ObjectChange and increments + metric counters whenever a tracked object is created or updated within a request. + """ + + @classmethod + def setUpTestData(cls): + cls.user = User.objects.create_user(username='alice', password='pw') + + def test_create_records_an_objectchange(self): + request = _build_request(self.user) + with event_tracking(request): + site = Site.objects.create(name='Site 1', slug='site-1') + + oc = ObjectChange.objects.get( + changed_object_type=ContentType.objects.get_for_model(Site), + changed_object_id=site.pk, + ) + self.assertEqual(oc.action, ObjectChangeActionChoices.ACTION_CREATE) + self.assertEqual(oc.user, self.user) + self.assertEqual(oc.request_id, request.id) + + def test_update_records_an_objectchange(self): + site = Site.objects.create(name='Site 1', slug='site-1') + request = _build_request(self.user) + + with event_tracking(request): + site.description = 'updated' + site.save() + + ocs = ObjectChange.objects.filter( + changed_object_type=ContentType.objects.get_for_model(Site), + changed_object_id=site.pk, + ).order_by('-pk') + self.assertEqual(ocs.first().action, ObjectChangeActionChoices.ACTION_UPDATE) + + def test_no_request_skips_objectchange(self): + # Saving outside a request context (no event_tracking) should not record any + # ObjectChange entries. + Site.objects.create(name='Site 1', slug='site-1') + self.assertEqual(ObjectChange.objects.count(), 0) + + def test_m2m_tag_change_records_objectchange_with_postchange_tags(self): + site = Site.objects.create(name='Site 1', slug='site-1') + tag = Tag.objects.create(name='Important', slug='important') + request = _build_request(self.user) + + with event_tracking(request): + site.tags.add(tag) + + oc = ObjectChange.objects.filter( + changed_object_type=ContentType.objects.get_for_model(Site), + changed_object_id=site.pk, + ).first() + self.assertEqual(oc.postchange_data['tags'], ['Important']) + + +class HandleDeletedObjectSignalTestCase(TestCase): + """ + Verify core.signals.handle_deleted_object writes a delete-type ObjectChange and + respects PROTECTION_RULES. + """ + + @classmethod + def setUpTestData(cls): + cls.user = User.objects.create_user(username='alice', password='pw') + + def setUp(self): + # Reset the in-memory pre_delete bookkeeping; the signal's de-dup set lives in a + # threading.local that is not rolled back between TestCase methods. + _signals_received.pre_delete = set() + + def test_delete_records_an_objectchange(self): + site = Site.objects.create(name='Site 1', slug='site-1') + site_pk = site.pk + site_type = ContentType.objects.get_for_model(Site) + request = _build_request(self.user) + + with event_tracking(request): + site.delete() + + oc = ObjectChange.objects.get(changed_object_type=site_type, changed_object_id=site_pk) + self.assertEqual(oc.action, ObjectChangeActionChoices.ACTION_DELETE) + self.assertIsNone(oc.postchange_data) + + @override_settings(PROTECTION_RULES={'dcim.site': [CustomValidator({'name': {'neq': 'protected'}})]}) + def test_protection_rule_violation_aborts_deletion(self): + site = Site.objects.create(name='protected', slug='protected') + request = _build_request(self.user) + + with event_tracking(request): + # The signal raises AbortRequest from a pre_delete handler, which can poison + # the surrounding transaction; isolate the delete in its own atomic block. + with self.assertRaises((AbortRequest, ValidationError)): + with transaction.atomic(): + site.delete() + + self.assertTrue(Site.objects.filter(pk=site.pk).exists()) + + def test_delete_records_single_objectchange(self): + # A delete should record exactly one ObjectChange for the deleted object. + site = Site.objects.create(name='Site 1', slug='site-1') + site_pk = site.pk + site_type = ContentType.objects.get_for_model(Site) + request = _build_request(self.user) + + with event_tracking(request): + site.delete() + + ocs = ObjectChange.objects.filter(changed_object_type=site_type, changed_object_id=site_pk) + self.assertEqual(ocs.count(), 1) + + def test_duplicate_pre_delete_for_same_instance_is_ignored(self): + # Exercise the dedup short-circuit by invoking the handler twice for the + # same instance, mirroring what happens when a parent and its child are + # deleted simultaneously and the same pre_delete fires more than once. + # Only the first invocation should record an ObjectChange. + site = Site.objects.create(name='Site 1', slug='site-1') + site_pk = site.pk + site_type = ContentType.objects.get_for_model(Site) + request = _build_request(self.user) + + with event_tracking(request): + signals.handle_deleted_object(sender=Site, instance=site) + signals.handle_deleted_object(sender=Site, instance=site) + + ocs = ObjectChange.objects.filter( + changed_object_type=site_type, + changed_object_id=site_pk, + action=ObjectChangeActionChoices.ACTION_DELETE, + ) + self.assertEqual(ocs.count(), 1) + + def test_delete_records_change_for_objects_with_nulled_fk(self): + # When a parent is deleted, related objects with on_delete=SET_NULL have + # their FK cleared by the signal *and* receive a change-log entry via + # snapshot()+save(). Without the signal, Django's SET_NULL would clear + # the FK silently with no ObjectChange. + group = SiteGroup.objects.create(name='Group', slug='group') + group_pk = group.pk + site = Site.objects.create(name='Site', slug='site', group=group) + site_type = ContentType.objects.get_for_model(Site) + request = _build_request(self.user) + + with event_tracking(request): + group.delete() + + site.refresh_from_db() + self.assertIsNone(site.group) + oc = ObjectChange.objects.get( + changed_object_type=site_type, + changed_object_id=site.pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ) + self.assertEqual(oc.prechange_data['group'], group_pk) + self.assertIsNone(oc.postchange_data['group']) + + +class ClearSignalHistorySignalTestCase(TestCase): + """ + Verify core.signals.clear_signal_history resets the pre_delete bookkeeping at the + end of every request. + """ + + def test_request_finished_clears_history(self): + _signals_received.pre_delete = {('a', 1), ('b', 2)} + + request_finished.send(sender=self.__class__) + + self.assertEqual(_signals_received.pre_delete, set()) + + +class ClearEventsQueueSignalTestCase(TestCase): + """ + Verify core.signals.clear_events_queue empties the in-flight events queue when the + clear_events signal fires (e.g. during a rolled-back bulk transaction). + """ + + def test_clear_events_signal_empties_the_queue(self): + events_queue.set({'event-1': object(), 'event-2': object()}) + + clear_events.send(sender='test-suite') + + self.assertEqual(events_queue.get(), {}) + + +class EnqueueSyncJobSignalTestCase(TestCase): + """ + Verify core.signals.enqueue_sync_job schedules a recurring sync job when a + DataSource is saved with a sync_interval, and removes any existing schedule + otherwise. + """ + + def test_saving_datasource_with_interval_enqueues_sync_job(self): + with patch('core.jobs.SyncDataSourceJob') as sync_job: + DataSource.objects.create( + name='DS 1', + type='local', + source_url='/tmp/ds1', + enabled=True, + sync_interval=60, + ) + + sync_job.enqueue_once.assert_called_once() + _, kwargs = sync_job.enqueue_once.call_args + self.assertEqual(kwargs.get('interval'), 60) + + def test_disabled_datasource_clears_scheduled_jobs(self): + class ScheduledJobQueryset: + def __init__(self, jobs): + self.jobs = jobs + self.defer = Mock(return_value=self) + self.filter = Mock(return_value=self) + + def __iter__(self): + return iter(self.jobs) + + with patch('core.jobs.SyncDataSourceJob') as sync_job: + ds = DataSource.objects.create( + name='DS 1', + type='local', + source_url='/tmp/ds1', + enabled=True, + sync_interval=60, + ) + sync_job.reset_mock() + + scheduled_job = Mock() + scheduled_jobs = ScheduledJobQueryset([scheduled_job]) + sync_job.get_jobs.return_value = scheduled_jobs + ds.enabled = False + ds.sync_interval = None + ds.save() + + sync_job.get_jobs.assert_called_once_with(ds) + scheduled_jobs.defer.assert_called_once_with('data') + scheduled_jobs.filter.assert_called_once_with(interval__isnull=False, status=JobStatusChoices.STATUS_SCHEDULED) + scheduled_job.delete.assert_called_once_with() + + def test_creating_disabled_datasource_does_not_enqueue(self): + with patch('core.jobs.SyncDataSourceJob') as sync_job: + DataSource.objects.create( + name='DS 1', + type='local', + source_url='/tmp/ds1', + enabled=False, + sync_interval=None, + ) + + sync_job.enqueue_once.assert_not_called() + sync_job.get_jobs.assert_not_called() + + +class AutoSyncSignalTestCase(TestCase): + """ + Verify core.signals.auto_sync re-syncs every AutoSyncRecord linked to the + DataSource when post_sync fires. + """ + + def test_post_sync_resyncs_dependent_records(self): + ds = DataSource.objects.create( + name='DS 1', + type='local', + source_url='/tmp/ds1', + status=DataSourceStatusChoices.COMPLETED, + ) + record_a = SimpleNamespace(object=SimpleNamespace(synced=False)) + record_a.object.sync = lambda save: setattr(record_a.object, 'synced', save) + record_b = SimpleNamespace(object=SimpleNamespace(synced=False)) + record_b.object.sync = lambda save: setattr(record_b.object, 'synced', save) + + with patch('core.models.AutoSyncRecord') as autosync_model: + autosync_model.objects.filter.return_value.prefetch_related.return_value = [ + record_a, + record_b, + ] + post_sync.send(sender=ds.__class__, instance=ds) + + self.assertTrue(record_a.object.synced) + self.assertTrue(record_b.object.synced) + + +class UpdateConfigSignalTestCase(TestCase): + """ + Verify core.signals.update_config invokes activate() on a newly-saved + ConfigRevision. + """ + + def test_saving_config_revision_activates_it(self): + with patch.object(ConfigRevision, 'activate') as activate: + ConfigRevision.objects.create(data={'foo': 1}, comment='test') + + activate.assert_called_once() + + +class HandleChangedObjectDirectHandlerTestCase(SimpleTestCase): + """ + Direct-call tests for handle_changed_object branches that are not naturally + reachable through ORM operations (a real .save() always produces changes, and + Django collapses every m2m_changed action into a single dispatch the handler + cannot fully simulate via real m2m operations). + """ + + def _instance(self): + objectchange = MagicMock() + objectchange.has_changes = True + objectchange.postchange_data = {'name': 'Device 1'} + instance = SimpleNamespace( + pk=123, + _meta=SimpleNamespace(model_name='device'), + refresh_from_db=MagicMock(), + ) + instance.to_objectchange = MagicMock(return_value=objectchange) + return instance, objectchange + + def test_unhandled_m2m_action_returns_without_recording(self): + request = SimpleNamespace(id='request-id', user='alice') + instance, _ = self._instance() + current_request = MagicMock() + current_request.get.return_value = request + + with patch.object(signals, 'current_request', current_request): + signals.handle_changed_object( + sender=None, + instance=instance, + action='pre_add', + pk_set={1}, + ) + + instance.to_objectchange.assert_not_called() + + def test_objectchange_without_changes_is_not_saved(self): + request = SimpleNamespace(id='request-id', user='alice') + instance, objectchange = self._instance() + objectchange.has_changes = False + current_request = MagicMock() + current_request.get.return_value = request + events_queue_mock = MagicMock() + events_queue_mock.get.return_value = {} + update_metric = MagicMock() + + with ( + patch.object(signals, 'current_request', current_request), + patch.object(signals, 'events_queue', events_queue_mock), + patch.object(signals, 'enqueue_event') as enqueue_event, + patch.object(signals.model_updates, 'labels', return_value=update_metric), + ): + signals.handle_changed_object(sender=None, instance=instance, created=False) + + instance.to_objectchange.assert_called_once_with(ObjectChangeActionChoices.ACTION_UPDATE) + # has_changes is False, so the ObjectChange should never be saved … + objectchange.save.assert_not_called() + # … but metric counters and event enqueueing still run. + update_metric.inc.assert_called_once_with() + enqueue_event.assert_called_once() + + def test_m2m_change_updates_existing_objectchange_in_same_request(self): + request = SimpleNamespace(id='request-id', user='alice') + instance, objectchange = self._instance() + previous_change = MagicMock() + current_request = MagicMock() + current_request.get.return_value = request + events_queue_mock = MagicMock() + events_queue_mock.get.return_value = {} + objectchange_model = MagicMock() + objectchange_model.objects.filter.return_value.first.return_value = previous_change + content_type_model = MagicMock() + content_type_model.objects.get_for_model.return_value = object() + + with ( + patch.object(signals, 'current_request', current_request), + patch.object(signals, 'events_queue', events_queue_mock), + patch.object(signals, 'ObjectChange', objectchange_model), + patch.object(signals, 'ContentType', content_type_model), + patch.object(signals, 'enqueue_event'), + patch.object(signals.model_updates, 'labels', return_value=MagicMock()), + ): + signals.handle_changed_object( + sender=None, + instance=instance, + action='post_add', + pk_set={1}, + ) + + # The handler should update the existing ObjectChange instead of creating a new one. + self.assertEqual(previous_change.postchange_data, objectchange.postchange_data) + previous_change.save.assert_called_once_with() + objectchange.save.assert_not_called() + instance.refresh_from_db.assert_called_once_with() + + +class HandleDeletedObjectDirectHandlerTestCase(SimpleTestCase): + """ + Direct-call tests for handle_deleted_object branches that are hard to construct + via real model operations (notably _netbox_private skip, which requires a + private-model instance with reverse relations the test can introspect). + """ + + def setUp(self): + _signals_received.pre_delete = set() + + def test_private_model_skips_reverse_relation_processing(self): + # Build a relation the handler would normally process — a ManyToOneRel-typed + # instance pointing at a ChangeLoggingMixin subclass. The handler narrows by + # exact type (`type(relation) is ManyToOneRel`), so do not use + # MagicMock(spec=ManyToOneRel): it would be skipped before reaching the + # _netbox_private branch. Patching ManyToOneRel to this fake class keeps the + # exact-type check meaningful, so related_model.objects.filter() would be + # called if the private-model skip failed. + class FakeManyToOneRel: + pass + + class FakeChangeLoggingMixin: + pass + + class FakeRelatedModel(FakeChangeLoggingMixin): + pass + + FakeRelatedModel.objects = MagicMock() + + fake_relation = FakeManyToOneRel() + fake_relation.related_model = FakeRelatedModel + fake_relation.remote_field = SimpleNamespace(name='parent') + fake_relation.null = True + fake_relation.on_delete = object() + + sender = SimpleNamespace(_meta=SimpleNamespace(app_label='dcim', model_name='cablepath')) + request = SimpleNamespace(id='request-id', user='alice') + instance = SimpleNamespace( + pk=1, + _meta=SimpleNamespace(model_name='cablepath', related_objects=[fake_relation]), + _netbox_private=True, + ) + # Private models typically don't have to_objectchange, so skip change-log too. + config = SimpleNamespace(PROTECTION_RULES={}) + current_request = MagicMock() + current_request.get.return_value = request + events_queue_mock = MagicMock() + events_queue_mock.get.return_value = {} + + with ( + patch.object(signals, 'ManyToOneRel', FakeManyToOneRel), + patch.object(signals, 'get_config', return_value=config), + patch.object(signals, 'get_config_value_ci', return_value=[]), + patch.object(signals, 'run_validators'), + patch.object(signals, 'current_request', current_request), + patch.object(signals, 'events_queue', events_queue_mock), + patch.object(signals, 'ContentType') as content_type_model, + patch.object(signals, 'ChangeLoggingMixin', FakeChangeLoggingMixin), + patch.object(signals, 'enqueue_event'), + patch.object(signals.model_deletes, 'labels', return_value=MagicMock()), + ): + content_type_model.objects.get_for_model.return_value = object() + signals.handle_deleted_object(sender=sender, instance=instance) + + FakeRelatedModel.objects.filter.assert_not_called() diff --git a/netbox/dcim/tests/test_signals.py b/netbox/dcim/tests/test_signals.py new file mode 100644 index 000000000..9edcfbd46 --- /dev/null +++ b/netbox/dcim/tests/test_signals.py @@ -0,0 +1,488 @@ +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +from django.contrib.contenttypes.models import ContentType +from django.test import SimpleTestCase, TestCase + +from dcim import signals +from dcim.choices import CableEndChoices, LinkStatusChoices +from dcim.models import ( + Cable, + CablePath, + Device, + DeviceRole, + DeviceType, + FrontPort, + Interface, + Location, + MACAddress, + Manufacturer, + PortMapping, + PowerPanel, + Rack, + RearPort, + Site, + SiteGroup, + VirtualChassis, +) +from ipam.models import Prefix +from virtualization.models import Cluster, ClusterType +from wireless.models import WirelessLAN + + +class LocationSiteChangeSignalTestCase(TestCase): + """ + Verify dcim.signals.handle_location_site_change propagates a Location's new Site to + every descendant Location, Rack, Device, PowerPanel, and component when the parent + Location's site assignment changes. + """ + + @classmethod + def setUpTestData(cls): + cls.site_a = Site.objects.create(name='Site A', slug='site-a') + cls.site_b = Site.objects.create(name='Site B', slug='site-b') + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + cls.device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type') + cls.device_role = DeviceRole.objects.create(name='Device Role', slug='device-role') + + def test_changing_location_site_propagates_to_children(self): + parent_location = Location.objects.create(name='Parent', slug='parent', site=self.site_a) + child_location = Location.objects.create(name='Child', slug='child', site=self.site_a, parent=parent_location) + rack = Rack.objects.create(name='Rack', site=self.site_a, location=parent_location) + device = Device.objects.create( + name='Device', + site=self.site_a, + location=parent_location, + device_type=self.device_type, + role=self.device_role, + ) + interface = Interface.objects.create(device=device, name='Interface 1') + power_panel = PowerPanel.objects.create(name='Panel', site=self.site_a, location=parent_location) + + parent_location.site = self.site_b + parent_location.save() + + child_location.refresh_from_db() + rack.refresh_from_db() + device.refresh_from_db() + interface.refresh_from_db() + power_panel.refresh_from_db() + self.assertEqual(child_location.site, self.site_b) + self.assertEqual(rack.site, self.site_b) + self.assertEqual(device.site, self.site_b) + self.assertEqual(interface._site, self.site_b) + self.assertEqual(power_panel.site, self.site_b) + + def test_creating_location_does_not_attempt_to_propagate(self): + # Should not raise — newly-created locations have no descendants. + Location.objects.create(name='New', slug='new', site=self.site_a) + + +class RackSiteChangeSignalTestCase(TestCase): + """ + Verify dcim.signals.handle_rack_site_change propagates a Rack's site/location to its + Devices and their components when the Rack is moved. + """ + + @classmethod + def setUpTestData(cls): + cls.site_a = Site.objects.create(name='Site A', slug='site-a') + cls.site_b = Site.objects.create(name='Site B', slug='site-b') + cls.location_b = Location.objects.create(name='Loc B', slug='loc-b', site=cls.site_b) + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + cls.device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type') + cls.device_role = DeviceRole.objects.create(name='Device Role', slug='device-role') + + def test_changing_rack_site_propagates_to_devices_and_components(self): + rack = Rack.objects.create(name='Rack', site=self.site_a) + device = Device.objects.create( + name='Device', + site=self.site_a, + rack=rack, + device_type=self.device_type, + role=self.device_role, + ) + interface = Interface.objects.create(device=device, name='Interface 1') + + rack.site = self.site_b + rack.location = self.location_b + rack.save() + + device.refresh_from_db() + interface.refresh_from_db() + self.assertEqual(device.site, self.site_b) + self.assertEqual(device.location, self.location_b) + self.assertEqual(interface._site, self.site_b) + self.assertEqual(interface._location, self.location_b) + + +class DeviceSiteChangeSignalTestCase(TestCase): + """ + Verify dcim.signals.handle_device_site_change propagates a Device's site/location/rack + to its components on save. + """ + + @classmethod + def setUpTestData(cls): + cls.site_a = Site.objects.create(name='Site A', slug='site-a') + cls.site_b = Site.objects.create(name='Site B', slug='site-b') + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + cls.device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type') + cls.device_role = DeviceRole.objects.create(name='Device Role', slug='device-role') + + def test_moving_device_updates_components_cached_scope(self): + device = Device.objects.create( + name='Device', + site=self.site_a, + device_type=self.device_type, + role=self.device_role, + ) + interface = Interface.objects.create(device=device, name='Interface 1') + self.assertEqual(interface._site, self.site_a) + + device.site = self.site_b + device.save() + + interface.refresh_from_db() + self.assertEqual(interface._site, self.site_b) + + +class VirtualChassisMasterSignalTestCase(TestCase): + """ + Verify dcim.signals.assign_virtualchassis_master links the master device back to a + newly-created VirtualChassis. + """ + + @classmethod + def setUpTestData(cls): + cls.site = Site.objects.create(name='Site', slug='site') + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + cls.device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type') + cls.device_role = DeviceRole.objects.create(name='Device Role', slug='device-role') + + def test_master_is_assigned_to_new_virtual_chassis(self): + master = Device.objects.create( + name='Master', + site=self.site, + device_type=self.device_type, + role=self.device_role, + ) + vc = VirtualChassis.objects.create(name='VC 1', master=master) + + master.refresh_from_db() + self.assertEqual(master.virtual_chassis, vc) + self.assertEqual(master.vc_position, 1) + + def test_updating_virtual_chassis_does_not_reassign_master(self): + master = Device.objects.create( + name='Master', + site=self.site, + device_type=self.device_type, + role=self.device_role, + ) + vc = VirtualChassis.objects.create(name='VC 1', master=master) + + # Detach the master, then save the VC again — the signal should not re-link. + master.virtual_chassis = None + master.vc_position = None + master.save() + + vc.domain = 'updated' + vc.save() + + master.refresh_from_db() + self.assertIsNone(master.virtual_chassis) + + +class CableSignalTestCase(TestCase): + """ + Verify dcim.signals.update_connected_endpoints, retrace_cable_paths, and + nullify_connected_endpoints maintain CablePaths in response to Cable lifecycle events. + """ + + @classmethod + def setUpTestData(cls): + cls.site = Site.objects.create(name='Site', slug='site') + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type') + role = DeviceRole.objects.create(name='Device Role', slug='device-role') + cls.device = Device.objects.create( + name='Device', + site=cls.site, + device_type=device_type, + role=role, + ) + + def test_creating_cable_creates_endpoint_paths(self): + interface_a = Interface.objects.create(device=self.device, name='Interface A') + interface_b = Interface.objects.create(device=self.device, name='Interface B') + cable = Cable(a_terminations=[interface_a], b_terminations=[interface_b]) + cable.save() + + self.assertEqual(CablePath.objects.count(), 2) + interface_a.refresh_from_db() + self.assertIsNotNone(interface_a._path_id) + + def test_changing_cable_status_marks_paths_inactive(self): + interface_a = Interface.objects.create(device=self.device, name='Interface A') + interface_b = Interface.objects.create(device=self.device, name='Interface B') + cable = Cable(a_terminations=[interface_a], b_terminations=[interface_b]) + cable.save() + self.assertTrue(all(cp.is_active for cp in CablePath.objects.all())) + + # Reload the cable so _orig_status reflects the persisted value and + # _terminations_modified resets to False. + cable = Cable.objects.get(pk=cable.pk) + cable.status = LinkStatusChoices.STATUS_PLANNED + cable.save() + + self.assertFalse(any(cp.is_active for cp in CablePath.objects.all())) + + def test_reconnecting_cable_marks_paths_active(self): + interface_a = Interface.objects.create(device=self.device, name='Interface A') + interface_b = Interface.objects.create(device=self.device, name='Interface B') + cable = Cable( + a_terminations=[interface_a], + b_terminations=[interface_b], + status=LinkStatusChoices.STATUS_PLANNED, + ) + cable.save() + self.assertFalse(any(cp.is_active for cp in CablePath.objects.all())) + + cable = Cable.objects.get(pk=cable.pk) + cable.status = LinkStatusChoices.STATUS_CONNECTED + cable.save() + + self.assertTrue(all(cp.is_active for cp in CablePath.objects.all())) + + def test_deleting_cable_retraces_paths(self): + interface_a = Interface.objects.create(device=self.device, name='Interface A') + interface_b = Interface.objects.create(device=self.device, name='Interface B') + cable = Cable(a_terminations=[interface_a], b_terminations=[interface_b]) + cable.save() + self.assertEqual(CablePath.objects.count(), 2) + + cable.delete() + self.assertEqual(CablePath.objects.count(), 0) + interface_a.refresh_from_db() + interface_b.refresh_from_db() + # Cable deletion must fully detach both endpoints, even though the + # nullify_connected_endpoints signal short-circuits during Cable cascade. + self.assertIsNone(interface_a._path_id) + self.assertIsNone(interface_b._path_id) + self.assertIsNone(interface_a.cable_id) + self.assertIsNone(interface_b.cable_id) + self.assertEqual(interface_a.cable_end, '') + self.assertEqual(interface_b.cable_end, '') + + def test_deleting_cable_skips_per_termination_retrace(self): + """ + When a Cable is deleted, nullify_connected_endpoints (post_delete on each + cascaded CableTermination) must skip retracing — retrace_cable_paths + retraces each affected path once on Cable post_delete instead. See #22104. + + Without the short-circuit, retrace would fire (n_terminations * n_paths) + times from the per-termination handler plus n_paths times from the Cable + handler — for this 2-termination, 2-path cable, 6 calls total. With the + short-circuit, only the n_paths calls from retrace_cable_paths remain. + """ + interface_a = Interface.objects.create(device=self.device, name='Interface A') + interface_b = Interface.objects.create(device=self.device, name='Interface B') + cable = Cable(a_terminations=[interface_a], b_terminations=[interface_b]) + cable.save() + self.assertEqual(CablePath.objects.count(), 2) + self.assertFalse(Cable._is_being_deleted(cable.pk)) + + with patch('dcim.models.cables.CablePath.retrace') as retrace: + cable.delete() + + # Exactly one retrace per affected CablePath (from retrace_cable_paths), + # not the n*m calls the per-termination handler would have made. + self.assertEqual(retrace.call_count, 2) + # The deletion-tracking set must be cleaned up after delete() returns, + # even when the cascade runs to completion. + self.assertFalse(Cable._is_being_deleted(cable.pk)) + + def test_creating_portmapping_retraces_dependent_paths(self): + interface = Interface.objects.create(device=self.device, name='Interface A') + front_port = FrontPort.objects.create(device=self.device, name='Front Port 1') + rear_port = RearPort.objects.create(device=self.device, name='Rear Port 1') + Cable(a_terminations=[interface], b_terminations=[front_port]).save() + + # Creating a PortMapping connecting the front and rear ports should retrace paths + # that traverse either port (i.e. the incomplete path through front_port). + PortMapping.objects.create( + device=self.device, + front_port=front_port, + front_port_position=1, + rear_port=rear_port, + rear_port_position=1, + ) + + path = CablePath.objects.filter(_nodes__contains=front_port).first() + self.assertIsNotNone(path) + # The retraced path should now extend through to the rear port. Path nodes are + # encoded as ":". + rear_port_node = f'{ContentType.objects.get_for_model(RearPort).pk}:{rear_port.pk}' + flat_nodes = [n for step in path.path for n in step] + self.assertIn(rear_port_node, flat_nodes) + + def test_deleting_cabletermination_nullifies_endpoints(self): + interface_a = Interface.objects.create(device=self.device, name='Interface A') + interface_b = Interface.objects.create(device=self.device, name='Interface B') + cable = Cable(a_terminations=[interface_a], b_terminations=[interface_b]) + cable.save() + termination = cable.terminations.get(cable_end=CableEndChoices.SIDE_A) + + termination.delete() + interface_a.refresh_from_db() + self.assertIsNone(interface_a.cable_id) + self.assertEqual(interface_a.cable_end, '') + + +class MACAddressInterfaceSignalTestCase(TestCase): + """ + Verify dcim.signals.update_mac_address_interface assigns a designated primary MAC to + the newly-created Interface or VMInterface. + """ + + @classmethod + def setUpTestData(cls): + cls.site = Site.objects.create(name='Site', slug='site') + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type') + role = DeviceRole.objects.create(name='Device Role', slug='device-role') + cls.device = Device.objects.create( + name='Device', + site=cls.site, + device_type=device_type, + role=role, + ) + + def test_primary_mac_is_assigned_to_new_interface(self): + mac = MACAddress.objects.create(mac_address='00:11:22:33:44:55') + interface = Interface(device=self.device, name='Interface 1', primary_mac_address=mac) + interface.save() + + mac.refresh_from_db() + self.assertEqual(mac.assigned_object, interface) + + def test_primary_mac_is_not_reassigned_on_interface_update(self): + mac = MACAddress.objects.create(mac_address='00:11:22:33:44:55') + interface = Interface.objects.create(device=self.device, name='Interface 1') + mac.assigned_object = interface + mac.save() + # Detach (simulate the MAC having been moved off the interface). + mac.assigned_object = None + mac.save() + + interface.primary_mac_address = mac + interface.description = 'updated' + interface.save() + + mac.refresh_from_db() + # Updating an existing interface should not re-assign the MAC. + self.assertIsNone(mac.assigned_object) + + +class SyncCachedScopeFieldsSignalTestCase(TestCase): + """ + Verify dcim.signals.sync_cached_scope_fields recomputes cached scope fields on + Prefix, Cluster, and WirelessLAN when a Site or Location is modified. + """ + + def test_site_group_change_updates_prefix_cached_scope(self): + group_a = SiteGroup.objects.create(name='Group A', slug='group-a') + group_b = SiteGroup.objects.create(name='Group B', slug='group-b') + site = Site.objects.create(name='Site', slug='site', group=group_a) + prefix = Prefix.objects.create( + prefix='10.0.0.0/24', + scope_type=ContentType.objects.get_for_model(Site), + scope_id=site.pk, + ) + self.assertEqual(prefix._site_group, group_a) + + site.group = group_b + site.save() + + prefix.refresh_from_db() + self.assertEqual(prefix._site, site) + self.assertEqual(prefix._site_group, group_b) + + def test_location_site_change_updates_prefix_cached_scope(self): + site_a = Site.objects.create(name='Site A', slug='site-a') + site_b = Site.objects.create(name='Site B', slug='site-b') + location = Location.objects.create(name='Loc', slug='loc', site=site_a) + prefix = Prefix.objects.create( + prefix='10.0.0.0/24', + scope_type=ContentType.objects.get_for_model(Location), + scope_id=location.pk, + ) + self.assertEqual(prefix._site, site_a) + self.assertEqual(prefix._location, location) + + location.site = site_b + location.save() + + prefix.refresh_from_db() + self.assertEqual(prefix._location, location) + self.assertEqual(prefix._site, site_b) + + def test_signal_updates_cluster_and_wirelesslan_cached_scope(self): + # Lock down the explicit (Prefix, Cluster, WirelessLAN) tuple in the + # signal by exercising Cluster and WirelessLAN alongside Prefix. If a + # future change drops Cluster or WirelessLAN from that tuple, this test + # will catch it. + group_a = SiteGroup.objects.create(name='Group A', slug='group-a') + group_b = SiteGroup.objects.create(name='Group B', slug='group-b') + site = Site.objects.create(name='Site', slug='site', group=group_a) + cluster_type = ClusterType.objects.create(name='CT', slug='ct') + cluster = Cluster.objects.create(name='Cluster', type=cluster_type, scope=site) + wireless_lan = WirelessLAN.objects.create(ssid='LAN', scope=site) + + self.assertEqual(cluster._site_group, group_a) + self.assertEqual(wireless_lan._site_group, group_a) + + site.group = group_b + site.save() + + cluster.refresh_from_db() + wireless_lan.refresh_from_db() + self.assertEqual(cluster._site_group, group_b) + self.assertEqual(wireless_lan._site_group, group_b) + + def test_create_site_does_not_attempt_to_resync(self): + # Should not raise — newly-created sites have nothing to sync. + Site.objects.create(name='New Site', slug='new-site') + + +class CableSignalDirectHandlerTestCase(SimpleTestCase): + """ + Direct-call tests for dcim signal branches that are not reachable through normal + model operations (raw=True is set only by Django's loaddata pathway). + """ + + def test_update_connected_endpoints_raw_import_is_a_no_op(self): + cable = SimpleNamespace(_terminations_modified=True) + logger = MagicMock() + + with ( + patch.object(signals.logging, 'getLogger', return_value=logger), + patch.object(signals, 'CableTermination') as cabletermination_model, + patch.object(signals, 'create_cablepaths') as create_cablepaths, + patch.object(signals, 'rebuild_paths') as rebuild_paths, + ): + signals.update_connected_endpoints(instance=cable, created=True, raw=True) + + logger.debug.assert_called_once() + cabletermination_model.objects.filter.assert_not_called() + create_cablepaths.assert_not_called() + rebuild_paths.assert_not_called() + + def test_update_mac_address_interface_raw_import_is_a_no_op(self): + primary_mac = SimpleNamespace(save=MagicMock()) + interface = SimpleNamespace(primary_mac_address=primary_mac) + + signals.update_mac_address_interface(instance=interface, created=True, raw=True) + + primary_mac.save.assert_not_called() diff --git a/netbox/extras/tests/test_signals.py b/netbox/extras/tests/test_signals.py new file mode 100644 index 000000000..2a8fb29e6 --- /dev/null +++ b/netbox/extras/tests/test_signals.py @@ -0,0 +1,297 @@ +import uuid +from unittest.mock import patch + +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ValidationError +from django.test import RequestFactory, TestCase, override_settings + +from core.events import JOB_COMPLETED, JOB_STARTED, OBJECT_DELETED, OBJECT_UPDATED +from core.models import Job, ObjectType +from core.signals import job_end, job_start +from dcim.choices import SiteStatusChoices +from dcim.models import Region, Site +from extras import signals +from extras.choices import CustomFieldTypeChoices, EventRuleActionChoices +from extras.models import CustomField, EventRule, Notification, Subscription, Tag, Webhook +from extras.validators import CustomValidator +from netbox.context_managers import event_tracking +from users.models import User +from utilities.exceptions import AbortRequest + + +def _build_request(user=None): + request = RequestFactory().get('/') + request.id = uuid.uuid4() + request.user = user + return request + + +class CustomFieldRenameSignalTestCase(TestCase): + """ + Verify extras.signals.handle_cf_renamed migrates stored custom-field data when a + CustomField is renamed. + """ + + def test_renaming_custom_field_moves_object_data(self): + site_type = ContentType.objects.get_for_model(Site) + cf = CustomField.objects.create( + name='asset_tag', + type=CustomFieldTypeChoices.TYPE_TEXT, + ) + cf.object_types.set([site_type]) + site = Site.objects.create(name='Site 1', slug='site-1', custom_field_data={'asset_tag': 'A123'}) + + cf.name = 'inventory_id' + cf.save() + + site.refresh_from_db() + self.assertNotIn('asset_tag', site.custom_field_data) + self.assertEqual(site.custom_field_data['inventory_id'], 'A123') + + def test_creating_custom_field_does_not_attempt_rename(self): + # Should not raise — newly-created custom fields have no prior name to migrate. + site_type = ContentType.objects.get_for_model(Site) + cf = CustomField.objects.create( + name='cf1', + type=CustomFieldTypeChoices.TYPE_TEXT, + ) + cf.object_types.set([site_type]) + + +class CustomFieldDeletedSignalTestCase(TestCase): + """ + Verify extras.signals.handle_cf_deleted strips stale data from associated objects + when a CustomField is deleted. + """ + + def test_deleting_custom_field_clears_object_data(self): + site_type = ContentType.objects.get_for_model(Site) + cf = CustomField.objects.create( + name='asset_tag', + type=CustomFieldTypeChoices.TYPE_TEXT, + ) + cf.object_types.set([site_type]) + site = Site.objects.create(name='Site 1', slug='site-1', custom_field_data={'asset_tag': 'A123'}) + + cf.delete() + + site.refresh_from_db() + self.assertNotIn('asset_tag', site.custom_field_data) + + +class CustomFieldObjectTypeSignalTestCase(TestCase): + """ + Verify extras.signals.handle_cf_added_obj_types and handle_cf_removed_obj_types + populate or strip default values when a CustomField's object_types m2m changes. + """ + + def test_adding_object_type_populates_default_value(self): + site_type = ContentType.objects.get_for_model(Site) + Site.objects.create(name='Site 1', slug='site-1') + cf = CustomField.objects.create( + name='asset_tag', + type=CustomFieldTypeChoices.TYPE_TEXT, + default='UNTAGGED', + ) + + cf.object_types.set([site_type]) + + site = Site.objects.get(slug='site-1') + self.assertEqual(site.custom_field_data.get('asset_tag'), 'UNTAGGED') + + def test_removing_object_type_clears_stored_data(self): + site_type = ContentType.objects.get_for_model(Site) + cf = CustomField.objects.create( + name='asset_tag', + type=CustomFieldTypeChoices.TYPE_TEXT, + ) + cf.object_types.set([site_type]) + site = Site.objects.create(name='Site 1', slug='site-1', custom_field_data={'asset_tag': 'A123'}) + + cf.object_types.remove(site_type) + + site.refresh_from_db() + self.assertNotIn('asset_tag', site.custom_field_data) + + +class RunSaveValidatorsSignalTestCase(TestCase): + """ + Verify extras.signals.run_save_validators invokes any configured CUSTOM_VALIDATORS + when a model emits the post_clean signal. + """ + + @override_settings(CUSTOM_VALIDATORS={'dcim.site': [CustomValidator({'name': {'eq': 'allowed'}})]}) + def test_validation_failure_raises_validation_error(self): + with self.assertRaises(ValidationError): + Site(name='blocked', slug='blocked', status=SiteStatusChoices.STATUS_ACTIVE).clean() + + @override_settings(CUSTOM_VALIDATORS={'dcim.site': [CustomValidator({'name': {'eq': 'allowed'}})]}) + def test_validation_success_does_not_raise(self): + Site(name='allowed', slug='allowed', status=SiteStatusChoices.STATUS_ACTIVE).clean() + + +class ValidateAssignedTagsSignalTestCase(TestCase): + """ + Verify extras.signals.validate_assigned_tags rejects Tags that are restricted to + object types incompatible with the target object. + """ + + def test_restricted_tag_blocks_incompatible_object(self): + region_type = ContentType.objects.get_for_model(Region) + tag = Tag.objects.create(name='RegionOnly', slug='regiononly') + tag.object_types.set([region_type]) + site = Site.objects.create(name='Site 1', slug='site-1') + + with self.assertRaises(AbortRequest): + site.tags.add(tag) + + def test_restricted_tag_allows_compatible_object(self): + site_type = ContentType.objects.get_for_model(Site) + tag = Tag.objects.create(name='SiteOnly', slug='siteonly') + tag.object_types.set([site_type]) + site = Site.objects.create(name='Site 1', slug='site-1') + + site.tags.add(tag) + self.assertEqual(list(site.tags.all()), [tag]) + + def test_unrestricted_tag_is_always_permitted(self): + tag = Tag.objects.create(name='Anywhere', slug='anywhere') + site = Site.objects.create(name='Site 1', slug='site-1') + + site.tags.add(tag) + self.assertEqual(list(site.tags.all()), [tag]) + + +class JobEventRulesSignalTestCase(TestCase): + """ + Verify extras.signals.process_job_start_event_rules and process_job_end_event_rules + invoke any EventRule registered for JOB_STARTED / JOB_COMPLETED on the sender's + object_type. + """ + + @classmethod + def setUpTestData(cls): + cls.site_type = ObjectType.objects.get_for_model(Site) + webhook = Webhook.objects.create( + name='Webhook', + payload_url='http://localhost/', + secret='secret', + ) + webhook_type = ObjectType.objects.get_for_model(Webhook) + cls.start_rule = EventRule.objects.create( + name='Job Start Rule', + event_types=[JOB_STARTED], + action_type=EventRuleActionChoices.WEBHOOK, + action_object_type=webhook_type, + action_object_id=webhook.pk, + ) + cls.start_rule.object_types.set([cls.site_type]) + cls.end_rule = EventRule.objects.create( + name='Job End Rule', + event_types=[JOB_COMPLETED], + action_type=EventRuleActionChoices.WEBHOOK, + action_object_type=webhook_type, + action_object_id=webhook.pk, + ) + cls.end_rule.object_types.set([cls.site_type]) + + def _create_job(self): + return Job.objects.create( + object_type=self.site_type, + name='test-job', + job_id=uuid.uuid4(), + data={'foo': 1}, + ) + + def test_job_start_filters_to_matching_event_rules(self): + sender = self._create_job() + + with patch('extras.signals.process_event_rules') as process_event_rules: + job_start.send(sender=sender) + + process_event_rules.assert_called_once() + rules_qs = process_event_rules.call_args.args[0] + self.assertEqual(list(rules_qs.values_list('pk', flat=True)), [self.start_rule.pk]) + + def test_job_end_filters_to_matching_event_rules(self): + sender = self._create_job() + + with patch('extras.signals.process_event_rules') as process_event_rules: + job_end.send(sender=sender) + + process_event_rules.assert_called_once() + rules_qs = process_event_rules.call_args.args[0] + self.assertEqual(list(rules_qs.values_list('pk', flat=True)), [self.end_rule.pk]) + + +class NotifyObjectChangedSignalTestCase(TestCase): + """ + Verify extras.signals.notify_object_changed creates Notifications for subscribed + users on object update and deletion, and skips creation otherwise. + """ + + @classmethod + def setUpTestData(cls): + cls.user = User.objects.create_user(username='alice', password='pw') + + def test_creating_object_does_not_create_notifications(self): + # Subscribe a user to the object BEFORE invoking the handler so the + # discriminating branch (created=True early return) is genuinely + # exercised. Without the subscription this assertion passes trivially. + site = Site.objects.create(name='Site 1', slug='site-1') + site_type = ContentType.objects.get_for_model(Site) + Subscription.objects.create(user=self.user, object_type=site_type, object_id=site.pk) + Notification.objects.all().delete() + + signals.notify_object_changed(sender=Site, instance=site, created=True) + + self.assertFalse(Notification.objects.exists()) + + def test_updating_subscribed_object_creates_update_notification(self): + site = Site.objects.create(name='Site 1', slug='site-1') + site_type = ContentType.objects.get_for_model(Site) + Subscription.objects.create(user=self.user, object_type=site_type, object_id=site.pk) + + site.description = 'updated' + site.save() + + notification = Notification.objects.get(user=self.user) + self.assertEqual(notification.object_type, site_type) + self.assertEqual(notification.object_id, site.pk) + self.assertEqual(notification.event_type, OBJECT_UPDATED) + + def test_deleting_subscribed_object_creates_delete_notification(self): + site = Site.objects.create(name='Site 1', slug='site-1') + site_type = ContentType.objects.get_for_model(Site) + Subscription.objects.create(user=self.user, object_type=site_type, object_id=site.pk) + + site.delete() + + notification = Notification.objects.get(user=self.user) + self.assertEqual(notification.event_type, OBJECT_DELETED) + + def test_updating_unsubscribed_object_creates_no_notification(self): + site = Site.objects.create(name='Site 1', slug='site-1') + + site.description = 'updated' + site.save() + + self.assertEqual(Notification.objects.count(), 0) + + def test_updating_object_replaces_existing_notification(self): + site = Site.objects.create(name='Site 1', slug='site-1') + site_type = ContentType.objects.get_for_model(Site) + Subscription.objects.create(user=self.user, object_type=site_type, object_id=site.pk) + + # Trigger two updates within a single request; only one Notification should remain. + request = _build_request(user=self.user) + with event_tracking(request): + site.description = 'first' + site.save() + site.description = 'second' + site.save() + + self.assertEqual( + Notification.objects.filter(user=self.user, object_type=site_type, object_id=site.pk).count(), + 1, + ) diff --git a/netbox/ipam/tests/test_signals.py b/netbox/ipam/tests/test_signals.py new file mode 100644 index 000000000..0db43c624 --- /dev/null +++ b/netbox/ipam/tests/test_signals.py @@ -0,0 +1,231 @@ +import uuid + +from django.contrib.contenttypes.models import ContentType +from django.test import RequestFactory, TestCase + +from core.choices import ObjectChangeActionChoices +from core.models import ObjectChange +from ipam.models import IPAddress, Prefix +from netbox.context_managers import event_tracking +from users.models import User +from utilities.testing.utils import create_test_device, create_test_virtualmachine + + +def _build_request(user): + request = RequestFactory().get('/') + request.id = uuid.uuid4() + request.user = user + return request + + +class PrefixHierarchySignalTestCase(TestCase): + """ + Verify ipam.signals.handle_prefix_saved / handle_prefix_deleted keep the cached + `_children` and `_depth` counters up to date as prefixes are added, modified, and + removed. + """ + + def _refresh_counters(self, *prefixes): + for prefix in prefixes: + prefix.refresh_from_db() + return prefixes + + def test_creating_prefix_initializes_hierarchy_counters(self): + parent = Prefix.objects.create(prefix='10.0.0.0/16') + child = Prefix.objects.create(prefix='10.0.1.0/24') + + self._refresh_counters(parent, child) + self.assertEqual(parent._children, 1) + self.assertEqual(child._depth, 1) + self.assertEqual(child._children, 0) + + def test_modifying_prefix_recomputes_old_and_new_position(self): + parent_a = Prefix.objects.create(prefix='10.0.0.0/16') + parent_b = Prefix.objects.create(prefix='192.168.0.0/16') + child = Prefix.objects.create(prefix='10.0.1.0/24') + + self._refresh_counters(parent_a, parent_b, child) + self.assertEqual(parent_a._children, 1) + self.assertEqual(parent_b._children, 0) + + # Move the child under parent_b. + child.prefix = '192.168.1.0/24' + child.save() + + self._refresh_counters(parent_a, parent_b, child) + self.assertEqual(parent_a._children, 0) + self.assertEqual(parent_b._children, 1) + self.assertEqual(child._depth, 1) + + def test_unchanged_save_does_not_disturb_counters(self): + parent = Prefix.objects.create(prefix='10.0.0.0/16') + child = Prefix.objects.create(prefix='10.0.1.0/24') + + self._refresh_counters(parent, child) + original_children = parent._children + original_depth = child._depth + + # Save with no field changes. + parent.description = '' + parent.save() + + self._refresh_counters(parent, child) + self.assertEqual(parent._children, original_children) + self.assertEqual(child._depth, original_depth) + + def test_deleting_prefix_recomputes_neighbor_counters(self): + parent = Prefix.objects.create(prefix='10.0.0.0/16') + child = Prefix.objects.create(prefix='10.0.1.0/24') + + self._refresh_counters(parent) + self.assertEqual(parent._children, 1) + + child.delete() + + self._refresh_counters(parent) + self.assertEqual(parent._children, 0) + + +class ClearPrimaryIPSignalTestCase(TestCase): + """ + Verify ipam.signals.clear_primary_ip detaches deleted IPAddresses from the Device or + VirtualMachine they were assigned as primary. The behavior under test is the + signal-driven snapshot+save (and resulting change-log entry), not the FK's + on_delete=SET_NULL fallback. + """ + + @classmethod + def setUpTestData(cls): + cls.user = User.objects.create_user(username='alice', password='pw') + + def test_device_primary_ip4_delete_records_device_update(self): + device = create_test_device('Device 1') + ip = IPAddress.objects.create(address='192.0.2.1/24') + device.primary_ip4 = ip + device.save() + + request = _build_request(self.user) + with event_tracking(request): + ip.delete() + + device.refresh_from_db() + self.assertIsNone(device.primary_ip4) + + oc = ObjectChange.objects.get( + changed_object_type=ContentType.objects.get_for_model(device), + changed_object_id=device.pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ) + self.assertIsNone(oc.postchange_data['primary_ip4']) + + def test_device_primary_ip6_delete_clears_field_and_saves(self): + device = create_test_device('Device 1') + ip = IPAddress.objects.create(address='2001:db8::1/64') + device.primary_ip6 = ip + device.save() + + request = _build_request(self.user) + with event_tracking(request): + ip.delete() + + device.refresh_from_db() + self.assertIsNone(device.primary_ip6) + oc = ObjectChange.objects.get( + changed_object_type=ContentType.objects.get_for_model(device), + changed_object_id=device.pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ) + self.assertIsNone(oc.postchange_data['primary_ip6']) + + def test_vm_primary_ip4_delete_records_vm_update(self): + vm = create_test_virtualmachine('VM 1') + ip = IPAddress.objects.create(address='192.0.2.10/24') + vm.primary_ip4 = ip + vm.save() + + request = _build_request(self.user) + with event_tracking(request): + ip.delete() + + vm.refresh_from_db() + self.assertIsNone(vm.primary_ip4) + oc = ObjectChange.objects.get( + changed_object_type=ContentType.objects.get_for_model(vm), + changed_object_id=vm.pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ) + self.assertIsNone(oc.postchange_data['primary_ip4']) + + def test_unrelated_ip_delete_records_no_device_change(self): + device = create_test_device('Device 1') + device_type = ContentType.objects.get_for_model(device) + assigned = IPAddress.objects.create(address='192.0.2.1/24') + unrelated = IPAddress.objects.create(address='192.0.2.2/24') + device.primary_ip4 = assigned + device.save() + + request = _build_request(self.user) + with event_tracking(request): + unrelated.delete() + + device.refresh_from_db() + self.assertEqual(device.primary_ip4, assigned) + self.assertFalse( + ObjectChange.objects.filter( + changed_object_type=device_type, + changed_object_id=device.pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ).exists() + ) + + +class ClearOOBIPSignalTestCase(TestCase): + """ + Verify ipam.signals.clear_oob_ip detaches a deleted IPAddress from any Device on + which it was set as the OOB IP, and records a Device update change-log entry. + """ + + @classmethod + def setUpTestData(cls): + cls.user = User.objects.create_user(username='alice', password='pw') + + def test_device_oob_ip_delete_records_device_update(self): + device = create_test_device('Device 1') + ip = IPAddress.objects.create(address='192.0.2.1/24') + device.oob_ip = ip + device.save() + + request = _build_request(self.user) + with event_tracking(request): + ip.delete() + + device.refresh_from_db() + self.assertIsNone(device.oob_ip) + oc = ObjectChange.objects.get( + changed_object_type=ContentType.objects.get_for_model(device), + changed_object_id=device.pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ) + self.assertIsNone(oc.postchange_data['oob_ip']) + + def test_unrelated_ip_delete_records_no_device_change(self): + device = create_test_device('Device 1') + device_type = ContentType.objects.get_for_model(device) + oob = IPAddress.objects.create(address='192.0.2.1/24') + unrelated = IPAddress.objects.create(address='192.0.2.2/24') + device.oob_ip = oob + device.save() + + request = _build_request(self.user) + with event_tracking(request): + unrelated.delete() + + device.refresh_from_db() + self.assertEqual(device.oob_ip, oob) + self.assertFalse( + ObjectChange.objects.filter( + changed_object_type=device_type, + changed_object_id=device.pk, + action=ObjectChangeActionChoices.ACTION_UPDATE, + ).exists() + ) diff --git a/netbox/users/tests/test_signals.py b/netbox/users/tests/test_signals.py new file mode 100644 index 000000000..b61309a7b --- /dev/null +++ b/netbox/users/tests/test_signals.py @@ -0,0 +1,128 @@ +from django.contrib.auth.signals import user_logged_in, user_login_failed +from django.db.models.signals import post_save +from django.test import RequestFactory, TestCase, override_settings + +from users.models import User, UserConfig +from users.signals import create_userconfig + + +class LogUserLoginFailedSignalTestCase(TestCase): + """ + Verify users.signals.log_user_login_failed emits the expected log records when the + user_login_failed signal fires. + """ + + def setUp(self): + self.factory = RequestFactory() + + def test_log_includes_client_ip_when_available(self): + request = self.factory.post('/login/', REMOTE_ADDR='192.0.2.100') + + with self.assertLogs('netbox.auth.login', level='INFO') as cm: + user_login_failed.send( + sender=self.__class__, + credentials={'username': 'alice'}, + request=request, + ) + + self.assertEqual(len(cm.records), 1) + self.assertEqual(cm.records[0].levelname, 'INFO') + self.assertIn('alice', cm.records[0].getMessage()) + self.assertIn('192.0.2.100', cm.records[0].getMessage()) + + def test_log_warns_when_client_ip_missing(self): + request = self.factory.post('/login/') + # RequestFactory sets REMOTE_ADDR by default; strip it to simulate missing IP. + request.META.pop('REMOTE_ADDR', None) + + with self.assertLogs('netbox.auth.login', level='INFO') as cm: + user_login_failed.send( + sender=self.__class__, + credentials={'username': 'alice'}, + request=request, + ) + + levels = [record.levelname for record in cm.records] + self.assertIn('WARNING', levels) + self.assertIn('INFO', levels) + info_message = next(r.getMessage() for r in cm.records if r.levelname == 'INFO') + self.assertEqual(info_message, 'Failed login attempt for username: alice') + + +class SetLanguageOnLoginSignalTestCase(TestCase): + """ + Verify users.signals.set_language_on_login stores the user's preferred language on the + request when the user logs in. + """ + + def setUp(self): + self.factory = RequestFactory() + self.user = User.objects.create_user(username='alice', password='pw') + + def test_language_cookie_is_set_from_user_config(self): + # Assign a fresh dict to avoid mutating the shared DEFAULT_USER_PREFERENCES reference. + self.user.config.data = {'locale': {'language': 'de'}} + self.user.config.save() + request = self.factory.post('/login/') + + user_logged_in.send(sender=self.__class__, user=self.user, request=request) + + self.assertEqual(request._language_cookie, 'de') + + def test_missing_language_preference_leaves_request_untouched(self): + self.user.config.data = {} + self.user.config.save() + request = self.factory.post('/login/') + + user_logged_in.send(sender=self.__class__, user=self.user, request=request) + + self.assertFalse(hasattr(request, '_language_cookie')) + + def test_user_without_config_leaves_request_untouched(self): + request = self.factory.post('/login/') + # Drop the UserConfig that was auto-created so `hasattr(user, 'config')` returns False. + self.user.config.delete() + # Reload the user instance from the DB so the cached 'config' related attribute is gone. + user = User.objects.get(pk=self.user.pk) + + user_logged_in.send(sender=self.__class__, user=user, request=request) + + self.assertFalse(hasattr(request, '_language_cookie')) + + +class CreateUserConfigSignalTestCase(TestCase): + """ + Verify users.signals.create_userconfig creates a default UserConfig for new users only. + """ + + @override_settings(DEFAULT_USER_PREFERENCES={'pagination.per_page': 42}) + def test_userconfig_is_created_with_default_preferences(self): + user = User.objects.create_user(username='alice', password='pw') + + config = UserConfig.objects.get(user=user) + self.assertEqual(config.data, {'pagination.per_page': 42}) + + def test_userconfig_is_not_created_for_existing_user(self): + user = User.objects.create_user(username='alice', password='pw') + UserConfig.objects.filter(user=user).delete() + + user.email = 'alice@example.com' + user.save() + + self.assertFalse(UserConfig.objects.filter(user=user).exists()) + + def test_userconfig_is_not_created_for_raw_imports(self): + """ + When loading a fixture (`raw=True`), the signal must skip UserConfig creation. + """ + user = User(username='bob') + # Simulate the post_save signal Django emits during loaddata with raw=True. + post_save.disconnect(create_userconfig, sender=User) + try: + user.save() + UserConfig.objects.filter(user=user).delete() + create_userconfig(instance=user, created=True, raw=True) + finally: + post_save.connect(create_userconfig, sender=User) + + self.assertFalse(UserConfig.objects.filter(user=user).exists()) diff --git a/netbox/virtualization/tests/test_signals.py b/netbox/virtualization/tests/test_signals.py new file mode 100644 index 000000000..358a9a5ff --- /dev/null +++ b/netbox/virtualization/tests/test_signals.py @@ -0,0 +1,85 @@ +from django.contrib.contenttypes.models import ContentType +from django.test import TestCase + +from dcim.models import Site +from virtualization.models import Cluster, ClusterType, VirtualDisk, VirtualMachine + + +class UpdateVirtualMachineDiskSignalTestCase(TestCase): + """ + Verify virtualization.signals.update_virtualmachine_disk keeps VirtualMachine.disk in sync + with the aggregate size of its VirtualDisks. + """ + + @classmethod + def setUpTestData(cls): + cluster_type = ClusterType.objects.create(name='Cluster Type', slug='cluster-type') + cls.cluster = Cluster.objects.create(name='Cluster', type=cluster_type) + + def test_disk_size_is_aggregated_on_save(self): + vm = VirtualMachine.objects.create(name='VM 1', cluster=self.cluster) + VirtualDisk.objects.create(virtual_machine=vm, name='disk0', size=50) + VirtualDisk.objects.create(virtual_machine=vm, name='disk1', size=75) + + vm.refresh_from_db() + self.assertEqual(vm.disk, 125) + + def test_disk_size_is_recalculated_on_delete(self): + vm = VirtualMachine.objects.create(name='VM 1', cluster=self.cluster) + disk = VirtualDisk.objects.create(virtual_machine=vm, name='disk0', size=50) + VirtualDisk.objects.create(virtual_machine=vm, name='disk1', size=75) + vm.refresh_from_db() + self.assertEqual(vm.disk, 125) + + disk.delete() + vm.refresh_from_db() + self.assertEqual(vm.disk, 75) + + def test_disk_size_is_none_when_all_disks_removed(self): + vm = VirtualMachine.objects.create(name='VM 1', cluster=self.cluster) + disk = VirtualDisk.objects.create(virtual_machine=vm, name='disk0', size=50) + + disk.delete() + vm.refresh_from_db() + self.assertIsNone(vm.disk) + + +class UpdateVirtualMachineSiteSignalTestCase(TestCase): + """ + Verify virtualization.signals.update_virtualmachine_site propagates a Cluster's cached + site to all of its VirtualMachines on save. + """ + + @classmethod + def setUpTestData(cls): + cls.site_a = Site.objects.create(name='Site A', slug='site-a') + cls.site_b = Site.objects.create(name='Site B', slug='site-b') + cls.cluster_type = ClusterType.objects.create(name='Cluster Type', slug='cluster-type') + + def test_cluster_site_change_propagates_to_vms(self): + cluster = Cluster.objects.create(name='Cluster', type=self.cluster_type, scope=self.site_a) + vm1 = VirtualMachine.objects.create(name='VM 1', cluster=cluster) + vm2 = VirtualMachine.objects.create(name='VM 2', cluster=cluster) + self.assertEqual(vm1.site, self.site_a) + self.assertEqual(vm2.site, self.site_a) + + # Re-scope the cluster to site B; both VMs should follow. + cluster.scope_type = ContentType.objects.get_for_model(Site) + cluster.scope_id = self.site_b.pk + cluster.save() + + vm1.refresh_from_db() + vm2.refresh_from_db() + self.assertEqual(vm1.site, self.site_b) + self.assertEqual(vm2.site, self.site_b) + + def test_cluster_without_site_does_not_overwrite_vm_site(self): + cluster = Cluster.objects.create(name='Cluster', type=self.cluster_type) + vm = VirtualMachine.objects.create(name='VM 1', cluster=cluster, site=self.site_a) + self.assertEqual(vm.site, self.site_a) + + cluster.description = 'updated' + cluster.save() + + vm.refresh_from_db() + self.assertEqual(vm.site, self.site_a) diff --git a/netbox/wireless/tests/test_signals.py b/netbox/wireless/tests/test_signals.py new file mode 100644 index 000000000..325b5c30d --- /dev/null +++ b/netbox/wireless/tests/test_signals.py @@ -0,0 +1,97 @@ +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +from django.test import SimpleTestCase, TestCase + +from dcim.choices import InterfaceTypeChoices +from dcim.models import CablePath, Interface +from utilities.testing.utils import create_test_device +from wireless import signals +from wireless.choices import WirelessChannelChoices +from wireless.models import WirelessLink + + +class WirelessLinkSignalTestCase(TestCase): + """ + Verify wireless.signals.update_connected_interfaces and nullify_connected_interfaces + keep the connected interfaces and CablePaths consistent with the WirelessLink lifecycle. + """ + + @classmethod + def setUpTestData(cls): + cls.device = create_test_device('Device 1') + # Eight interfaces — one distinct pair per test method so no test sees stale + # in-memory state mutated by a previous test. + cls.interfaces = [ + Interface.objects.create( + device=cls.device, + name=f'radio{i}', + type=InterfaceTypeChoices.TYPE_80211AC, + rf_channel=WirelessChannelChoices.CHANNEL_5G_32, + rf_channel_frequency=5160, + rf_channel_width=20, + ) + for i in range(8) + ] + + def test_creating_link_assigns_wireless_link_to_both_interfaces(self): + interface_a, interface_b = self.interfaces[0], self.interfaces[1] + link = WirelessLink(interface_a=interface_a, interface_b=interface_b, ssid='LINK1') + link.save() + + interface_a.refresh_from_db() + interface_b.refresh_from_db() + self.assertEqual(interface_a.wireless_link, link) + self.assertEqual(interface_b.wireless_link, link) + + def test_creating_link_creates_cablepaths(self): + interface_a, interface_b = self.interfaces[2], self.interfaces[3] + link = WirelessLink(interface_a=interface_a, interface_b=interface_b, ssid='LINK1') + link.save() + + self.assertEqual(CablePath.objects.filter(_nodes__contains=link).count(), 2) + + def test_saving_existing_link_does_not_create_extra_paths(self): + interface_a, interface_b = self.interfaces[4], self.interfaces[5] + link = WirelessLink(interface_a=interface_a, interface_b=interface_b, ssid='LINK1') + link.save() + path_count = CablePath.objects.count() + + link.description = 'updated' + link.save() + + self.assertEqual(CablePath.objects.count(), path_count) + + def test_deleting_link_clears_interfaces_and_paths(self): + interface_a, interface_b = self.interfaces[6], self.interfaces[7] + link = WirelessLink(interface_a=interface_a, interface_b=interface_b, ssid='LINK1') + link.save() + self.assertEqual(CablePath.objects.filter(_nodes__contains=link).count(), 2) + + link.delete() + + interface_a.refresh_from_db() + interface_b.refresh_from_db() + self.assertIsNone(interface_a.wireless_link) + self.assertIsNone(interface_b.wireless_link) + # All wireless cable paths should be gone. + self.assertEqual(CablePath.objects.count(), 0) + + +class UpdateConnectedInterfacesDirectHandlerTestCase(SimpleTestCase): + """ + Direct-call tests for update_connected_interfaces branches not reachable through + normal model operations (raw=True is only set during Django's loaddata pathway). + """ + + def test_raw_import_skips_interface_assignment_and_path_creation(self): + interface_a = SimpleNamespace(wireless_link=None, save=MagicMock()) + interface_b = SimpleNamespace(wireless_link=None, cable=None, save=MagicMock()) + instance = SimpleNamespace(interface_a=interface_a, interface_b=interface_b) + + with patch.object(signals, 'create_cablepaths') as create_cablepaths: + signals.update_connected_interfaces(instance=instance, created=True, raw=True) + + interface_a.save.assert_not_called() + interface_b.save.assert_not_called() + create_cablepaths.assert_not_called() From 7a3397798a903f87e13744d1b26e90a024304cf5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Wed, 13 May 2026 14:38:30 -0700 Subject: [PATCH 035/131] Fixes #16851: Add missing Aria Labels (#22178) * #16851 - Add missing Aria Labels * #16851 - Add missing Aria Labels * #16851 - Add missing Aria Labels * fixes for form field labels * cleanup * cleanup * cleanup * cleanup * cleanup * cleanup * cleanup --- netbox/dcim/forms/model_forms.py | 3 +- netbox/netbox/forms/mixins.py | 4 ++ netbox/netbox/tables/columns.py | 11 +++- netbox/templates/account/preferences.html | 4 +- netbox/templates/dcim/device/base.html | 2 +- netbox/templates/dcim/device_edit.html | 12 ++-- netbox/templates/dcim/devicebay_populate.html | 8 +-- .../dcim/inc/interface_vlans_table.html | 8 +-- netbox/templates/dcim/manufacturer.html | 2 +- netbox/templates/dcim/module.html | 2 +- .../dcim/panels/rack_elevations.html | 2 +- .../templates/dcim/virtualchassis_edit.html | 4 +- netbox/templates/generic/object_edit.html | 6 +- netbox/templates/generic/object_list.html | 4 +- netbox/templates/inc/filter_list.html | 4 +- netbox/templates/inc/light_toggle.html | 8 +-- netbox/templates/inc/notification_bell.html | 8 ++- netbox/templates/inc/paginator.html | 24 ++++---- netbox/templates/inc/table_controls_htmx.html | 12 ++-- netbox/templates/inc/toast.html | 5 +- netbox/templates/inc/user_menu.html | 18 +++--- .../virtualization/virtualmachine/base.html | 2 +- netbox/utilities/forms/fields/fields.py | 2 +- .../utilities/templates/buttons/bookmark.html | 4 +- .../templates/buttons/subscribe.html | 4 +- .../templates/form_helpers/render_field.html | 22 ++++---- .../form_helpers/render_fieldset.html | 14 ++--- .../templates/helpers/utilization_graph.html | 2 + .../utilities/templates/navigation/menu.html | 10 ++-- .../templates/widgets/apiselect.html | 6 +- .../templates/widgets/markdown_input.html | 4 +- netbox/utilities/templatetags/form_helpers.py | 56 ++++++++++++++++++- netbox/utilities/tests/test_templatetags.py | 42 ++++++++++++++ netbox/virtualization/forms/model_forms.py | 3 +- 34 files changed, 219 insertions(+), 103 deletions(-) diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index 9672cc54b..7745deb60 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -690,7 +690,8 @@ class DeviceForm(TenancyForm, PrimaryModelForm): ) local_context_data = JSONField( required=False, - label='' + label='', + widget=forms.Textarea(attrs={'aria-label': _('Local config context data')}) ) virtual_chassis = DynamicModelChoiceField( label=_('Virtual chassis'), diff --git a/netbox/netbox/forms/mixins.py b/netbox/netbox/forms/mixins.py index 681047f56..2f031c70f 100644 --- a/netbox/netbox/forms/mixins.py +++ b/netbox/netbox/forms/mixins.py @@ -109,6 +109,10 @@ class SavedFiltersMixin(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + # Ensure the underlying ') + return format_html( + '', + title_text, title_text, + ) class BooleanColumn(tables.Column): diff --git a/netbox/templates/account/preferences.html b/netbox/templates/account/preferences.html index b2898da6c..3550bd1cb 100644 --- a/netbox/templates/account/preferences.html +++ b/netbox/templates/account/preferences.html @@ -44,7 +44,7 @@
- + {% trans "Table" %} {% trans "Ordering" %}
- + {{ table }} {{ prefs.ordering|join:", "|placeholder }}{{ obj.untagged_vlan|linkify:"vid" }} {{ obj.untagged_vlan.name }} - + - +
{{ vlan|linkify:"vid" }} {{ vlan.name }} - + - +
{% if virtual_chassis.pk %} - + {% endif %} diff --git a/netbox/templates/generic/object_edit.html b/netbox/templates/generic/object_edit.html index ad880220d..2149cae2d 100644 --- a/netbox/templates/generic/object_edit.html +++ b/netbox/templates/generic/object_edit.html @@ -32,8 +32,8 @@ Context: {# Link to model documentation #} {% if settings.DOCS_ROOT and object.docs_url %} - - {% trans "Help" %} + + {% trans "Help" %} {% endif %} @@ -51,7 +51,7 @@ Context: {% endblock tabs %} {% block content %} -
+
{# Warn about missing prerequisite objects #} {% if prerequisite_model %} diff --git a/netbox/templates/generic/object_list.html b/netbox/templates/generic/object_list.html index 0780a39aa..a8f792304 100644 --- a/netbox/templates/generic/object_list.html +++ b/netbox/templates/generic/object_list.html @@ -38,14 +38,14 @@ Context: {% block tabs %}