diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
deleted file mode 100644
index 6292b9c7..00000000
--- a/.pre-commit-config.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-repos:
-- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.6.0
- hooks:
- - id: check-yaml
-
-- repo: https://github.com/PyCQA/isort
- rev: 5.13.2
- hooks:
- - id: isort
-
-- repo: https://github.com/psf/black
- rev: 24.4.2
- hooks:
- - id: black
- name: black
-
-- repo: https://github.com/pycqa/flake8
- rev: 7.1.0
- hooks:
- - id: flake8
-
-- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.10.1
- hooks:
- - id: mypy
- additional_dependencies: [types-setuptools, pydantic==1.10.4]
-
-- repo: https://github.com/executablebooks/mdformat
- rev: 0.7.17
- hooks:
- - id: mdformat
- additional_dependencies: [mdformat-gfm, mdformat-frontmatter, mdformat-pyproject]
-
-default_language_version:
- python: python3
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 3b654d3f..00000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# Development
-
-To get started with working on the codebase, use the following steps prepare your local environment:
-
-```bash
-# clone the github repo and navigate into the folder
-git clone https://github.com/ApeWorX/ape-vyper.git
-cd ape-vyper
-
-# create and load a virtual environment
-python3 -m venv venv
-source venv/bin/activate
-
-# install ape-vyper into the virtual environment
-python setup.py install
-
-# install the developer dependencies (-e is interactive mode)
-pip install -e .'[dev]'
-```
-
-## Pre-Commit Hooks
-
-We use [`pre-commit`](https://pre-commit.com/) hooks to simplify linting and ensure consistent formatting among contributors.
-Use of `pre-commit` is not a requirement, but is highly recommended.
-
-Install `pre-commit` locally from the root folder:
-
-```bash
-pip install pre-commit
-pre-commit install
-```
-
-Committing will now automatically run the local hooks and ensure that your commit passes all lint checks.
-
-## Pull Requests
-
-Pull requests are welcomed! Please adhere to the following:
-
-- Ensure your pull request passes our linting checks
-- Include test cases for any new functionality
-- Include any relevant documentation updates
-
-It's a good idea to make pull requests early on.
-A pull request represents the start of a discussion, and doesn't necessarily need to be the final, finished submission.
-
-If you are opening a work-in-progress pull request to verify that it passes CI tests, please consider
-[marking it as a draft](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests).
-
-Join the ApeWorX [Discord](https://discord.gg/apeworx) if you have any questions.
-
-## Testing
-
-By default, the test suite will use a new, temporary path for the Vyper compiler installations.
-This ensures that the tests always run from a clean slate without any relying on existing installations.
-
-If you wish to use your existing `~/.vvm` installations instead, you must set the environment variable `APE_VYPER_USE_SYSTEM_VYPER=1`.
-
-This will ensure that vvm's default path will be used, but any compilers installed as part of the tests will not be removed after tests have completed.
diff --git a/README.md b/README.md
index 9d3ae00d..aefaeb69 100644
--- a/README.md
+++ b/README.md
@@ -1,132 +1 @@
-# Quick Start
-
-Ape compiler plugin around [VVM](https://github.com/vyperlang/vvm)
-
-## Dependencies
-
-- [python3](https://www.python.org/downloads) version 3.10 up to 3.12.
-
-## Installation
-
-### via `pip`
-
-You can install the latest release via [`pip`](https://pypi.org/project/pip/):
-
-```bash
-pip install ape-vyper
-```
-
-### via `setuptools`
-
-You can clone the repository and use [`setuptools`](https://github.com/pypa/setuptools) for the most up-to-date version:
-
-```bash
-git clone https://github.com/ApeWorX/ape-vyper.git
-cd ape-vyper
-python3 setup.py install
-```
-
-## Quick Usage
-
-First, place Vyper contract source files (files with extension `.vy`) in your Ape project's contracts folder.
-An example Vyper contract can be found [here](https://vyper.readthedocs.io/en/stable/vyper-by-example.html).
-Then, from your root Ape project folder, run the command:
-
-```bash
-ape compile
-```
-
-The `.vy` files in your project will compile into `ContractTypes` that you can deploy and interact with in Ape.
-
-### Contract Flattening
-
-For ease of publishing, validation, and some other cases it's sometimes useful to "flatten" your contract into a single file.
-This combines your contract and any imported interfaces together in a way the compiler can understand.
-You can do so with a command like this:
-
-```bash
-ape vyper flatten contracts/MyContract.vy build/MyContractFlattened.vy
-```
-
-> \[!WARNING\]
-> This feature is experimental. Please [report any bugs](https://github.com/ApeWorX/ape-solidity/issues/new?assignees=&labels=bug&projects=&template=bug.md) you find when trying it out.
-
-### Compiler Version
-
-By default, the `ape-vyper` plugin uses version pragma for version specification.
-However, you can also configure the version directly in your `ape-config.yaml` file:
-
-```yaml
-vyper:
- version: 0.3.7
-```
-
-### EVM Versioning
-
-By default, `ape-vyper` will use whatever version of EVM rules are set as default in the compiler version that gets used,
-or based on what the `#pragma evm-version ...` pragma comment specifies (available post-`v0.3.10`).
-Sometimes, you might want to use a different version, such as deploying on Arbitrum or Optimism where new opcodes are not supported yet.
-If you want to require a different version of EVM rules to use in the configuration of the compiler, set it in your `ape-config.yaml` like this:
-
-```yaml
-vyper:
- evm_version: paris
-```
-
-**NOTE**: The config value chosen will not override if a pragma is set in a contract.
-
-### Interfaces
-
-You can not compile interface source files directly.
-Thus, you must place interface files in a directory named `interfaces` in your `contracts_folder` e.g. `contracts/interfaces/IFace.vy`.
-Then, these files can be imported in other `.vy` sources files via:
-
-```python
-import interfaces.IFace as IFace
-```
-
-Alternatively, use JSON interfaces from dependency contract types by listing them under the `import_remapping` key:
-
-```yaml
-# Use `voting` example contracts from Vyperlang repo.
-dependencies:
- - name: VyperVoting
- github: vyperlang/vyper
- contracts_folder: examples/voting/
- version: v0.3.8
-
-# Automatically allow importing voting contracts in your project.
-vyper:
- import_remapping:
- - "voting=VyperVoting@v0.3.8"
-```
-
-Import the voting contract types like this:
-
-```python
-# @version 0.3.10
-
-import voting.ballot as ballot
-```
-
-### Pragmas
-
-Ape-Vyper supports Vyper 0.3.10's [new pragma formats](https://github.com/vyperlang/vyper/pull/3493)
-
-#### Version Pragma
-
-```python
-#pragma version 0.3.10
-```
-
-#### EVM Version Pragma
-
-```python
-#pragma evm-version paris
-```
-
-#### Optimization Pragma
-
-```python
-#pragma optimize codesize
-```
+# ape-vyper
\ No newline at end of file
diff --git a/ape_vyper/__init__.py b/ape_vyper/__init__.py
deleted file mode 100644
index ebd7db41..00000000
--- a/ape_vyper/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from ape import plugins
-
-from .compiler import FileType, VyperCompiler, VyperConfig
-
-
-@plugins.register(plugins.Config)
-def config_class():
- return VyperConfig
-
-
-@plugins.register(plugins.CompilerPlugin)
-def register_compiler():
- return tuple(e.value for e in FileType), VyperCompiler
diff --git a/ape_vyper/_cli.py b/ape_vyper/_cli.py
deleted file mode 100644
index bfddd372..00000000
--- a/ape_vyper/_cli.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from pathlib import Path
-
-import ape
-import click
-from ape.cli import ape_cli_context, project_option
-
-
-@click.group
-def cli():
- """`vyper` command group"""
-
-
-@cli.command(short_help="Flatten select contract source files")
-@ape_cli_context()
-@project_option()
-@click.argument("CONTRACT", type=click.Path(exists=True, resolve_path=True))
-@click.argument("OUTFILE", type=click.Path(exists=False, resolve_path=True, writable=True))
-def flatten(cli_ctx, project, contract: Path, outfile: Path):
- """
- Flatten a contract into a single file
- """
- with Path(outfile).open("w") as fout:
- content = ape.compilers.vyper.flatten_contract(
- Path(contract),
- base_path=ape.project.contracts_folder,
- project=project,
- )
- fout.write(str(content))
diff --git a/ape_vyper/ast.py b/ape_vyper/ast.py
deleted file mode 100644
index e9b40838..00000000
--- a/ape_vyper/ast.py
+++ /dev/null
@@ -1,99 +0,0 @@
-"""Utilities for dealing with Vyper AST"""
-
-from ethpm_types import ABI, MethodABI
-from ethpm_types.abi import ABIType
-from vyper.ast import parse_to_ast # type: ignore
-from vyper.ast.nodes import FunctionDef, Module, Name, Subscript # type: ignore
-
-DEFAULT_VYPER_MUTABILITY = "nonpayable"
-DECORATOR_MUTABILITY = {
- "pure", # Function does not read contract state or environment variables
- "view", # Function does not alter contract state
- "payable", # Function is able to receive Ether and may alter state
- "nonpayable", # Function may alter sate
-}
-
-
-def funcdef_decorators(funcdef: FunctionDef) -> list[str]:
- return [d.id for d in funcdef.get("decorator_list") or []]
-
-
-def funcdef_inputs(funcdef: FunctionDef) -> list[ABIType]:
- """Get a FunctionDef's defined input args"""
- args = funcdef.get("args")
- # TODO: Does Vyper allow complex input types, like structs and arrays?
- return (
- [ABIType.model_validate({"name": arg.arg, "type": arg.annotation.id}) for arg in args.args]
- if args
- else []
- )
-
-
-def funcdef_outputs(funcdef: FunctionDef) -> list[ABIType]:
- """Get a FunctionDef's outputs, or return values"""
- returns = funcdef.get("returns")
-
- if not returns:
- return []
-
- if isinstance(returns, Name):
- # TODO: Structs fall in here. I think they're supposed to be a tuple of types in the ABI.
- # Need to dig into that more.
- return [ABIType.model_validate({"type": returns.id})]
-
- elif isinstance(returns, Subscript):
- # An array type
- length = returns.slice.value.value
- if array_type := getattr(returns.value, "id", None):
- # TOOD: Is this an accurate way to define a fixed length array for ABI?
- return [ABIType.model_validate({"type": f"{array_type}[{length}]"})]
-
- raise NotImplementedError(f"Unhandled return type {type(returns)}")
-
-
-def funcdef_state_mutability(funcdef: FunctionDef) -> str:
- """Get a FunctionDef's declared state mutability"""
- for decorator in funcdef_decorators(funcdef):
- if decorator in DECORATOR_MUTABILITY:
- return decorator
- return DEFAULT_VYPER_MUTABILITY
-
-
-def funcdef_is_external(funcdef: FunctionDef) -> bool:
- """Check if a FunctionDef is declared external"""
- for decorator in funcdef_decorators(funcdef):
- if decorator == "external":
- return True
- return False
-
-
-def funcdef_to_abi(func: FunctionDef) -> ABI:
- """Return a MethodABI instance for a Vyper FunctionDef"""
- return MethodABI.model_validate(
- {
- "name": func.get("name"),
- "inputs": funcdef_inputs(func),
- "outputs": funcdef_outputs(func),
- "stateMutability": funcdef_state_mutability(func),
- }
- )
-
-
-def module_to_abi(module: Module) -> list[ABI]:
- """
- Create a list of MethodABIs from a Vyper AST Module instance.
- """
- abi = []
- for child in module.get_children():
- if isinstance(child, FunctionDef):
- abi.append(funcdef_to_abi(child))
- return abi
-
-
-def source_to_abi(source: str) -> list[ABI]:
- """
- Given Vyper source code, return a list of Ape ABI elements needed for an external interface.
- This currently does not include complex types or events.
- """
- module = parse_to_ast(source)
- return module_to_abi(module)
diff --git a/ape_vyper/compiler.py b/ape_vyper/compiler.py
deleted file mode 100644
index 96486dfc..00000000
--- a/ape_vyper/compiler.py
+++ /dev/null
@@ -1,2084 +0,0 @@
-import os
-import re
-import shutil
-import time
-from base64 import b64encode
-from collections import defaultdict
-from collections.abc import Iterable, Iterator
-from enum import Enum
-from fnmatch import fnmatch
-from importlib import import_module
-from pathlib import Path
-from site import getsitepackages
-from typing import Any, Optional, Union, cast
-
-import vvm # type: ignore
-from ape.api import PluginConfig, TraceAPI
-from ape.api.compiler import CompilerAPI
-from ape.exceptions import ContractLogicError, ProjectError
-from ape.logging import logger
-from ape.managers.project import LocalProject, ProjectManager
-from ape.types import ContractSourceCoverage, ContractType, SourceTraceback
-from ape.utils import cached_property, get_relative_path, pragma_str_to_specifier_set
-from ape.utils._github import _GithubClient
-from ape.utils.os import clean_path, get_full_extension
-from eth_pydantic_types import HexBytes
-from eth_utils import is_0x_prefixed
-from ethpm_types import ASTNode, PackageManifest, PCMap, SourceMapItem
-from ethpm_types.ast import ASTClassification
-from ethpm_types.contract_type import SourceMap
-from ethpm_types.source import Compiler, Content, ContractSource, Function, SourceLocation
-from evm_trace import TraceFrame
-from evm_trace.enums import CALL_OPCODES
-from evm_trace.geth import create_call_node_data
-from packaging.specifiers import InvalidSpecifier, SpecifierSet
-from packaging.version import Version
-from pydantic import field_serializer, field_validator, model_validator
-from vvm import compile_standard as vvm_compile_standard
-from vvm.exceptions import VyperError # type: ignore
-
-from ape_vyper.ast import source_to_abi
-from ape_vyper.exceptions import (
- RUNTIME_ERROR_MAP,
- IntegerBoundsCheck,
- RuntimeErrorType,
- VyperCompileError,
- VyperInstallError,
-)
-from ape_vyper.interface import (
- extract_import_aliases,
- extract_imports,
- extract_meta,
- generate_interface,
-)
-
-DEV_MSG_PATTERN = re.compile(r".*\s*#\s*(dev:.+)")
-_RETURN_OPCODES = ("RETURN", "REVERT", "STOP")
-_FUNCTION_DEF = "FunctionDef"
-_FUNCTION_AST_TYPES = (_FUNCTION_DEF, "Name", "arguments")
-_EMPTY_REVERT_OFFSET = 18
-_NON_PAYABLE_STR = f"dev: {RuntimeErrorType.NONPAYABLE_CHECK.value}"
-Optimization = Union[str, bool]
-
-EVM_VERSION_DEFAULT = {
- "0.2.15": "berlin",
- "0.2.16": "berlin",
- "0.3.0": "berlin",
- "0.3.1": "berlin",
- "0.3.2": "berlin",
- "0.3.3": "berlin",
- "0.3.4": "berlin",
- "0.3.6": "berlin",
- "0.3.7": "paris",
- "0.3.8": "shanghai",
- "0.3.9": "shanghai",
- "0.3.10": "shanghai",
- "0.4.0": "shanghai",
-}
-
-
-class FileType(str, Enum):
- SOURCE = ".vy"
- INTERFACE = ".vyi"
-
- def __str__(self) -> str:
- return self.value
-
-
-class Remapping(PluginConfig):
- key: str
- dependency_name: str
- dependency_version: Optional[None] = None
-
- @model_validator(mode="before")
- @classmethod
- def validate_str(cls, value):
- if isinstance(value, str):
- parts = value.split("=")
- key = parts[0].strip()
- value = parts[1].strip()
- if "@" in value:
- value_parts = value.split("@")
- dep_name = value_parts[0].strip()
- dep_version = value_parts[1].strip()
- else:
- dep_name = value
- dep_version = None
-
- return {"key": key, "dependency_name": dep_name, "dependency_version": dep_version}
-
- return value
-
- def __str__(self) -> str:
- value = self.dependency_name
- if _version := self.dependency_version:
- value = f"{value}@{_version}"
-
- return f"{self.key}={value}"
-
-
-class VyperConfig(PluginConfig):
- version: Optional[SpecifierSet] = None
- """
- Configure a version to use for all files,
- regardless of pragma.
- """
-
- evm_version: Optional[str] = None
- """
- The evm-version or hard-fork name.
- """
-
- import_remapping: list[Remapping] = []
- """
- Configuration of an import name mapped to a dependency listing.
- To use a specific version of a dependency, specify using ``@`` symbol.
-
- Usage example::
-
- vyper:
- import_remapping:
- - "dep_a=dependency_a@0.1.1"
- - "dep_b=dependency" # Uses only version. Will raise if more than 1.
-
- """
-
- @field_validator("version", mode="before")
- def validate_version(cls, value):
- return pragma_str_to_specifier_set(value) if isinstance(value, str) else value
-
- @field_serializer("version")
- def serialize_version(self, value: Optional[SpecifierSet], _info) -> Optional[str]:
- if version := value:
- return str(version)
-
- return None
-
-
-def _install_vyper(version: Version):
- try:
- vvm.install_vyper(version, show_progress=True)
- except Exception as err:
- raise VyperInstallError(
- f"Unable to install Vyper version: '{version}'.\nReason: {err}"
- ) from err
-
-
-def get_version_pragma_spec(source: Union[str, Path]) -> Optional[SpecifierSet]:
- """
- Extracts version pragma information from Vyper source code.
-
- Args:
- source (str): Vyper source code
-
- Returns:
- ``packaging.specifiers.SpecifierSet``, or None if no valid pragma is found.
- """
- _version_pragma_patterns: tuple[str, str] = (
- r"(?:\n|^)\s*#\s*@version\s*([^\n]*)",
- r"(?:\n|^)\s*#\s*pragma\s+version\s*([^\n]*)",
- )
-
- source_str = source if isinstance(source, str) else source.read_text(encoding="utf8")
- for pattern in _version_pragma_patterns:
- for match in re.finditer(pattern, source_str):
- raw_pragma = match.groups()[0]
- pragma_str = " ".join(raw_pragma.split()).replace("^", "~=")
- if pragma_str and pragma_str[0].isnumeric():
- pragma_str = f"=={pragma_str}"
-
- try:
- return SpecifierSet(pragma_str)
- except InvalidSpecifier:
- logger.warning(f"Invalid pragma spec: '{raw_pragma}'. Trying latest.")
- return None
- return None
-
-
-def get_optimization_pragma(source: Union[str, Path]) -> Optional[str]:
- """
- Extracts optimization pragma information from Vyper source code.
-
- Args:
- source (Union[str, Path]): Vyper source code
-
- Returns:
- ``str``, or None if no valid pragma is found.
- """
- if isinstance(source, str):
- source_str = source
- elif not source.is_file():
- return None
- else:
- source_str = source.read_text(encoding="utf8")
-
- if pragma_match := next(
- re.finditer(r"(?:\n|^)\s*#pragma\s+optimize\s+([^\n]*)", source_str), None
- ):
- return pragma_match.groups()[0]
-
- return None
-
-
-def get_evmversion_pragma(source: Union[str, Path]) -> Optional[str]:
- """
- Extracts evm version pragma information from Vyper source code.
-
- Args:
- source (Union[str, Path]): Vyper source code
-
- Returns:
- ``str``, or None if no valid pragma is found.
- """
- if isinstance(source, str):
- source_str = source
- elif not source.is_file():
- return None
- else:
- source_str = source.read_text(encoding="utf8")
-
- if pragma_match := next(
- re.finditer(r"(?:\n|^)\s*#pragma\s+evm-version\s+([^\n]*)", source_str), None
- ):
- return pragma_match.groups()[0]
-
- return None
-
-
-def get_optimization_pragma_map(
- contract_filepaths: Iterable[Path],
- base_path: Path,
- default: Optimization,
-) -> dict[str, Optimization]:
- pragma_map: dict[str, Optimization] = {}
-
- for path in contract_filepaths:
- res = get_optimization_pragma(path)
- pragma = default if res is None else res
- source_id = str(get_relative_path(path.absolute(), base_path.absolute()))
- pragma_map[source_id] = pragma
-
- return pragma_map
-
-
-def get_evm_version_pragma_map(
- contract_filepaths: Iterable[Path], base_path: Path
-) -> dict[str, str]:
- pragmas: dict[str, str] = {}
- for path in contract_filepaths:
- pragma = get_evmversion_pragma(path)
- if not pragma:
- continue
-
- source_id = str(get_relative_path(path.absolute(), base_path.absolute()))
- pragmas[source_id] = pragma
-
- return pragmas
-
-
-def _lookup_source_from_site_packages(
- dependency_name: str,
- filestem: str,
- config_override: Optional[dict] = None,
-) -> Optional[tuple[Path, ProjectManager]]:
- # Attempt looking up dependency from site-packages.
- config_override = config_override or {}
- if "contracts_folder" not in config_override:
- # Default to looking through the whole release for
- # contracts. Most often, Python-based dependencies publish
- # only their contracts this way, and we are only looking
- # for sources so accurate project configuration is not required.
- config_override["contracts_folder"] = "."
-
- try:
- imported_project = ProjectManager.from_python_library(
- dependency_name,
- config_override=config_override,
- )
- except ProjectError as err:
- # Still attempt to let Vyper handle this during compilation.
- logger.error(
- f"'{dependency_name}' may not be installed. "
- "Could not find it in Ape dependencies or Python's site-packages. "
- f"Error: {err}"
- )
- else:
- extensions = [*[f"{t}" for t in FileType], ".json"]
-
- def seek() -> Optional[Path]:
- for ext in extensions:
- try_source_id = f"{filestem}{ext}"
- if source_path := imported_project.sources.lookup(try_source_id):
- return source_path
-
- return None
-
- if res := seek():
- return res, imported_project
-
- # Still not found. Try again without contracts_folder set.
- # This will attempt to use Ape's contracts_folder detection system.
- # However, I am not sure this situation occurs, as Vyper-python
- # based dependencies are new at the time of writing this.
- new_override = config_override or {}
- if "contracts_folder" in new_override:
- del new_override["contracts_folder"]
-
- imported_project.reconfigure(**new_override)
- if res := seek():
- return res, imported_project
-
- # Still not found. Log a very helpful message.
- existing_filestems = [f.stem for f in imported_project.path.iterdir()]
- fs_str = ", ".join(existing_filestems)
- contracts_folder = imported_project.contracts_folder
- path = imported_project.path
-
- # This will log the calculated / user-set contracts_folder.
- contracts_path = f"{get_relative_path(contracts_folder, path)}"
-
- logger.error(
- f"Source for stem '{filestem}' not found in "
- f"'{imported_project.path}'."
- f"Contracts folder: {contracts_path}, "
- f"Existing file(s): {fs_str}"
- )
-
- return None
-
-
-class VyperCompiler(CompilerAPI):
- @property
- def name(self) -> str:
- return "vyper"
-
- def get_imports(
- self,
- contract_filepaths: Iterable[Path],
- project: Optional[ProjectManager] = None,
- ) -> dict[str, list[str]]:
- pm = project or self.local_project
- return self._get_imports(contract_filepaths, project=pm, handled=set())
-
- def _get_imports(
- self,
- contract_filepaths: Iterable[Path],
- project: Optional[ProjectManager] = None,
- handled: Optional[set[str]] = None,
- ):
- pm = project or self.local_project
-
- # When compiling projects outside the cwd, we must
- # use absolute paths.
- use_absolute_paths = pm.path != Path.cwd()
-
- import_map: defaultdict = defaultdict(list)
- handled = handled or set()
- dependencies = self.get_dependencies(project=pm)
- for path in contract_filepaths:
- if not path.is_file():
- continue
-
- content = path.read_text().splitlines()
- source_id = (
- str(path.absolute())
- if use_absolute_paths
- else str(get_relative_path(path.absolute(), pm.path.absolute()))
- )
-
- # Prevent infinitely handling imports when they cross over.
- if source_id in handled:
- continue
-
- handled.add(source_id)
- for line in content:
- if line.startswith("import "):
- import_line_parts = line.replace("import ", "").split(" ")
- prefix = import_line_parts[0]
-
- elif line.startswith("from ") and " import " in line:
- import_line_parts = line.replace("from ", "").strip().split(" ")
- module_name = import_line_parts[0].strip()
- prefix = os.path.sep.join([module_name, import_line_parts[2].strip()])
-
- else:
- # Not an import line
- continue
-
- dots = ""
- while prefix.startswith("."):
- dots += prefix[0]
- prefix = prefix[1:]
-
- is_relative = dots != ""
-
- # Replace rest of dots with slashes.
- prefix = prefix.replace(".", os.path.sep)
-
- if prefix.startswith("vyper/") or prefix.startswith("ethereum/"):
- if f"{prefix}.json" not in import_map[source_id]:
- import_map[source_id].append(f"{prefix}.json")
-
- continue
-
- local_path = (
- (path.parent / dots / prefix.lstrip(os.path.sep)).resolve()
- if is_relative
- else (pm.path / prefix.lstrip(os.path.sep)).resolve()
- )
- local_prefix = str(local_path).replace(f"{pm.path}", "").lstrip(os.path.sep)
-
- import_source_id = None
- is_local = True
-
- # NOTE: Defaults to JSON (assuming from input JSON or a local JSON),
- # unless a Vyper file exists.
- if (pm.path / f"{local_prefix}{FileType.SOURCE}").is_file():
- ext = FileType.SOURCE.value
- elif (pm.path / f"{local_prefix}{FileType.SOURCE}").is_file():
- ext = FileType.INTERFACE.value
- elif (pm.path / f"{local_prefix}{FileType.INTERFACE}").is_file():
- ext = FileType.INTERFACE.value
- else:
- ext = ".json"
- dep_key = prefix.split(os.path.sep)[0]
- dependency_name = prefix.split(os.path.sep)[0]
- filestem = prefix.replace(f"{dependency_name}{os.path.sep}", "")
- if dep_key in dependencies:
- for version_str, dep_project in pm.dependencies[dependency_name].items():
- dependency = pm.dependencies.get_dependency(
- dependency_name, version_str
- )
- path_id = dependency.package_id.replace("/", "_")
- contracts_path = dep_project.contracts_folder
- dependency_source_prefix = (
- f"{get_relative_path(contracts_path, dep_project.path)}"
- )
- source_id_stem = f"{dependency_source_prefix}{os.path.sep}{filestem}"
- for ext in (".vy", ".json"):
- if f"{source_id_stem}{ext}" in dep_project.sources:
- import_source_id = os.path.sep.join(
- (path_id, version_str, f"{source_id_stem}{ext}")
- )
-
- # Also include imports of imports.
- sub_imports = self._get_imports(
- (dep_project.path / f"{source_id_stem}{ext}",),
- project=dep_project,
- handled=handled,
- )
- for sub_import_ls in sub_imports.values():
- import_map[source_id].extend(sub_import_ls)
-
- is_local = False
- break
- elif dependency_name:
- # Attempt looking up dependency from site-packages.
- if res := _lookup_source_from_site_packages(dependency_name, filestem):
- source_path, imported_project = res
- import_source_id = str(source_path)
- # Also include imports of imports.
- sub_imports = self._get_imports(
- (source_path,),
- project=imported_project,
- handled=handled,
- )
- for sub_import_ls in sub_imports.values():
- import_map[source_id].extend(sub_import_ls)
-
- is_local = False
-
- if is_local:
- import_source_id = f"{local_prefix}{ext}"
- full_path = local_path.parent / f"{local_path.stem}{ext}"
-
- # Also include imports of imports.
- sub_imports = self._get_imports((full_path,), project=project, handled=handled)
- for sub_import_ls in sub_imports.values():
- import_map[source_id].extend(sub_import_ls)
-
- if use_absolute_paths:
- import_source_id = str(full_path)
-
- if import_source_id and import_source_id not in import_map[source_id]:
- import_map[source_id].append(import_source_id)
-
- return dict(import_map)
-
- def get_versions(self, all_paths: Iterable[Path]) -> set[str]:
- versions = set()
- for path in all_paths:
- if version_spec := get_version_pragma_spec(path):
- try:
- # Make sure we have the best compiler available to compile this
- version_iter = version_spec.filter(self.available_versions)
-
- except VyperInstallError as err:
- # Possible internet issues. Try to stick to installed versions.
- logger.error(
- "Error checking available versions, possibly due to Internet problems. "
- "Attempting to use the best installed version. "
- f"Error: {err}"
- )
- version_iter = version_spec.filter(self.installed_versions)
-
- matching_versions = sorted(list(version_iter))
- if matching_versions:
- versions.add(str(matching_versions[0]))
-
- return versions
-
- @cached_property
- def package_version(self) -> Optional[Version]:
- try:
- vyper = import_module("vyper")
- except ModuleNotFoundError:
- return None
-
- version_str = getattr(vyper, "__version__", None)
- return Version(version_str) if version_str else None
-
- @cached_property
- def available_versions(self) -> list[Version]:
- # NOTE: Package version should already be included in available versions
- max_retries = 10
- buffer = 1
- times_tried = 0
- result = []
- headers = None
- if token := os.environ.get(_GithubClient.TOKEN_KEY):
- auth = b64encode(token.encode()).decode()
- headers = {"Authorization": f"Basic {auth}"}
-
- while times_tried < max_retries:
- try:
- result = vvm.get_installable_vyper_versions(headers=headers)
- except ConnectionError as err:
- if "API rate limit exceeded" in str(err):
- if times_tried == max_retries:
- raise VyperInstallError(str(err)) from err
-
- # Retry
- logger.warning(
- f"GitHub throttled requests. Retrying in '{buffer}' seconds. "
- f"Tries left={max_retries - times_tried}"
- )
- time.sleep(buffer)
- buffer += 1
- times_tried += 1
- continue
-
- else:
- # This is a different error.
- raise VyperInstallError(str(err)) from err
-
- # Succeeded.
- break
-
- return result
-
- @property
- def installed_versions(self) -> list[Version]:
- # Doing this so it prefers package version
- package_version = self.package_version
- versions = [package_version] if package_version else []
- # currently package version is [] this should be ok
- return versions + vvm.get_installed_vyper_versions()
-
- @cached_property
- def vyper_json(self):
- try:
- from vyper.cli import vyper_json # type: ignore
-
- return vyper_json
- except ImportError:
- return None
-
- def get_dependencies(
- self, project: Optional[ProjectManager] = None
- ) -> dict[str, ProjectManager]:
- pm = project or self.local_project
- config = self.get_config(project=pm)
- dependencies: dict[str, ProjectManager] = {}
- handled: set[str] = set()
-
- # Add remappings from config.
- for remapping in config.import_remapping:
- name = remapping.dependency_name
- if not (_version := remapping.dependency_version):
- versions = pm.dependencies[name]
- if len(versions) == 1:
- _version = versions[0]
- else:
- continue
-
- dependency = pm.dependencies.get_dependency(name, _version)
- dep_id = f"{dependency.name}_{dependency.version}"
- if dep_id in handled or (
- isinstance(dependency.project, LocalProject) and dependency.project.path == pm.path
- ):
- continue
-
- handled.add(dep_id)
-
- try:
- dependency.compile()
- except Exception as err:
- logger.warning(
- f"Failed to compile dependency '{dependency.name}' @ '{dependency.version}'.\n"
- f"Reason: {err}"
- )
- continue
-
- dependencies[remapping.key] = dependency.project
-
- # Add auto-remapped dependencies.
- for dependency in pm.dependencies.specified:
- dep_id = f"{dependency.name}_{dependency.version}"
- if dep_id in handled or (
- isinstance(dependency.project, LocalProject) and dependency.project.path == pm.path
- ):
- continue
-
- handled.add(dep_id)
-
- try:
- dependency.compile()
- except Exception as err:
- logger.warning(
- f"Failed to compile dependency '{dependency.name}' @ '{dependency.version}'.\n"
- f"Reason: {err}"
- )
- continue
-
- dependencies[dependency.name] = dependency.project
-
- return dependencies
-
- def get_import_remapping(self, project: Optional[ProjectManager] = None) -> dict[str, dict]:
- """
- Configured interface imports from dependencies.
- """
- pm = project or self.local_project
- dependencies = self.get_dependencies(project=pm)
- interfaces: dict[str, dict] = {}
- for key, dependency_project in dependencies.items():
- manifest = dependency_project.manifest
- for name, ct in (manifest.contract_types or {}).items():
- filename = f"{key}/{name}.json"
- abi_list = [x.model_dump(mode="json", by_alias=True) for x in ct.abi]
- interfaces[filename] = {"abi": abi_list}
-
- return interfaces
-
- def classify_ast(self, _node: ASTNode):
- if _node.ast_type in _FUNCTION_AST_TYPES:
- _node.classification = ASTClassification.FUNCTION
-
- for child in _node.children:
- self.classify_ast(child)
-
- def compile(
- self,
- contract_filepaths: Iterable[Path],
- project: Optional[ProjectManager] = None,
- settings: Optional[dict] = None,
- ) -> Iterator[ContractType]:
- pm = project or self.local_project
-
- # (0.4.0): If compiling a project outside the cwd (such as a dependency),
- # we are forced to use absolute paths.
- use_absolute_paths = pm.path != Path.cwd()
-
- self.compiler_settings = {**self.compiler_settings, **(settings or {})}
- contract_types: list[ContractType] = []
- import_map = self.get_imports(contract_filepaths, project=pm)
- config = self.get_config(pm)
- version_map = self._get_version_map_from_import_map(
- contract_filepaths,
- import_map,
- project=pm,
- config=config,
- )
- compiler_data = self._get_compiler_arguments(version_map, project=pm, config=config)
- all_settings = self._get_compiler_settings_from_version_map(version_map, project=pm)
- contract_versions: dict[str, tuple[Version, str]] = {}
- import_remapping = self.get_import_remapping(project=pm)
-
- for vyper_version, version_settings in all_settings.items():
- for settings_key, settings_set in version_settings.items():
- if vyper_version >= Version("0.4.0rc1"):
- sources = settings_set.get("outputSelection", {})
- if not sources:
- continue
-
- if use_absolute_paths:
- src_dict = {
- str(pm.path / p): {"content": (pm.path / p).read_text(encoding="utf8")}
- for p in sources
- }
- else:
- src_dict = {
- p: {"content": Path(p).read_text(encoding="utf8")} for p in sources
- }
-
- for src in sources:
- if Path(src).is_absolute():
- src_id = (
- str(Path(src))
- if use_absolute_paths
- else f"{get_relative_path(Path(src), pm.path)}"
- )
- else:
- src_id = src
-
- if imports := import_map.get(src_id):
- for imp in imports:
- if imp in src_dict:
- continue
-
- imp_path = Path(imp)
- if (pm.path / imp).is_file():
- imp_path = pm.path / imp
- if not imp_path.is_file():
- continue
-
- src_dict[imp] = {"content": imp_path.read_text(encoding="utf8")}
-
- else:
- for parent in imp_path.parents:
- if parent.name == "site-packages":
- src_id = f"{get_relative_path(imp_path, parent)}"
- break
-
- elif parent.name == ".ape":
- dm = self.local_project.dependencies
- full_parent = dm.packages_cache.projects_folder
- src_id = f"{get_relative_path(imp_path, full_parent)}"
- break
-
- # Likely from a dependency. Exclude absolute prefixes so Vyper
- # knows what to do.
- if imp_path.is_file():
- src_dict[src_id] = {
- "content": imp_path.read_text(encoding="utf8")
- }
-
- else:
- # NOTE: Pre vyper 0.4.0, interfaces CANNOT be in the source dict,
- # but post 0.4.0, they MUST be.
- src_dict = {
- s: {"content": p.read_text(encoding="utf8")}
- for s, p in {
- p: pm.path / p for p in settings_set["outputSelection"]
- }.items()
- if p.parent != pm.path / "interfaces"
- }
-
- input_json: dict = {
- "language": "Vyper",
- "settings": settings_set,
- "sources": src_dict,
- }
-
- if interfaces := import_remapping:
- input_json["interfaces"] = interfaces
-
- # Output compiler details.
- keys = (
- "\n\t".join(
- sorted(
- [
- clean_path(Path(x))
- for x in settings_set.get("outputSelection", {}).keys()
- ]
- )
- )
- or "No input."
- )
- log_str = f"Compiling using Vyper compiler '{vyper_version}'.\nInput:\n\t{keys}"
- logger.info(log_str)
-
- vyper_binary = compiler_data[vyper_version]["vyper_binary"]
- comp_kwargs = {"vyper_version": vyper_version, "vyper_binary": vyper_binary}
-
- # `base_path` is required for pre-0.4 versions or else imports won't resolve.
- if vyper_version < Version("0.4.0"):
- comp_kwargs["base_path"] = pm.path
-
- try:
- result = vvm_compile_standard(input_json, **comp_kwargs)
- except VyperError as err:
- raise VyperCompileError(err) from err
-
- for source_id, output_items in result["contracts"].items():
- content = {
- i + 1: ln
- for i, ln in enumerate(
- (pm.path / source_id).read_text(encoding="utf8").splitlines()
- )
- }
- for name, output in output_items.items():
- # De-compress source map to get PC POS map.
- ast = ASTNode.model_validate(result["sources"][source_id]["ast"])
- self.classify_ast(ast)
-
- # Track function offsets.
- function_offsets = []
- for node in ast.children:
- lineno = node.lineno
-
- # NOTE: Constructor is handled elsewhere.
- if node.ast_type == "FunctionDef" and "__init__" not in content.get(
- lineno, ""
- ):
- function_offsets.append((node.lineno, node.end_lineno))
-
- evm = output["evm"]
- bytecode = evm["deployedBytecode"]
- opcodes = bytecode["opcodes"].split(" ")
-
- src_map_raw = bytecode["sourceMap"]
- if isinstance(src_map_raw, str):
- # <0.4 range.
- compressed_src_map = SourceMap(root=src_map_raw)
- else:
- # >=0.4 range.
- compressed_src_map = SourceMap(
- root=src_map_raw["pc_pos_map_compressed"]
- )
-
- src_map = list(compressed_src_map.parse())[1:]
-
- pcmap = (
- _get_legacy_pcmap(ast, src_map, opcodes)
- if vyper_version <= Version("0.3.7")
- else _get_pcmap(bytecode)
- )
-
- # Find content-specified dev messages.
- dev_messages = {}
- for line_no, line in content.items():
- if match := re.search(DEV_MSG_PATTERN, line):
- dev_messages[line_no] = match.group(1).strip()
-
- source_id_path = Path(source_id)
- if source_id_path.is_absolute():
- final_source_id = f"{get_relative_path(Path(source_id), pm.path)}"
- else:
- final_source_id = source_id
-
- contract_type = ContractType.model_validate(
- {
- "ast": ast,
- "contractName": name,
- "sourceId": final_source_id,
- "deploymentBytecode": {"bytecode": evm["bytecode"]["object"]},
- "runtimeBytecode": {"bytecode": bytecode["object"]},
- "abi": output["abi"],
- "sourcemap": compressed_src_map,
- "pcmap": pcmap,
- "userdoc": output["userdoc"],
- "devdoc": output["devdoc"],
- "dev_messages": dev_messages,
- }
- )
- contract_types.append(contract_type)
- contract_versions[name] = (vyper_version, settings_key)
- yield contract_type
-
- # Output compiler data used.
- compilers_used: dict[Version, dict[str, Compiler]] = {}
- for ct in contract_types:
- if not ct.name:
- # Won't happen, but just for mypy.
- continue
-
- ct_version, ct_settings_key = contract_versions[ct.name]
- settings = all_settings[ct_version][ct_settings_key]
-
- if ct_version not in compilers_used:
- compilers_used[ct_version] = {}
-
- if ct_settings_key in compilers_used[ct_version] and ct.name not in (
- compilers_used[ct_version][ct_settings_key].contractTypes or []
- ):
- # Add contractType to already-tracked compiler.
- compilers_used[ct_version][ct_settings_key].contractTypes = [
- *(compilers_used[ct_version][ct_settings_key].contractTypes or []),
- ct.name,
- ]
-
- elif ct_settings_key not in compilers_used[ct_version]:
- # Add optimization-compiler for the first time.
- compilers_used[ct_version][ct_settings_key] = Compiler(
- name=self.name.lower(),
- version=f"{ct_version}",
- contractTypes=[ct.name],
- settings=settings,
- )
-
- # Output compiler data to the cached project manifest.
- compilers_ls = [
- compiler
- for optimization_settings in compilers_used.values()
- for compiler in optimization_settings.values()
- ]
-
- # NOTE: This method handles merging contractTypes and filtered out
- # no longer used Compilers.
- pm.add_compiler_data(compilers_ls)
-
- def compile_code(
- self, code: str, project: Optional[ProjectManager] = None, **kwargs
- ) -> ContractType:
- # NOTE: We are unable to use `vvm.compile_code()` because it does not
- # appear to honor altered VVM install paths, thus always re-installs
- # Vyper in our tests because of the monkeypatch. Also, their approach
- # isn't really different than our approach implemented below.
- pm = project or self.local_project
- with pm.isolate_in_tempdir():
- name = kwargs.get("contractName", "code")
- file = pm.path / f"{name}.vy"
- file.write_text(code, encoding="utf8")
- contract_type = next(self.compile((file,), project=pm), None)
- if contract_type is None:
- # Not sure when this would happen.
- raise VyperCompileError("Failed to produce contract type.")
-
- return contract_type
-
- def _source_vyper_version(self, code: str) -> Version:
- """Given source code, figure out which Vyper version to use"""
- version_spec = get_version_pragma_spec(code)
-
- def first_full_release(versions: Iterable[Version]) -> Optional[Version]:
- for vers in versions:
- if not vers.is_devrelease and not vers.is_postrelease and not vers.is_prerelease:
- return vers
-
- return None
-
- if version_spec is None:
- if version := first_full_release(self.installed_versions + self.available_versions):
- return version
-
- raise VyperInstallError("No available version.")
-
- return next(version_spec.filter(self.available_versions))
-
- def _flatten_source(
- self,
- path: Path,
- project: Optional[ProjectManager] = None,
- include_pragma: bool = True,
- sources_handled: Optional[set[Path]] = None,
- warn_flattening_modules: bool = True,
- ) -> str:
- pm = project or self.local_project
- handled = sources_handled or set()
- handled.add(path)
- # Get the non stdlib import paths for our contracts
- imports = list(
- filter(
- lambda x: not x.startswith("vyper/"),
- [y for x in self.get_imports((path,), project=pm).values() for y in x],
- )
- )
-
- dependencies: dict[str, PackageManifest] = {}
- dependency_projects = self.get_dependencies(project=pm)
- for key, dependency_project in dependency_projects.items():
- package = key.split("=")[0]
- base = dependency_project.path if hasattr(dependency_project, "path") else package
- manifest = dependency_project.manifest
- if manifest.sources is None:
- continue
-
- for source_id in manifest.sources.keys():
- import_match = f"{base}/{source_id}"
- dependencies[import_match] = manifest
-
- interfaces_source = ""
- og_source = (pm.path / path).read_text(encoding="utf8")
-
- # Get info about imports and source meta
- aliases = extract_import_aliases(og_source)
- pragma, source_without_meta = extract_meta(og_source)
- version_specifier = get_version_pragma_spec(pragma) if pragma else None
- stdlib_imports, _, source_without_imports = extract_imports(source_without_meta)
- flattened_modules = ""
- modules_prefixes: set[str] = set()
-
- for import_path in sorted(imports):
- import_file = None
- for base in (pm.path, pm.interfaces_folder):
- for opt in {import_path, import_path.replace(f"interfaces{os.path.sep}", "")}:
- try_import_file = base / opt
- if try_import_file.is_file():
- import_file = try_import_file
- break
-
- if import_file is None:
- import_file = pm.path / import_path
-
- # Vyper imported interface names come from their file names
- file_name = import_file.stem
- # If we have a known alias, ("import X as Y"), use the alias as interface name
- iface_name = aliases[file_name] if file_name in aliases else file_name
-
- def _match_source(imp_path: str) -> Optional[PackageManifest]:
- for source_path in dependencies.keys():
- if source_path.endswith(imp_path):
- return dependencies[source_path]
-
- return None
-
- if matched_source := _match_source(import_path):
- if not matched_source.contract_types:
- continue
-
- abis = [
- el
- for k in matched_source.contract_types.keys()
- for el in matched_source.contract_types[k].abi
- ]
- interfaces_source += generate_interface(abis, iface_name)
- continue
-
- # Generate an ABI from the source code
- elif import_file.is_file():
- if (
- version_specifier
- and version_specifier.contains("0.4.0")
- and import_file.suffix != ".vyi"
- ):
- if warn_flattening_modules:
- logger.warning(
- "Flattening modules DOES NOT yield the same bytecode! "
- "This is **NOT** valid for contract-verification."
- )
- warn_flattening_modules = False
-
- modules_prefixes.add(import_file.stem)
- if import_file in handled:
- # We have already included this source somewhere.
- continue
-
- # Is a module or an interface imported from a module.
- # Copy in the source code directly.
- flattened_module = self._flatten_source(
- import_file,
- include_pragma=False,
- sources_handled=handled,
- warn_flattening_modules=warn_flattening_modules,
- )
- flattened_modules = f"{flattened_modules}\n\n{flattened_module}"
-
- else:
- # Vyper <0.4 interface from folder other than interfaces/
- # such as a .vyi file in the contracts folder.
- abis = source_to_abi(import_file.read_text(encoding="utf8"))
- interfaces_source += generate_interface(abis, iface_name)
-
- def no_nones(it: Iterable[Optional[str]]) -> Iterable[str]:
- # Type guard like generator to remove Nones and make mypy happy
- for el in it:
- if el is not None:
- yield el
-
- pragma_to_include = pragma if include_pragma else ""
-
- # Join all the OG and generated parts back together
- flattened_source = "\n\n".join(
- no_nones(
- (
- pragma_to_include,
- stdlib_imports,
- interfaces_source,
- flattened_modules,
- source_without_imports,
- )
- )
- )
-
- # Clear module-usage prefixes.
- for prefix in modules_prefixes:
- # Replace usage lines like 'zero_four_module.moduleMethod()'
- # with 'self.moduleMethod()'.
- flattened_source = flattened_source.replace(f"{prefix}.", "self.")
-
- # Remove module-level doc-strings, as it causes compilation issues
- # when used in root contracts.
- lines_no_doc: list[str] = []
- in_str_comment = False
- for line in flattened_source.splitlines():
- line_stripped = line.rstrip()
- if not in_str_comment and line_stripped.startswith('"""'):
- if line_stripped == '"""' or not line_stripped.endswith('"""'):
- in_str_comment = True
- continue
-
- elif in_str_comment:
- if line_stripped.endswith('"""'):
- in_str_comment = False
-
- continue
-
- lines_no_doc.append(line)
-
- flattened_source = "\n".join(lines_no_doc)
-
- # TODO: Replace this nonsense with a real code formatter
- def format_source(source: str) -> str:
- while "\n\n\n\n" in source:
- source = source.replace("\n\n\n\n", "\n\n\n")
- return source
-
- return format_source(flattened_source)
-
- def flatten_contract(
- self,
- path: Path,
- project: Optional[ProjectManager] = None,
- **kwargs,
- ) -> Content:
- """
- Returns the flattened contract suitable for compilation or verification as a single file
- """
- pm = project or self.local_project
- src = self._flatten_source(path, project=pm)
- return Content({i: ln for i, ln in enumerate(src.splitlines())})
-
- def get_version_map(
- self,
- contract_filepaths: Iterable[Path],
- project: Optional[ProjectManager] = None,
- ) -> dict[Version, set[Path]]:
- pm = project or self.local_project
- import_map = self.get_imports(contract_filepaths, project=pm)
- return self._get_version_map_from_import_map(contract_filepaths, import_map, project=pm)
-
- def _get_version_map_from_import_map(
- self,
- contract_filepaths: Iterable[Path],
- import_map: dict[str, list[str]],
- project: Optional[ProjectManager] = None,
- config: Optional[PluginConfig] = None,
- ):
- pm = project or self.local_project
- self.compiler_settings = {**self.compiler_settings}
- config = config or self.get_config(pm)
- version_map: dict[Version, set[Path]] = {}
- source_path_by_version_spec: dict[SpecifierSet, set[Path]] = {}
- source_paths_without_pragma = set()
-
- # Sort contract_filepaths to promote consistent, reproduce-able behavior
- for path in sorted(contract_filepaths):
- src_id = f"{get_relative_path(path.absolute(), pm.path)}"
- imports = [pm.path / imp for imp in import_map.get(src_id, [])]
-
- if config_spec := config.version:
- _safe_append(source_path_by_version_spec, config_spec, {path, *imports})
- elif pragma := get_version_pragma_spec(path):
- _safe_append(source_path_by_version_spec, pragma, {path, *imports})
- else:
- source_paths_without_pragma.add(path)
-
- # Install all requires versions *before* building map
- for pragma_spec, path_set in source_path_by_version_spec.items():
- if list(pragma_spec.filter(self.installed_versions)):
- # Already met.
- continue
-
- versions_can_install = sorted(
- list(pragma_spec.filter(self.available_versions)), reverse=True
- )
- if versions_can_install:
- did_install = False
- for version in versions_can_install:
- if version == self.package_version:
- break
- else:
- _install_vyper(version)
- did_install = True
- break
-
- if not did_install:
- versions_str = ", ".join([f"{v}" for v in versions_can_install])
- raise VyperInstallError(f"Unable to install vyper version(s) '{versions_str}'.")
- else:
- raise VyperInstallError("No available version to install.")
-
- # By this point, all the of necessary versions will be installed.
- # Thus, we will select only the best versions to use per source set.
- for pragma_spec, path_set in source_path_by_version_spec.items():
- versions = sorted(list(pragma_spec.filter(self.installed_versions)), reverse=True)
- if versions:
- _safe_append(
- version_map, versions[0], {p for p in path_set if p in contract_filepaths}
- )
-
- if not self.installed_versions:
- # If we have no installed versions by this point, we need to install one.
- # This happens when there are no pragmas in any sources and no vyper installations.
- _install_vyper(max(self.available_versions))
-
- # Handle no-pragma sources
- if source_paths_without_pragma:
- versions_given = [x for x in version_map.keys()]
- max_installed_vyper_version = None
- if versions_given:
- version_given_non_pre = [x for x in versions_given if not x.pre]
- if version_given_non_pre:
- max_installed_vyper_version = max(version_given_non_pre)
-
- if max_installed_vyper_version is None:
- max_installed_vyper_version = max(v for v in self.installed_versions if not v.pre)
-
- _safe_append(
- version_map,
- max_installed_vyper_version,
- {p for p in source_paths_without_pragma if p in contract_filepaths},
- )
-
- return version_map
-
- def get_compiler_settings(
- self,
- contract_filepaths: Iterable[Path],
- project: Optional[ProjectManager] = None,
- **kwargs,
- ) -> dict[Version, dict]:
- pm = project or self.local_project
- # NOTE: Interfaces cannot be in the outputSelection
- # (but are required in `sources` for the 0.4.0 range).
- valid_paths = [
- p
- for p in contract_filepaths
- if get_full_extension(p) == FileType.SOURCE
- and not str(p).startswith(str(pm.path / "interfaces"))
- ]
- version_map = self.get_version_map(valid_paths, project=pm)
- return self._get_compiler_settings_from_version_map(version_map, project=pm)
-
- def _get_compiler_settings_from_version_map(
- self,
- version_map: dict[Version, set[Path]],
- project: Optional[ProjectManager] = None,
- ):
- pm = project or self.local_project
-
- # When compiling projects outside the cwd, use absolute paths for ease.
- # Also, struggled to get it work any other way.
- use_absolute_path = pm.path != Path.cwd()
-
- compiler_data = self._get_compiler_arguments(version_map, project=pm)
- settings = {}
- for version, data in compiler_data.items():
- source_paths = list(version_map.get(version, []))
- if not source_paths:
- continue
-
- default_optimization: Optimization = True if version < Version("0.3.10") else "gas"
- output_selection: dict[str, set[str]] = {}
- optimizations_map = get_optimization_pragma_map(
- source_paths, pm.path, default_optimization
- )
- evm_version_map = get_evm_version_pragma_map(source_paths, pm.path)
- default_evm_version = data.get(
- "evm_version", data.get("evmVersion")
- ) or EVM_VERSION_DEFAULT.get(version.base_version)
- for source_path in source_paths:
- source_id = str(get_relative_path(source_path.absolute(), pm.path))
-
- if not (optimization := optimizations_map.get(source_id)):
- optimization = True if version < Version("0.3.10") else "gas"
-
- evm_version = evm_version_map.get(source_id, default_evm_version)
- settings_key = f"{optimization}%{evm_version}".lower()
- if settings_key not in output_selection:
- output_selection[settings_key] = {source_id}
- else:
- output_selection[settings_key].add(source_id)
-
- version_settings: dict[str, dict] = {}
- for settings_key, selection in output_selection.items():
- optimization, evm_version = settings_key.split("%")
- if optimization == "true":
- optimization = True
- elif optimization == "false":
- optimization = False
-
- if version >= Version("0.4.0"):
-
- def _to_src_id(s):
- return str(pm.path / s) if use_absolute_path else s
-
- selection_dict = {
- _to_src_id(s): ["*"]
- for s in selection
- if ((pm.path / s).is_file() if use_absolute_path else Path(s).is_file())
- and f"interfaces{os.path.sep}" not in s
- and get_full_extension(pm.path / s) != FileType.INTERFACE
- }
- else:
- selection_dict = {
- s: ["*"]
- for s in selection
- if (pm.path / s).is_file()
- if "interfaces" not in s
- }
-
- search_paths = [*getsitepackages()]
- if pm.path == Path.cwd():
- search_paths.append(".")
- else:
- search_paths.append(str(pm.path))
- # else: only seem to get absolute paths to work (for compiling deps alone).
-
- version_settings[settings_key] = {
- "optimize": optimization,
- "outputSelection": selection_dict,
- "search_paths": search_paths,
- }
- if evm_version and evm_version not in ("none", "null"):
- version_settings[settings_key]["evmVersion"] = f"{evm_version}"
-
- settings[version] = version_settings
-
- return settings
-
- def init_coverage_profile(
- self, source_coverage: ContractSourceCoverage, contract_source: ContractSource
- ):
- exclusions = self.config_manager.get_config("test").coverage.exclude
- contract_name = contract_source.contract_type.name or "__UnknownContract__"
-
- # Check if excluding this contract.
- for exclusion in exclusions:
- if fnmatch(contract_name, exclusion.contract_name) and (
- not exclusion.method_name or exclusion.method_name == "*"
- ):
- # Skip this whole source.
- return
-
- contract_coverage = source_coverage.include(contract_name)
-
- def _exclude_fn(_name: str) -> bool:
- for _exclusion in exclusions:
- if fnmatch(contract_coverage.name, _exclusion.contract_name) and fnmatch(
- _name, _exclusion.method_name
- ):
- # This function should be skipped.
- return True
-
- return False
-
- def _profile(_name: str, _full_name: str):
- # Ensure function isn't excluded.
- if _exclude_fn(_name):
- return
-
- _function_coverage = contract_coverage.include(_name, _full_name)
-
- # Only put the builtin-tags we expect users to be able to cover.
- tag = (
- str(item["dev"])
- if item.get("dev")
- and isinstance(item["dev"], str)
- and item["dev"].startswith("dev: ")
- and RuntimeErrorType.USER_ASSERT.value not in item["dev"]
- else None
- )
- _function_coverage.profile_statement(pc_int, location=location, tag=tag)
-
- # Some statements are too difficult to know right away where they belong,
- # such as statement related to kwarg-default auto-generated implicit lookups.
- # function_name -> (pc, location)
- pending_statements: dict[str, list[tuple[int, SourceLocation]]] = {}
-
- for pc, item in contract_source.pcmap.root.items():
- pc_int = int(pc)
- if pc_int < 0:
- continue
-
- location: Optional[SourceLocation]
- if item.get("location"):
- location_list = item["location"]
- if not isinstance(location_list, (list, tuple)):
- raise TypeError(f"Unexpected location type '{type(location_list)}'.")
-
- # NOTE: Only doing 0 because mypy for some reason thinks it is optional.
- location = (
- location_list[0] or 0,
- location_list[1] or 0,
- location_list[2] or 0,
- location_list[3] or 0,
- )
- else:
- location = None
-
- if location is not None and not isinstance(location, tuple):
- # Only really for mypy.
- raise TypeError(f"Received unexpected type for location '{location}'.")
-
- if not location and not item.get("dev"):
- # Not a statement we can measure.
- continue
-
- if location:
- function = contract_source.lookup_function(location)
- if not function:
- # Not sure if this happens.
- continue
-
- matching_abis = [
- a for a in contract_source.contract_type.methods if a.name == function.name
- ]
- if len(matching_abis) > 1:
- # In Vyper, if there are multiple method ABIs with the same name,
- # that is evidence of the default key-word argument generated methods.
-
- is_part_of_signature = location[0] < function.offset
- if is_part_of_signature and location[0] != location[2]:
- # This likely is not a real statement, but not really sure what this is.
- continue
-
- # In Vyper, the ABI with the most inputs should be the one without extra steps.
- longest_abi = max(matching_abis, key=lambda x: len(x.inputs))
- if is_part_of_signature and longest_abi.name in pending_statements:
- pending_statements[longest_abi.name].append((pc_int, location))
- elif is_part_of_signature:
- pending_statements[longest_abi.name] = [(pc_int, location)]
- else:
- # Put actual source statements under the ABI with all parameters as inputs.
- _profile(longest_abi.name, longest_abi.selector)
-
- elif len(matching_abis) == 1:
- _profile(function.name, matching_abis[0].selector)
-
- elif len(matching_abis) == 0:
- # Is likely an internal method.
- _profile(function.name, function.full_name or function.name)
-
- else:
- _profile("__builtin__", "__builtin__")
-
- if pending_statements:
- # Handle auto-generated kwarg-default statements here.
- # Sort each statement into buckets mapping to the method it belongs in.
- for fn_name, pending_ls in pending_statements.items():
- matching_abis = [
- m for m in contract_source.contract_type.methods if m.name == fn_name
- ]
- longest_abi = max(matching_abis, key=lambda x: len(x.inputs))
- autogenerated_abis = [
- abi for abi in matching_abis if abi.selector != longest_abi.selector
- ]
- # Sort the autogenerated ABIs so we can loop through them in the correct order.
- autogenerated_abis.sort(key=lambda a: len(a.inputs))
- buckets: dict[str, list[tuple[int, SourceLocation]]] = {
- a.selector: [] for a in autogenerated_abis
- }
- selector_index = 0
- selector = autogenerated_abis[0].selector
- # Must loop through PCs from smallest to greatest for this to work.
- pending_ls.sort()
- jump_threshold = 10
- for _pc, loc in pending_ls:
- if selector_index < len(autogenerated_abis):
- selector = autogenerated_abis[selector_index].selector
-
- if not buckets[selector]:
- # No need for bounds checking when the bucket is empty.
- buckets[selector].append((_pc, loc))
- continue
-
- last_pc = buckets[selector][-1][0]
-
- # Check if jumped.
- distance = _pc - last_pc
- if distance > jump_threshold:
- selector_index += 1
- if selector_index >= len(autogenerated_abis):
- break
-
- selector = autogenerated_abis[selector_index].selector
- buckets[selector].append((_pc, loc))
- else:
- buckets[selector].append((_pc, loc))
-
- for full_name, statements in buckets.items():
- for _pc, location in statements:
- if _exclude_fn(fn_name):
- continue
-
- function_coverage = contract_coverage.include(fn_name, full_name)
- function_coverage.profile_statement(_pc, location=location)
-
- # After handling all methods with locations, let's also add the auto-getters,
- # which are not present in the source map.
- for method in contract_source.contract_type.view_methods:
- if method.selector not in [fn.full_name for fn in contract_coverage.functions]:
- if _exclude_fn(method.name):
- return
-
- # Auto-getter found. Profile function without statements.
- contract_coverage.include(method.name, method.selector)
-
- def _get_compiler_arguments(
- self,
- version_map: dict,
- project: Optional[ProjectManager] = None,
- config: Optional[PluginConfig] = None,
- ) -> dict[Version, dict]:
- pm = project or self.local_project
- config = config or self.get_config(pm)
- evm_version = config.evm_version
- arguments_map = {}
- for vyper_version, source_paths in version_map.items():
- bin_arg = self._get_vyper_bin(vyper_version)
- arguments_map[vyper_version] = {
- "base_path": f"{pm.path}",
- "evm_version": evm_version,
- "vyper_version": str(vyper_version),
- "vyper_binary": bin_arg,
- }
-
- return arguments_map
-
- def _get_vyper_bin(self, vyper_version: Version):
- return shutil.which("vyper") if vyper_version is self.package_version else None
-
- def enrich_error(self, err: ContractLogicError) -> ContractLogicError:
- try:
- dev_message = err.dev_message
- except ValueError:
- # Not available.
- return err
-
- if not dev_message:
- return err
-
- err_str = dev_message.replace("dev: ", "")
- error_type = None
- if err_str in [m.value for m in RuntimeErrorType]:
- # Is a builtin compiler error.
- error_type = RuntimeErrorType(err_str)
-
- elif "bounds check" in err_str:
- error_type = RuntimeErrorType.INTEGER_BOUNDS_CHECK
-
- else:
- # Check names
- for name, _type in [(m.name, m) for m in RuntimeErrorType]:
- if err_str == name:
- error_type = _type
- break
-
- if not error_type:
- # Not a builtin compiler error; cannot enrich.
- return err
-
- runtime_error_cls = RUNTIME_ERROR_MAP[error_type]
- tx_kwargs: dict = {
- "contract_address": err.contract_address,
- "source_traceback": err.source_traceback,
- "trace": err.trace,
- "txn": err.txn,
- }
- return (
- runtime_error_cls(err_str.split(" ")[0], **tx_kwargs)
- if runtime_error_cls == IntegerBoundsCheck
- else runtime_error_cls(**tx_kwargs)
- )
-
- def trace_source(
- self, contract_source: ContractSource, trace: TraceAPI, calldata: HexBytes
- ) -> SourceTraceback:
- frames = trace.get_raw_frames()
- return self._get_traceback(contract_source, frames, calldata)
-
- def _get_traceback(
- self,
- contract_src: ContractSource,
- frames: Iterator[dict],
- calldata: HexBytes,
- previous_depth: Optional[int] = None,
- ) -> SourceTraceback:
- traceback = SourceTraceback.model_validate([])
- method_id = HexBytes(calldata[:4])
- completed = False
- pcmap = PCMap.model_validate({})
-
- for frame in frames:
- if frame["op"] in [c.value for c in CALL_OPCODES]:
- start_depth = frame["depth"]
- called_contract, sub_calldata = self._create_contract_from_call(frame)
- if called_contract:
- ext = get_full_extension(Path(called_contract.source_id))
- if ext in [x for x in FileType]:
- # Called another Vyper contract.
- sub_trace = self._get_traceback(
- called_contract, frames, sub_calldata, previous_depth=frame["depth"]
- )
- traceback.extend(sub_trace)
-
- else:
- # Not a Vyper contract!
- compiler = self.compiler_manager.registered_compilers[ext]
- try:
- sub_trace = compiler.trace_source(
- called_contract.contract_type, frames, sub_calldata
- )
- traceback.extend(sub_trace)
- except NotImplementedError:
- # Compiler not supported. Fast forward out of this call.
- for fr in frames:
- if fr["depth"] <= start_depth:
- break
-
- continue
-
- else:
- # Contract not found. Fast forward out of this call.
- for fr in frames:
- if fr["depth"] <= start_depth:
- break
-
- continue
-
- elif frame["op"] in _RETURN_OPCODES:
- # For the base CALL, don't mark as completed until trace is gone.
- # This helps in cases where we failed to detect a subcall properly.
- completed = previous_depth is not None
-
- pcs_to_try_adding = set()
- if "PUSH" in frame["op"] and frame["pc"] in contract_src.pcmap:
- # Check if next op is SSTORE to properly use AST from push op.
- next_frame: Optional[dict] = frame
- loc = contract_src.pcmap[frame["pc"]]
- pcs_to_try_adding.add(frame["pc"])
-
- while next_frame and "PUSH" in next_frame["op"]:
- next_frame = next(frames, None)
- if next_frame and "PUSH" in next_frame["op"]:
- pcs_to_try_adding.add(next_frame["pc"])
-
- is_non_payable_hit = False
- if next_frame and next_frame["op"] == "SSTORE":
- push_location = tuple(loc["location"]) # type: ignore
- pcmap = PCMap.model_validate({next_frame["pc"]: {"location": push_location}})
-
- elif next_frame and next_frame["op"] in _RETURN_OPCODES:
- completed = True
-
- else:
- pcmap = contract_src.pcmap
- dev_val = str((loc.get("dev") or "")).replace("dev: ", "")
- is_non_payable_hit = dev_val == RuntimeErrorType.NONPAYABLE_CHECK.value
-
- if not is_non_payable_hit and next_frame:
- frame = next_frame
-
- else:
- pcmap = contract_src.pcmap
-
- pcs_to_try_adding.add(frame["pc"])
- pcs_to_try_adding = {pc for pc in pcs_to_try_adding if pc in pcmap}
- if not pcs_to_try_adding:
- if (
- frame["op"] == "REVERT"
- and frame["pc"] + 1 in pcmap
- and RuntimeErrorType.USER_ASSERT.value
- in str(pcmap[frame["pc"] + 1].get("dev", ""))
- ):
- # Not sure why this happens. Maybe an off-by-1 bug in Vyper.
- pcs_to_try_adding.add(frame["pc"] + 1)
-
- pc_groups: list[list] = []
- for pc in pcs_to_try_adding:
- location = (
- cast(tuple[int, int, int, int], tuple(pcmap[pc].get("location") or [])) or None
- )
- dev_item = pcmap[pc].get("dev", "")
- dev = str(dev_item).replace("dev: ", "")
-
- done = False
- for group in pc_groups:
- if group[0] != location:
- continue
-
- group[1].add(pc)
- dev = group[2] = dev or group[2]
- done = True
- break
-
- if not done:
- # New group.
- pc_groups.append([location, {pc}, dev])
-
- dev_messages = contract_src.contract_type.dev_messages or {}
- for location, pcs, dev in pc_groups:
- if dev in [m.value for m in RuntimeErrorType if m != RuntimeErrorType.USER_ASSERT]:
- error_type = RuntimeErrorType(dev)
- if (
- error_type != RuntimeErrorType.NONPAYABLE_CHECK
- and traceback.last is not None
- ):
- # If the error type is not the non-payable check,
- # it happened in the last method.
- name = traceback.last.closure.name
- full_name = traceback.last.closure.full_name
-
- elif method_id in contract_src.contract_type.methods:
- # For non-payable checks, they should hit here.
- method_checked = contract_src.contract_type.methods[method_id]
- name = method_checked.name
- full_name = method_checked.selector
-
- else:
- # Not sure if possible to get here.
- name = error_type.name.lower()
- full_name = name
-
- if (
- dev == RuntimeErrorType.INVALID_CALLDATA_OR_VALUE.value
- and len(traceback.source_statements) > 0
- ):
- # NOTE: Skip adding invalid calldata / value checks when
- # we have already hit source statements. The reason for this
- # is because of misleading Vyper optimizations sharing revert PCs.
- continue
-
- # Empty source (is builtin)
- traceback.add_builtin_jump(
- name,
- f"dev: {dev}",
- full_name=full_name,
- pcs=pcs,
- source_path=contract_src.source_path,
- )
- continue
-
- elif not location:
- # Unknown.
- continue
-
- if not (function := contract_src.lookup_function(location, method_id=method_id)):
- continue
-
- if (
- not traceback.last
- or traceback.last.closure.full_name != function.full_name
- or not isinstance(traceback.last.closure, Function)
- ):
- depth = (
- frame["depth"] + 1
- if traceback.last and traceback.last.depth == frame["depth"]
- else frame["depth"]
- )
-
- traceback.add_jump(
- location,
- function,
- depth,
- pcs=pcs,
- source_path=contract_src.source_path,
- )
- else:
- traceback.extend_last(location, pcs=pcs)
-
- if len(traceback.source_statements) > 0:
- last_statement = traceback.source_statements[-1]
- if dev.endswith(RuntimeErrorType.USER_ASSERT.value) or any(
- DEV_MSG_PATTERN.match(str(s)) for s in str(last_statement).splitlines()
- ):
- # Add dev message to user assert
- for lineno in range(
- last_statement.end_lineno, last_statement.begin_lineno - 1, -1
- ):
- if lineno in dev_messages:
- last_statement.type = dev_messages[lineno]
-
- if completed:
- break
-
- return traceback
-
- def _create_contract_from_call(self, frame: dict) -> tuple[Optional[ContractSource], HexBytes]:
- evm_frame = TraceFrame(**frame)
- data = create_call_node_data(evm_frame)
- calldata = data.get("calldata", HexBytes(""))
- if not (address := (data.get("address", evm_frame.contract_address) or None)):
- return None, calldata
-
- try:
- address = self.provider.network.ecosystem.decode_address(address)
- except Exception:
- return None, calldata
-
- if address not in self.chain_manager.contracts:
- return None, calldata
-
- called_contract = self.chain_manager.contracts[address]
- return self.local_project._create_contract_source(called_contract), calldata
-
-
-def _safe_append(data: dict, version: Union[Version, SpecifierSet], paths: Union[Path, set]):
- if isinstance(paths, Path):
- paths = {paths}
- if version in data:
- data[version] = data[version].union(paths)
- else:
- data[version] = paths
-
-
-def _is_revert_jump(op: str, value: Optional[int], revert_pc: int) -> bool:
- return op == "JUMPI" and value is not None and value == revert_pc
-
-
-def _has_empty_revert(opcodes: list[str]) -> bool:
- return (len(opcodes) > 12 and opcodes[-13] == "JUMPDEST" and opcodes[-9] == "REVERT") or (
- len(opcodes) > 4 and opcodes[-5] == "JUMPDEST" and opcodes[-1] == "REVERT"
- )
-
-
-def _get_pcmap(bytecode: dict) -> PCMap:
- # Find the non payable value check.
- src_info = bytecode["sourceMapFull"] if "sourceMapFull" in bytecode else bytecode["sourceMap"]
- pc_data = {pc: {"location": ln} for pc, ln in src_info["pc_pos_map"].items()}
- if not pc_data:
- return PCMap.model_validate({})
-
- # Apply other errors.
- errors = src_info["error_map"]
- for err_pc, error_type in errors.items():
- use_loc = True
- if "safemul" in error_type or "safeadd" in error_type or "bounds check" in error_type:
- # NOTE: Bound check may also occur for underflow.
- error_str = RuntimeErrorType.INTEGER_OVERFLOW.value
- elif "safesub" in error_type or "clamp" in error_type:
- error_str = RuntimeErrorType.INTEGER_UNDERFLOW.value
- elif "safediv" in error_type or "clamp gt 0" in error_type:
- error_str = RuntimeErrorType.DIVISION_BY_ZERO.value
- elif "safemod" in error_type:
- error_str = RuntimeErrorType.MODULO_BY_ZERO.value
- elif "bounds check" in error_type:
- error_str = RuntimeErrorType.INDEX_OUT_OF_RANGE.value
- elif "user assert" in error_type.lower() or "user revert" in error_type.lower():
- # Mark user-asserts so the Ape can correctly find dev messages.
- error_str = RuntimeErrorType.USER_ASSERT.value
- elif "fallback function" in error_type:
- error_str = RuntimeErrorType.FALLBACK_NOT_DEFINED.value
- use_loc = False
- elif "bad calldatasize or callvalue" in error_type:
- # Only on >=0.3.10.
- # NOTE: We are no longer able to get Nonpayable checks errors since they
- # are now combined.
- error_str = RuntimeErrorType.INVALID_CALLDATA_OR_VALUE.value
- elif "nonpayable check" in error_type:
- error_str = RuntimeErrorType.NONPAYABLE_CHECK.value
- else:
- error_str = ""
- error_type_name = error_type.upper().replace(" ", "_")
- for _type in RuntimeErrorType:
- if _type.name == error_type_name:
- error_str = _type.value
- break
-
- error_str = error_str or error_type_name
- use_loc = False
-
- location = None
- if use_loc:
- # Add surrounding locations
- for pc in range(int(err_pc), -1, -1):
- if (
- (data := pc_data.get(f"{pc}"))
- and "dev" not in data
- and (location := data.get("location"))
- ):
- break
-
- if err_pc in pc_data:
- pc_data[err_pc]["dev"] = f"dev: {error_str}"
- else:
- pc_data[err_pc] = {"dev": f"dev: {error_str}", "location": location}
-
- return PCMap.model_validate(pc_data)
-
-
-def _get_legacy_pcmap(ast: ASTNode, src_map: list[SourceMapItem], opcodes: list[str]):
- """
- For Vyper versions <= 0.3.7, allows us to still get a PCMap.
- """
-
- pc = 0
- pc_map_list: list[tuple[int, dict[str, Optional[Any]]]] = []
- last_value = None
- revert_pc = -1
- if _has_empty_revert(opcodes):
- revert_pc = _get_revert_pc(opcodes)
-
- processed_opcodes = []
-
- # There is only 1 non-payable check and it happens early in the bytecode.
- non_payable_check_found = False
-
- # There is at most 1 fallback error PC
- fallback_found = False
-
- while src_map and opcodes:
- src = src_map.pop(0)
- op = opcodes.pop(0)
- processed_opcodes.append(op)
- pc += 1
-
- # If immutable member load, ignore increasing pc by push size.
- if _is_immutable_member_load(opcodes):
- last_value = int(opcodes.pop(0), 16)
- # Add the push number, e.g. PUSH1 adds `1`.
- num_pushed = int(op[4:])
- pc += num_pushed
-
- # Add content PC item.
- # Also check for compiler runtime error handling.
- # Runtime error locations are marked in the PCMap for further analysis.
- if src.start is not None and src.length is not None:
- stmt = ast.get_node(src)
- if stmt:
- # Add located item.
- line_nos = list(stmt.line_numbers)
- item: dict = {"location": line_nos}
- is_revert_jump = _is_revert_jump(op, last_value, revert_pc)
- if op == "REVERT" or is_revert_jump:
- dev = None
- if stmt.ast_type in ("AugAssign", "BinOp"):
- # SafeMath
- for node in stmt.children:
- dev = RuntimeErrorType.from_operator(node.ast_type)
- if dev:
- break
-
- elif stmt.ast_type == "Subscript":
- dev = RuntimeErrorType.INDEX_OUT_OF_RANGE
-
- else:
- # This is needed for finding the corresponding dev message.
- dev = RuntimeErrorType.USER_ASSERT
-
- if dev:
- val = f"dev: {dev.value}"
- if is_revert_jump and len(pc_map_list) >= 1:
- pc_map_list[-1][1]["dev"] = val
- else:
- item["dev"] = val
-
- pc_map_list.append((pc, item))
-
- elif not fallback_found and _is_fallback_check(opcodes, op):
- # You can tell this is the Fallback jump because it is checking for the method ID.
- item = {"dev": f"dev: {RuntimeErrorType.FALLBACK_NOT_DEFINED.value}", "location": None}
- # PC is actually the one before but it easier to detect here.
- pc_map_list.append((pc - 1, item))
- fallback_found = True
-
- elif not non_payable_check_found and _is_non_payable_check(opcodes, op, revert_pc):
- item = {"dev": _NON_PAYABLE_STR, "location": None}
- pc_map_list.append((pc, item))
- non_payable_check_found = True
-
- elif op == "REVERT":
- # Source-less revert found, use latest item with a source.
- for item in [x[1] for x in pc_map_list[::-1] if x[1]["location"]]:
- if not item.get("dev"):
- item["dev"] = f"dev: {RuntimeErrorType.USER_ASSERT.value}"
- break
-
- pcmap_data = dict(pc_map_list)
- return PCMap.model_validate(pcmap_data)
-
-
-def _find_non_payable_check(src_map: list[SourceMapItem], opcodes: list[str]) -> Optional[int]:
- pc = 0
- revert_pc = -1
- if _has_empty_revert(opcodes):
- revert_pc = _get_revert_pc(opcodes)
-
- while src_map and opcodes:
- op = opcodes.pop(0)
- pc += 1
-
- # If immutable member load, ignore increasing pc by push size.
- if _is_immutable_member_load(opcodes):
- # Add the push number, e.g. PUSH1 adds `1`.
- pc += int(op[4:])
-
- if _is_non_payable_check(opcodes, op, revert_pc):
- return pc
-
- return None
-
-
-def _is_non_payable_check(opcodes: list[str], op: str, revert_pc: int) -> bool:
- return (
- len(opcodes) >= 3
- and op == "CALLVALUE"
- and "PUSH" in opcodes[0]
- and is_0x_prefixed(opcodes[1])
- and _is_revert_jump(opcodes[2], int(opcodes[1], 16), revert_pc)
- )
-
-
-def _get_revert_pc(opcodes: list[str]) -> int:
- """
- Starting in vyper 0.2.14, reverts without a reason string are optimized
- with a jump to the "end" of the bytecode.
- """
- return (
- len(opcodes)
- + sum(int(i[4:]) - 1 for i in opcodes if i.startswith("PUSH"))
- - _EMPTY_REVERT_OFFSET
- )
-
-
-def _is_immutable_member_load(opcodes: list[str]):
- is_code_copy = len(opcodes) > 5 and opcodes[5] == "CODECOPY"
- return not is_code_copy and opcodes and is_0x_prefixed(opcodes[0])
-
-
-def _extend_return(function: Function, traceback: SourceTraceback, last_pc: int, source_path: Path):
- return_ast_result = [x for x in function.ast.children if x.ast_type == "Return"]
- if not return_ast_result:
- return
-
- # Ensure return statement added.
- # Sometimes it is missing from the PCMap otherwise.
- return_ast = return_ast_result[-1]
- location = return_ast.line_numbers
-
- last_lineno = max(0, location[2] - 1)
- for frameset in traceback.root[::-1]:
- if frameset.end_lineno is not None:
- last_lineno = frameset.end_lineno
- break
-
- start = last_lineno + 1
- last_pcs = {last_pc + 1} if last_pc else set()
- if traceback.last:
- traceback.last.extend(location, pcs=last_pcs, ws_start=start)
- else:
- # Not sure if it ever gets here, but type-checks say it could.
- traceback.add_jump(location, function, 1, last_pcs, source_path=source_path)
-
-
-def _is_fallback_check(opcodes: list[str], op: str) -> bool:
- return (
- "JUMP" in op
- and len(opcodes) >= 7
- and opcodes[0] == "JUMPDEST"
- and opcodes[6] == "SHR"
- and opcodes[5] == "0xE0"
- )
diff --git a/ape_vyper/exceptions.py b/ape_vyper/exceptions.py
deleted file mode 100644
index b45fc9d7..00000000
--- a/ape_vyper/exceptions.py
+++ /dev/null
@@ -1,177 +0,0 @@
-from enum import Enum
-from typing import Optional, Union
-
-from ape.exceptions import CompilerError, ContractLogicError
-from ape.utils import USER_ASSERT_TAG
-from vvm.exceptions import VyperError # type: ignore
-
-
-class VyperCompilerPluginError(CompilerError):
- """
- An error raised in the Vyper compiler.
- """
-
-
-class VyperInstallError(VyperCompilerPluginError):
- """
- An error raised failing to install Vyper.
- """
-
-
-class VyperCompileError(VyperCompilerPluginError):
- """
- A compiler-specific error in Vyper.
- """
-
- def __init__(self, err: Union[VyperError, str]):
- if isinstance(err, VyperError):
- self.base_err = err
- message = "\n\n".join(
- f"{e['sourceLocation']['file']}\n{e['type']}:"
- f"{e.get('formattedMessage', e['message'])}"
- for e in (err.error_dict or {})
- )
- # Try to find any indication of error.
- message = message or getattr(err, "message", "")
-
- # If is only the default, check stderr.
- if message == "An error occurred during execution" and getattr(err, "stderr_data", ""):
- message = err.stderr_data
-
- else:
- self.base_err = None
- message = str(err)
-
- super().__init__(message)
-
-
-class RuntimeErrorType(Enum):
- NONPAYABLE_CHECK = "Cannot send ether to non-payable function"
- INVALID_CALLDATA_OR_VALUE = "Invalid calldata or value"
- INDEX_OUT_OF_RANGE = "Index out of range"
- INTEGER_OVERFLOW = "Integer overflow"
- INTEGER_UNDERFLOW = "Integer underflow"
- INTEGER_BOUNDS_CHECK = "Integer bounds check"
- DIVISION_BY_ZERO = "Division by zero"
- MODULO_BY_ZERO = "Modulo by zero"
- FALLBACK_NOT_DEFINED = "Fallback not defined"
- USER_ASSERT = USER_ASSERT_TAG
-
- @classmethod
- def from_operator(cls, operator: str) -> Optional["RuntimeErrorType"]:
- if operator == "Add":
- return cls.INTEGER_OVERFLOW
- elif operator == "Sub":
- return cls.INTEGER_UNDERFLOW
- elif operator == "Div":
- return cls.DIVISION_BY_ZERO
- elif operator == "Mod":
- return cls.MODULO_BY_ZERO
-
- return None
-
-
-class VyperRuntimeError(ContractLogicError):
- """
- An error raised when running EVM code, such as a index or math error.
- It is a type of ``ContractLogicError`` where the code came from the
- compiler and not directly from the source.
- """
-
- def __init__(self, error_type: Union[RuntimeErrorType, str], **kwargs):
- super().__init__(error_type if isinstance(error_type, str) else error_type.value, **kwargs)
-
-
-class NonPayableError(VyperRuntimeError):
- """
- Raised when sending ether to a non-payable function.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.NONPAYABLE_CHECK, **kwargs)
-
-
-class InvalidCalldataOrValueError(VyperRuntimeError):
- """
- Raises on Vyper versions >= 0.3.10 in place of NonPayableError.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.INVALID_CALLDATA_OR_VALUE, **kwargs)
-
-
-class IndexOutOfRangeError(VyperRuntimeError, IndexError):
- """
- Raised when accessing an array using an out-of-range index.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.INDEX_OUT_OF_RANGE, **kwargs)
-
-
-class IntegerOverflowError(VyperRuntimeError):
- """
- Raised when addition results in an integer exceeding its max size.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.INTEGER_OVERFLOW, **kwargs)
-
-
-class IntegerUnderflowError(VyperRuntimeError):
- """
- Raised when addition results in an integer exceeding its max size.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.INTEGER_UNDERFLOW, **kwargs)
-
-
-class IntegerBoundsCheck(VyperRuntimeError):
- """
- Raised when receiving any integer bounds check failure.
- """
-
- def __init__(self, _type: str, **kwargs):
- super().__init__(f"{_type} {RuntimeErrorType.INTEGER_OVERFLOW.value}", **kwargs)
-
-
-class DivisionByZeroError(VyperRuntimeError, ZeroDivisionError):
- """
- Raised when dividing by zero.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.DIVISION_BY_ZERO, **kwargs)
-
-
-class ModuloByZeroError(VyperRuntimeError, ZeroDivisionError):
- """
- Raised when modding by zero.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.MODULO_BY_ZERO, **kwargs)
-
-
-class FallbackNotDefinedError(VyperRuntimeError):
- """
- Raised when calling a contract directly (with missing method bytes) that has no fallback
- method defined in its ABI.
- """
-
- def __init__(self, **kwargs):
- super().__init__(RuntimeErrorType.FALLBACK_NOT_DEFINED, **kwargs)
-
-
-RUNTIME_ERROR_MAP: dict[RuntimeErrorType, type[ContractLogicError]] = {
- RuntimeErrorType.NONPAYABLE_CHECK: NonPayableError,
- RuntimeErrorType.INVALID_CALLDATA_OR_VALUE: InvalidCalldataOrValueError,
- RuntimeErrorType.INDEX_OUT_OF_RANGE: IndexOutOfRangeError,
- RuntimeErrorType.INTEGER_OVERFLOW: IntegerOverflowError,
- RuntimeErrorType.INTEGER_UNDERFLOW: IntegerUnderflowError,
- RuntimeErrorType.INTEGER_BOUNDS_CHECK: IntegerBoundsCheck,
- RuntimeErrorType.DIVISION_BY_ZERO: DivisionByZeroError,
- RuntimeErrorType.MODULO_BY_ZERO: ModuloByZeroError,
- RuntimeErrorType.FALLBACK_NOT_DEFINED: FallbackNotDefinedError,
-}
diff --git a/ape_vyper/interface.py b/ape_vyper/interface.py
deleted file mode 100644
index d59b372a..00000000
--- a/ape_vyper/interface.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""
-Tools for working with ABI specs and Vyper interface source code
-"""
-
-from typing import Any, Optional, Union
-
-from ethpm_types import ABI, MethodABI
-from ethpm_types.abi import ABIType
-
-INDENT_SPACES = 4
-INDENT = " " * INDENT_SPACES
-
-
-def indent_line(line: str, level=1) -> str:
- """Indent a source line of code"""
- return f"{INDENT * level}{line}"
-
-
-def generate_inputs(inputs: list[ABIType]) -> str:
- """Generate the source code input args from ABI inputs"""
- return ", ".join(f"{i.name}: {i.type}" for i in inputs)
-
-
-def generate_method(abi: MethodABI) -> str:
- """Generate Vyper interface method definition"""
- inputs = generate_inputs(abi.inputs)
- return_maybe = f" -> {abi.outputs[0].type}" if abi.outputs else ""
- return f"def {abi.name}({inputs}){return_maybe}: {abi.stateMutability}\n"
-
-
-def abi_to_type(iface: dict[str, Any]) -> Optional[ABI]:
- """Convert a dict JSON-like interface to an ethpm-types ABI type"""
- if iface["type"] == "function":
- return MethodABI.model_validate(iface)
- return None
-
-
-def generate_interface(abi: Union[list[dict[str, Any]], list[ABI]], iface_name: str) -> str:
- """
- Generate a Vyper interface source code from an ABI spec
-
- Args:
- abi (List[Union[Dict[str, Any], ABI]]): An ABI spec for a contract
- iface_name (str): The name of the interface
-
- Returns:
- ``str`` Vyper source code for the interface
- """
- source = f"interface {iface_name}:\n"
-
- for iface in abi:
- if isinstance(iface, dict):
- _iface = abi_to_type(iface)
-
- if _iface is None:
- continue
-
- # Re-assignment after None check because mypy
- iface = _iface
-
- if isinstance(iface, MethodABI):
- source += indent_line(generate_method(iface))
-
- return f"{source}\n"
-
-
-def extract_meta(source_code: str) -> tuple[Optional[str], str]:
- """Extract version pragma, and return cleaned source"""
- version_pragma: Optional[str] = None
- cleaned_source_lines: list[str] = []
-
- """
- Pragma format changed a bit.
-
- >= 3.10: #pragma version ^0.3.0
- < 3.10: # @version ^0.3.0
-
- Both are valid until 0.4 where the latter may be deprecated
- """
- for line in source_code.splitlines():
- if line.startswith("#") and (
- ("pragma version" in line or "@version" in line) and version_pragma is None
- ):
- version_pragma = line
- else:
- cleaned_source_lines.append(line)
-
- return (version_pragma, "\n".join(cleaned_source_lines))
-
-
-def extract_imports(source: str) -> tuple[str, str, str]:
- """
- Extract import lines from the source, return them and the source without imports
-
- Returns:
- Tuple[str, str, str]: (stdlib_import_lines, interface_import_lines, cleaned_source)
- """
- interface_import_lines = []
- stdlib_import_lines = []
- cleaned_source_lines = []
-
- for line in source.splitlines():
- if line.startswith("import ") or (line.startswith("from ") and " import " in line):
- if "vyper.interfaces" in line:
- stdlib_import_lines.append(line)
- else:
- interface_import_lines.append(line)
- else:
- cleaned_source_lines.append(line)
-
- return (
- "\n".join(stdlib_import_lines),
- "\n".join(interface_import_lines),
- "\n".join(cleaned_source_lines),
- )
-
-
-def extract_import_aliases(source: str) -> dict[str, str]:
- """
- Extract import aliases from import lines
-
- Returns:
- Dict[str, str]: {import: alias}
- """
- aliases = {}
- for line in source.splitlines():
- if (
- line.startswith("import ") or (line.startswith("from ") and " import " in line)
- ) and " as " in line:
- subject_parts = line.split("import ")[1]
- alias_parts = subject_parts.split(" as ")
- iface_path_name = alias_parts[0].split(".")[-1] # Remove path parts from import
- aliases[iface_path_name] = alias_parts[1]
- return aliases
diff --git a/index.html b/index.html
deleted file mode 100644
index 80ffdd14..00000000
--- a/index.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
Redirecting...
-
diff --git a/latest/.buildinfo b/latest/.buildinfo
deleted file mode 100644
index 38ad2dda..00000000
--- a/latest/.buildinfo
+++ /dev/null
@@ -1,4 +0,0 @@
-# Sphinx build info version 1
-# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 8388cda1962348bc92e7707e3b90bb3a
-tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/latest/.doctrees/environment.pickle b/latest/.doctrees/environment.pickle
deleted file mode 100644
index 5827cab4..00000000
Binary files a/latest/.doctrees/environment.pickle and /dev/null differ
diff --git a/latest/.doctrees/index.doctree b/latest/.doctrees/index.doctree
deleted file mode 100644
index 0dff73a8..00000000
Binary files a/latest/.doctrees/index.doctree and /dev/null differ
diff --git a/latest/.doctrees/methoddocs/compiler.doctree b/latest/.doctrees/methoddocs/compiler.doctree
deleted file mode 100644
index d7f29dc0..00000000
Binary files a/latest/.doctrees/methoddocs/compiler.doctree and /dev/null differ
diff --git a/latest/.doctrees/methoddocs/exceptions.doctree b/latest/.doctrees/methoddocs/exceptions.doctree
deleted file mode 100644
index a9aaa045..00000000
Binary files a/latest/.doctrees/methoddocs/exceptions.doctree and /dev/null differ
diff --git a/latest/.doctrees/methoddocs/interface.doctree b/latest/.doctrees/methoddocs/interface.doctree
deleted file mode 100644
index 266799ce..00000000
Binary files a/latest/.doctrees/methoddocs/interface.doctree and /dev/null differ
diff --git a/latest/.doctrees/userguides/quickstart.doctree b/latest/.doctrees/userguides/quickstart.doctree
deleted file mode 100644
index 1fc5db9e..00000000
Binary files a/latest/.doctrees/userguides/quickstart.doctree and /dev/null differ
diff --git a/latest/_sources/index.md.txt b/latest/_sources/index.md.txt
deleted file mode 100644
index 594b37fa..00000000
--- a/latest/_sources/index.md.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-# Vyper Docs
-
-```{eval-rst}
-.. toctree::
- :caption: User Guides
- :maxdepth: 1
-
- userguides/quickstart
-```
-
-```{eval-rst}
-.. toctree::
- :caption: Python Reference
- :maxdepth: 1
-
- methoddocs/compiler.md
- methoddocs/exceptions.md
- methoddocs/interface.md
-```
diff --git a/latest/_sources/methoddocs/compiler.md.txt b/latest/_sources/methoddocs/compiler.md.txt
deleted file mode 100644
index aed23796..00000000
--- a/latest/_sources/methoddocs/compiler.md.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# Compiler
-
-```{eval-rst}
-.. automodule:: ape_vyper.compiler
- :members:
-```
diff --git a/latest/_sources/methoddocs/exceptions.md.txt b/latest/_sources/methoddocs/exceptions.md.txt
deleted file mode 100644
index 5bc2108b..00000000
--- a/latest/_sources/methoddocs/exceptions.md.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# Exceptions
-
-```{eval-rst}
-.. automodule:: ape_vyper.exceptions
- :members:
-```
diff --git a/latest/_sources/methoddocs/interface.md.txt b/latest/_sources/methoddocs/interface.md.txt
deleted file mode 100644
index 49d18540..00000000
--- a/latest/_sources/methoddocs/interface.md.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# Interface
-
-```{eval-rst}
-.. automodule:: ape_vyper.interface
- :members:
-```
diff --git a/latest/_sources/userguides/quickstart.md.txt b/latest/_sources/userguides/quickstart.md.txt
deleted file mode 100644
index c7719d82..00000000
--- a/latest/_sources/userguides/quickstart.md.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-```{include} ../../README.md
-```
diff --git a/latest/_static/_sphinx_javascript_frameworks_compat.js b/latest/_static/_sphinx_javascript_frameworks_compat.js
deleted file mode 100644
index 81415803..00000000
--- a/latest/_static/_sphinx_javascript_frameworks_compat.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Compatability shim for jQuery and underscores.js.
- *
- * Copyright Sphinx contributors
- * Released under the two clause BSD licence
- */
-
-/**
- * small helper function to urldecode strings
- *
- * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
- */
-jQuery.urldecode = function(x) {
- if (!x) {
- return x
- }
- return decodeURIComponent(x.replace(/\+/g, ' '));
-};
-
-/**
- * small helper function to urlencode strings
- */
-jQuery.urlencode = encodeURIComponent;
-
-/**
- * This function returns the parsed url parameters of the
- * current request. Multiple values per key are supported,
- * it will always return arrays of strings for the value parts.
- */
-jQuery.getQueryParameters = function(s) {
- if (typeof s === 'undefined')
- s = document.location.search;
- var parts = s.substr(s.indexOf('?') + 1).split('&');
- var result = {};
- for (var i = 0; i < parts.length; i++) {
- var tmp = parts[i].split('=', 2);
- var key = jQuery.urldecode(tmp[0]);
- var value = jQuery.urldecode(tmp[1]);
- if (key in result)
- result[key].push(value);
- else
- result[key] = [value];
- }
- return result;
-};
-
-/**
- * highlight a given string on a jquery object by wrapping it in
- * span elements with the given class name.
- */
-jQuery.fn.highlightText = function(text, className) {
- function highlight(node, addItems) {
- if (node.nodeType === 3) {
- var val = node.nodeValue;
- var pos = val.toLowerCase().indexOf(text);
- if (pos >= 0 &&
- !jQuery(node.parentNode).hasClass(className) &&
- !jQuery(node.parentNode).hasClass("nohighlight")) {
- var span;
- var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
- if (isInSVG) {
- span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
- } else {
- span = document.createElement("span");
- span.className = className;
- }
- span.appendChild(document.createTextNode(val.substr(pos, text.length)));
- node.parentNode.insertBefore(span, node.parentNode.insertBefore(
- document.createTextNode(val.substr(pos + text.length)),
- node.nextSibling));
- node.nodeValue = val.substr(0, pos);
- if (isInSVG) {
- var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
- var bbox = node.parentElement.getBBox();
- rect.x.baseVal.value = bbox.x;
- rect.y.baseVal.value = bbox.y;
- rect.width.baseVal.value = bbox.width;
- rect.height.baseVal.value = bbox.height;
- rect.setAttribute('class', className);
- addItems.push({
- "parent": node.parentNode,
- "target": rect});
- }
- }
- }
- else if (!jQuery(node).is("button, select, textarea")) {
- jQuery.each(node.childNodes, function() {
- highlight(this, addItems);
- });
- }
- }
- var addItems = [];
- var result = this.each(function() {
- highlight(this, addItems);
- });
- for (var i = 0; i < addItems.length; ++i) {
- jQuery(addItems[i].parent).before(addItems[i].target);
- }
- return result;
-};
-
-/*
- * backward compatibility for jQuery.browser
- * This will be supported until firefox bug is fixed.
- */
-if (!jQuery.browser) {
- jQuery.uaMatch = function(ua) {
- ua = ua.toLowerCase();
-
- var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
- /(webkit)[ \/]([\w.]+)/.exec(ua) ||
- /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
- /(msie) ([\w.]+)/.exec(ua) ||
- ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
- [];
-
- return {
- browser: match[ 1 ] || "",
- version: match[ 2 ] || "0"
- };
- };
- jQuery.browser = {};
- jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
-}
diff --git a/latest/_static/basic.css b/latest/_static/basic.css
deleted file mode 100644
index 7577acb1..00000000
--- a/latest/_static/basic.css
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * basic.css
- * ~~~~~~~~~
- *
- * Sphinx stylesheet -- basic theme.
- *
- * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-
-/* -- main layout ----------------------------------------------------------- */
-
-div.clearer {
- clear: both;
-}
-
-div.section::after {
- display: block;
- content: '';
- clear: left;
-}
-
-/* -- relbar ---------------------------------------------------------------- */
-
-div.related {
- width: 100%;
- font-size: 90%;
-}
-
-div.related h3 {
- display: none;
-}
-
-div.related ul {
- margin: 0;
- padding: 0 0 0 10px;
- list-style: none;
-}
-
-div.related li {
- display: inline;
-}
-
-div.related li.right {
- float: right;
- margin-right: 5px;
-}
-
-/* -- sidebar --------------------------------------------------------------- */
-
-div.sphinxsidebarwrapper {
- padding: 10px 5px 0 10px;
-}
-
-div.sphinxsidebar {
- float: left;
- width: 230px;
- margin-left: -100%;
- font-size: 90%;
- word-wrap: break-word;
- overflow-wrap : break-word;
-}
-
-div.sphinxsidebar ul {
- list-style: none;
-}
-
-div.sphinxsidebar ul ul,
-div.sphinxsidebar ul.want-points {
- margin-left: 20px;
- list-style: square;
-}
-
-div.sphinxsidebar ul ul {
- margin-top: 0;
- margin-bottom: 0;
-}
-
-div.sphinxsidebar form {
- margin-top: 10px;
-}
-
-div.sphinxsidebar input {
- border: 1px solid #98dbcc;
- font-family: sans-serif;
- font-size: 1em;
-}
-
-div.sphinxsidebar #searchbox form.search {
- overflow: hidden;
-}
-
-div.sphinxsidebar #searchbox input[type="text"] {
- float: left;
- width: 80%;
- padding: 0.25em;
- box-sizing: border-box;
-}
-
-div.sphinxsidebar #searchbox input[type="submit"] {
- float: left;
- width: 20%;
- border-left: none;
- padding: 0.25em;
- box-sizing: border-box;
-}
-
-
-img {
- border: 0;
- max-width: 100%;
-}
-
-/* -- search page ----------------------------------------------------------- */
-
-ul.search {
- margin: 10px 0 0 20px;
- padding: 0;
-}
-
-ul.search li {
- padding: 5px 0 5px 20px;
- background-image: url(file.png);
- background-repeat: no-repeat;
- background-position: 0 7px;
-}
-
-ul.search li a {
- font-weight: bold;
-}
-
-ul.search li p.context {
- color: #888;
- margin: 2px 0 0 30px;
- text-align: left;
-}
-
-ul.keywordmatches li.goodmatch a {
- font-weight: bold;
-}
-
-/* -- index page ------------------------------------------------------------ */
-
-table.contentstable {
- width: 90%;
- margin-left: auto;
- margin-right: auto;
-}
-
-table.contentstable p.biglink {
- line-height: 150%;
-}
-
-a.biglink {
- font-size: 1.3em;
-}
-
-span.linkdescr {
- font-style: italic;
- padding-top: 5px;
- font-size: 90%;
-}
-
-/* -- general index --------------------------------------------------------- */
-
-table.indextable {
- width: 100%;
-}
-
-table.indextable td {
- text-align: left;
- vertical-align: top;
-}
-
-table.indextable ul {
- margin-top: 0;
- margin-bottom: 0;
- list-style-type: none;
-}
-
-table.indextable > tbody > tr > td > ul {
- padding-left: 0em;
-}
-
-table.indextable tr.pcap {
- height: 10px;
-}
-
-table.indextable tr.cap {
- margin-top: 10px;
- background-color: #f2f2f2;
-}
-
-img.toggler {
- margin-right: 3px;
- margin-top: 3px;
- cursor: pointer;
-}
-
-div.modindex-jumpbox {
- border-top: 1px solid #ddd;
- border-bottom: 1px solid #ddd;
- margin: 1em 0 1em 0;
- padding: 0.4em;
-}
-
-div.genindex-jumpbox {
- border-top: 1px solid #ddd;
- border-bottom: 1px solid #ddd;
- margin: 1em 0 1em 0;
- padding: 0.4em;
-}
-
-/* -- domain module index --------------------------------------------------- */
-
-table.modindextable td {
- padding: 2px;
- border-collapse: collapse;
-}
-
-/* -- general body styles --------------------------------------------------- */
-
-div.body {
- min-width: 360px;
- max-width: 800px;
-}
-
-div.body p, div.body dd, div.body li, div.body blockquote {
- -moz-hyphens: auto;
- -ms-hyphens: auto;
- -webkit-hyphens: auto;
- hyphens: auto;
-}
-
-a.headerlink {
- visibility: hidden;
-}
-
-h1:hover > a.headerlink,
-h2:hover > a.headerlink,
-h3:hover > a.headerlink,
-h4:hover > a.headerlink,
-h5:hover > a.headerlink,
-h6:hover > a.headerlink,
-dt:hover > a.headerlink,
-caption:hover > a.headerlink,
-p.caption:hover > a.headerlink,
-div.code-block-caption:hover > a.headerlink {
- visibility: visible;
-}
-
-div.body p.caption {
- text-align: inherit;
-}
-
-div.body td {
- text-align: left;
-}
-
-.first {
- margin-top: 0 !important;
-}
-
-p.rubric {
- margin-top: 30px;
- font-weight: bold;
-}
-
-img.align-left, figure.align-left, .figure.align-left, object.align-left {
- clear: left;
- float: left;
- margin-right: 1em;
-}
-
-img.align-right, figure.align-right, .figure.align-right, object.align-right {
- clear: right;
- float: right;
- margin-left: 1em;
-}
-
-img.align-center, figure.align-center, .figure.align-center, object.align-center {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
-
-img.align-default, figure.align-default, .figure.align-default {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
-
-.align-left {
- text-align: left;
-}
-
-.align-center {
- text-align: center;
-}
-
-.align-default {
- text-align: center;
-}
-
-.align-right {
- text-align: right;
-}
-
-/* -- sidebars -------------------------------------------------------------- */
-
-div.sidebar,
-aside.sidebar {
- margin: 0 0 0.5em 1em;
- border: 1px solid #ddb;
- padding: 7px;
- background-color: #ffe;
- width: 40%;
- float: right;
- clear: right;
- overflow-x: auto;
-}
-
-p.sidebar-title {
- font-weight: bold;
-}
-
-nav.contents,
-aside.topic,
-div.admonition, div.topic, blockquote {
- clear: left;
-}
-
-/* -- topics ---------------------------------------------------------------- */
-
-nav.contents,
-aside.topic,
-div.topic {
- border: 1px solid #ccc;
- padding: 7px;
- margin: 10px 0 10px 0;
-}
-
-p.topic-title {
- font-size: 1.1em;
- font-weight: bold;
- margin-top: 10px;
-}
-
-/* -- admonitions ----------------------------------------------------------- */
-
-div.admonition {
- margin-top: 10px;
- margin-bottom: 10px;
- padding: 7px;
-}
-
-div.admonition dt {
- font-weight: bold;
-}
-
-p.admonition-title {
- margin: 0px 10px 5px 0px;
- font-weight: bold;
-}
-
-div.body p.centered {
- text-align: center;
- margin-top: 25px;
-}
-
-/* -- content of sidebars/topics/admonitions -------------------------------- */
-
-div.sidebar > :last-child,
-aside.sidebar > :last-child,
-nav.contents > :last-child,
-aside.topic > :last-child,
-div.topic > :last-child,
-div.admonition > :last-child {
- margin-bottom: 0;
-}
-
-div.sidebar::after,
-aside.sidebar::after,
-nav.contents::after,
-aside.topic::after,
-div.topic::after,
-div.admonition::after,
-blockquote::after {
- display: block;
- content: '';
- clear: both;
-}
-
-/* -- tables ---------------------------------------------------------------- */
-
-table.docutils {
- margin-top: 10px;
- margin-bottom: 10px;
- border: 0;
- border-collapse: collapse;
-}
-
-table.align-center {
- margin-left: auto;
- margin-right: auto;
-}
-
-table.align-default {
- margin-left: auto;
- margin-right: auto;
-}
-
-table caption span.caption-number {
- font-style: italic;
-}
-
-table caption span.caption-text {
-}
-
-table.docutils td, table.docutils th {
- padding: 1px 8px 1px 5px;
- border-top: 0;
- border-left: 0;
- border-right: 0;
- border-bottom: 1px solid #aaa;
-}
-
-th {
- text-align: left;
- padding-right: 5px;
-}
-
-table.citation {
- border-left: solid 1px gray;
- margin-left: 1px;
-}
-
-table.citation td {
- border-bottom: none;
-}
-
-th > :first-child,
-td > :first-child {
- margin-top: 0px;
-}
-
-th > :last-child,
-td > :last-child {
- margin-bottom: 0px;
-}
-
-/* -- figures --------------------------------------------------------------- */
-
-div.figure, figure {
- margin: 0.5em;
- padding: 0.5em;
-}
-
-div.figure p.caption, figcaption {
- padding: 0.3em;
-}
-
-div.figure p.caption span.caption-number,
-figcaption span.caption-number {
- font-style: italic;
-}
-
-div.figure p.caption span.caption-text,
-figcaption span.caption-text {
-}
-
-/* -- field list styles ----------------------------------------------------- */
-
-table.field-list td, table.field-list th {
- border: 0 !important;
-}
-
-.field-list ul {
- margin: 0;
- padding-left: 1em;
-}
-
-.field-list p {
- margin: 0;
-}
-
-.field-name {
- -moz-hyphens: manual;
- -ms-hyphens: manual;
- -webkit-hyphens: manual;
- hyphens: manual;
-}
-
-/* -- hlist styles ---------------------------------------------------------- */
-
-table.hlist {
- margin: 1em 0;
-}
-
-table.hlist td {
- vertical-align: top;
-}
-
-/* -- object description styles --------------------------------------------- */
-
-.sig {
- font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
-}
-
-.sig-name, code.descname {
- background-color: transparent;
- font-weight: bold;
-}
-
-.sig-name {
- font-size: 1.1em;
-}
-
-code.descname {
- font-size: 1.2em;
-}
-
-.sig-prename, code.descclassname {
- background-color: transparent;
-}
-
-.optional {
- font-size: 1.3em;
-}
-
-.sig-paren {
- font-size: larger;
-}
-
-.sig-param.n {
- font-style: italic;
-}
-
-/* C++ specific styling */
-
-.sig-inline.c-texpr,
-.sig-inline.cpp-texpr {
- font-family: unset;
-}
-
-.sig.c .k, .sig.c .kt,
-.sig.cpp .k, .sig.cpp .kt {
- color: #0033B3;
-}
-
-.sig.c .m,
-.sig.cpp .m {
- color: #1750EB;
-}
-
-.sig.c .s, .sig.c .sc,
-.sig.cpp .s, .sig.cpp .sc {
- color: #067D17;
-}
-
-
-/* -- other body styles ----------------------------------------------------- */
-
-ol.arabic {
- list-style: decimal;
-}
-
-ol.loweralpha {
- list-style: lower-alpha;
-}
-
-ol.upperalpha {
- list-style: upper-alpha;
-}
-
-ol.lowerroman {
- list-style: lower-roman;
-}
-
-ol.upperroman {
- list-style: upper-roman;
-}
-
-:not(li) > ol > li:first-child > :first-child,
-:not(li) > ul > li:first-child > :first-child {
- margin-top: 0px;
-}
-
-:not(li) > ol > li:last-child > :last-child,
-:not(li) > ul > li:last-child > :last-child {
- margin-bottom: 0px;
-}
-
-ol.simple ol p,
-ol.simple ul p,
-ul.simple ol p,
-ul.simple ul p {
- margin-top: 0;
-}
-
-ol.simple > li:not(:first-child) > p,
-ul.simple > li:not(:first-child) > p {
- margin-top: 0;
-}
-
-ol.simple p,
-ul.simple p {
- margin-bottom: 0;
-}
-
-aside.footnote > span,
-div.citation > span {
- float: left;
-}
-aside.footnote > span:last-of-type,
-div.citation > span:last-of-type {
- padding-right: 0.5em;
-}
-aside.footnote > p {
- margin-left: 2em;
-}
-div.citation > p {
- margin-left: 4em;
-}
-aside.footnote > p:last-of-type,
-div.citation > p:last-of-type {
- margin-bottom: 0em;
-}
-aside.footnote > p:last-of-type:after,
-div.citation > p:last-of-type:after {
- content: "";
- clear: both;
-}
-
-dl.field-list {
- display: grid;
- grid-template-columns: fit-content(30%) auto;
-}
-
-dl.field-list > dt {
- font-weight: bold;
- word-break: break-word;
- padding-left: 0.5em;
- padding-right: 5px;
-}
-
-dl.field-list > dd {
- padding-left: 0.5em;
- margin-top: 0em;
- margin-left: 0em;
- margin-bottom: 0em;
-}
-
-dl {
- margin-bottom: 15px;
-}
-
-dd > :first-child {
- margin-top: 0px;
-}
-
-dd ul, dd table {
- margin-bottom: 10px;
-}
-
-dd {
- margin-top: 3px;
- margin-bottom: 10px;
- margin-left: 30px;
-}
-
-dl > dd:last-child,
-dl > dd:last-child > :last-child {
- margin-bottom: 0;
-}
-
-dt:target, span.highlighted {
- background-color: #fbe54e;
-}
-
-rect.highlighted {
- fill: #fbe54e;
-}
-
-dl.glossary dt {
- font-weight: bold;
- font-size: 1.1em;
-}
-
-.versionmodified {
- font-style: italic;
-}
-
-.system-message {
- background-color: #fda;
- padding: 5px;
- border: 3px solid red;
-}
-
-.footnote:target {
- background-color: #ffa;
-}
-
-.line-block {
- display: block;
- margin-top: 1em;
- margin-bottom: 1em;
-}
-
-.line-block .line-block {
- margin-top: 0;
- margin-bottom: 0;
- margin-left: 1.5em;
-}
-
-.guilabel, .menuselection {
- font-family: sans-serif;
-}
-
-.accelerator {
- text-decoration: underline;
-}
-
-.classifier {
- font-style: oblique;
-}
-
-.classifier:before {
- font-style: normal;
- margin: 0 0.5em;
- content: ":";
- display: inline-block;
-}
-
-abbr, acronym {
- border-bottom: dotted 1px;
- cursor: help;
-}
-
-/* -- code displays --------------------------------------------------------- */
-
-pre {
- overflow: auto;
- overflow-y: hidden; /* fixes display issues on Chrome browsers */
-}
-
-pre, div[class*="highlight-"] {
- clear: both;
-}
-
-span.pre {
- -moz-hyphens: none;
- -ms-hyphens: none;
- -webkit-hyphens: none;
- hyphens: none;
- white-space: nowrap;
-}
-
-div[class*="highlight-"] {
- margin: 1em 0;
-}
-
-td.linenos pre {
- border: 0;
- background-color: transparent;
- color: #aaa;
-}
-
-table.highlighttable {
- display: block;
-}
-
-table.highlighttable tbody {
- display: block;
-}
-
-table.highlighttable tr {
- display: flex;
-}
-
-table.highlighttable td {
- margin: 0;
- padding: 0;
-}
-
-table.highlighttable td.linenos {
- padding-right: 0.5em;
-}
-
-table.highlighttable td.code {
- flex: 1;
- overflow: hidden;
-}
-
-.highlight .hll {
- display: block;
-}
-
-div.highlight pre,
-table.highlighttable pre {
- margin: 0;
-}
-
-div.code-block-caption + div {
- margin-top: 0;
-}
-
-div.code-block-caption {
- margin-top: 1em;
- padding: 2px 5px;
- font-size: small;
-}
-
-div.code-block-caption code {
- background-color: transparent;
-}
-
-table.highlighttable td.linenos,
-span.linenos,
-div.highlight span.gp { /* gp: Generic.Prompt */
- user-select: none;
- -webkit-user-select: text; /* Safari fallback only */
- -webkit-user-select: none; /* Chrome/Safari */
- -moz-user-select: none; /* Firefox */
- -ms-user-select: none; /* IE10+ */
-}
-
-div.code-block-caption span.caption-number {
- padding: 0.1em 0.3em;
- font-style: italic;
-}
-
-div.code-block-caption span.caption-text {
-}
-
-div.literal-block-wrapper {
- margin: 1em 0;
-}
-
-code.xref, a code {
- background-color: transparent;
- font-weight: bold;
-}
-
-h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
- background-color: transparent;
-}
-
-.viewcode-link {
- float: right;
-}
-
-.viewcode-back {
- float: right;
- font-family: sans-serif;
-}
-
-div.viewcode-block:target {
- margin: -1px -10px;
- padding: 0 10px;
-}
-
-/* -- math display ---------------------------------------------------------- */
-
-img.math {
- vertical-align: middle;
-}
-
-div.body div.math p {
- text-align: center;
-}
-
-span.eqno {
- float: right;
-}
-
-span.eqno a.headerlink {
- position: absolute;
- z-index: 1;
-}
-
-div.math:hover a.headerlink {
- visibility: visible;
-}
-
-/* -- printout stylesheet --------------------------------------------------- */
-
-@media print {
- div.document,
- div.documentwrapper,
- div.bodywrapper {
- margin: 0 !important;
- width: 100%;
- }
-
- div.sphinxsidebar,
- div.related,
- div.footer,
- #top-link {
- display: none;
- }
-}
\ No newline at end of file
diff --git a/latest/_static/custom.css b/latest/_static/custom.css
deleted file mode 100644
index cd8af758..00000000
--- a/latest/_static/custom.css
+++ /dev/null
@@ -1,3 +0,0 @@
-html[data-accent-color='lime'] {
- --accent-9: #7efa01;
-}
\ No newline at end of file
diff --git a/latest/_static/doctools.js b/latest/_static/doctools.js
deleted file mode 100644
index d06a71d7..00000000
--- a/latest/_static/doctools.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * doctools.js
- * ~~~~~~~~~~~
- *
- * Base JavaScript utilities for all Sphinx HTML documentation.
- *
- * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-"use strict";
-
-const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
- "TEXTAREA",
- "INPUT",
- "SELECT",
- "BUTTON",
-]);
-
-const _ready = (callback) => {
- if (document.readyState !== "loading") {
- callback();
- } else {
- document.addEventListener("DOMContentLoaded", callback);
- }
-};
-
-/**
- * Small JavaScript module for the documentation.
- */
-const Documentation = {
- init: () => {
- Documentation.initDomainIndexTable();
- Documentation.initOnKeyListeners();
- },
-
- /**
- * i18n support
- */
- TRANSLATIONS: {},
- PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
- LOCALE: "unknown",
-
- // gettext and ngettext don't access this so that the functions
- // can safely bound to a different name (_ = Documentation.gettext)
- gettext: (string) => {
- const translated = Documentation.TRANSLATIONS[string];
- switch (typeof translated) {
- case "undefined":
- return string; // no translation
- case "string":
- return translated; // translation exists
- default:
- return translated[0]; // (singular, plural) translation tuple exists
- }
- },
-
- ngettext: (singular, plural, n) => {
- const translated = Documentation.TRANSLATIONS[singular];
- if (typeof translated !== "undefined")
- return translated[Documentation.PLURAL_EXPR(n)];
- return n === 1 ? singular : plural;
- },
-
- addTranslations: (catalog) => {
- Object.assign(Documentation.TRANSLATIONS, catalog.messages);
- Documentation.PLURAL_EXPR = new Function(
- "n",
- `return (${catalog.plural_expr})`
- );
- Documentation.LOCALE = catalog.locale;
- },
-
- /**
- * helper function to focus on search bar
- */
- focusSearchBar: () => {
- document.querySelectorAll("input[name=q]")[0]?.focus();
- },
-
- /**
- * Initialise the domain index toggle buttons
- */
- initDomainIndexTable: () => {
- const toggler = (el) => {
- const idNumber = el.id.substr(7);
- const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
- if (el.src.substr(-9) === "minus.png") {
- el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
- toggledRows.forEach((el) => (el.style.display = "none"));
- } else {
- el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
- toggledRows.forEach((el) => (el.style.display = ""));
- }
- };
-
- const togglerElements = document.querySelectorAll("img.toggler");
- togglerElements.forEach((el) =>
- el.addEventListener("click", (event) => toggler(event.currentTarget))
- );
- togglerElements.forEach((el) => (el.style.display = ""));
- if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
- },
-
- initOnKeyListeners: () => {
- // only install a listener if it is really needed
- if (
- !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
- !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
- )
- return;
-
- document.addEventListener("keydown", (event) => {
- // bail for input elements
- if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
- // bail with special keys
- if (event.altKey || event.ctrlKey || event.metaKey) return;
-
- if (!event.shiftKey) {
- switch (event.key) {
- case "ArrowLeft":
- if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
-
- const prevLink = document.querySelector('link[rel="prev"]');
- if (prevLink && prevLink.href) {
- window.location.href = prevLink.href;
- event.preventDefault();
- }
- break;
- case "ArrowRight":
- if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
-
- const nextLink = document.querySelector('link[rel="next"]');
- if (nextLink && nextLink.href) {
- window.location.href = nextLink.href;
- event.preventDefault();
- }
- break;
- }
- }
-
- // some keyboard layouts may need Shift to get /
- switch (event.key) {
- case "/":
- if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
- Documentation.focusSearchBar();
- event.preventDefault();
- }
- });
- },
-};
-
-// quick alias for translations
-const _ = Documentation.gettext;
-
-_ready(Documentation.init);
diff --git a/latest/_static/documentation_options.js b/latest/_static/documentation_options.js
deleted file mode 100644
index b57ae3b8..00000000
--- a/latest/_static/documentation_options.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var DOCUMENTATION_OPTIONS = {
- URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
- VERSION: '',
- LANGUAGE: 'en',
- COLLAPSE_INDEX: false,
- BUILDER: 'html',
- FILE_SUFFIX: '.html',
- LINK_SUFFIX: '.html',
- HAS_SOURCE: true,
- SOURCELINK_SUFFIX: '.txt',
- NAVIGATION_WITH_KEYS: false,
- SHOW_SEARCH_SUMMARY: true,
- ENABLE_SEARCH_SHORTCUTS: true,
-};
\ No newline at end of file
diff --git a/latest/_static/favicon.ico b/latest/_static/favicon.ico
deleted file mode 100644
index 05f17aa6..00000000
Binary files a/latest/_static/favicon.ico and /dev/null differ
diff --git a/latest/_static/file.png b/latest/_static/file.png
deleted file mode 100644
index a858a410..00000000
Binary files a/latest/_static/file.png and /dev/null differ
diff --git a/latest/_static/jquery.js b/latest/_static/jquery.js
deleted file mode 100644
index c4c6022f..00000000
--- a/latest/_static/jquery.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */
-!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=" ",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML=" ";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML=" ",y.option=!!ce.lastChild;var ge={thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 00
- var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
- var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
- var s_v = "^(" + C + ")?" + v; // vowel in stem
-
- this.stemWord = function (w) {
- var stem;
- var suffix;
- var firstch;
- var origword = w;
-
- if (w.length < 3)
- return w;
-
- var re;
- var re2;
- var re3;
- var re4;
-
- firstch = w.substr(0,1);
- if (firstch == "y")
- w = firstch.toUpperCase() + w.substr(1);
-
- // Step 1a
- re = /^(.+?)(ss|i)es$/;
- re2 = /^(.+?)([^s])s$/;
-
- if (re.test(w))
- w = w.replace(re,"$1$2");
- else if (re2.test(w))
- w = w.replace(re2,"$1$2");
-
- // Step 1b
- re = /^(.+?)eed$/;
- re2 = /^(.+?)(ed|ing)$/;
- if (re.test(w)) {
- var fp = re.exec(w);
- re = new RegExp(mgr0);
- if (re.test(fp[1])) {
- re = /.$/;
- w = w.replace(re,"");
- }
- }
- else if (re2.test(w)) {
- var fp = re2.exec(w);
- stem = fp[1];
- re2 = new RegExp(s_v);
- if (re2.test(stem)) {
- w = stem;
- re2 = /(at|bl|iz)$/;
- re3 = new RegExp("([^aeiouylsz])\\1$");
- re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
- if (re2.test(w))
- w = w + "e";
- else if (re3.test(w)) {
- re = /.$/;
- w = w.replace(re,"");
- }
- else if (re4.test(w))
- w = w + "e";
- }
- }
-
- // Step 1c
- re = /^(.+?)y$/;
- if (re.test(w)) {
- var fp = re.exec(w);
- stem = fp[1];
- re = new RegExp(s_v);
- if (re.test(stem))
- w = stem + "i";
- }
-
- // Step 2
- re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
- if (re.test(w)) {
- var fp = re.exec(w);
- stem = fp[1];
- suffix = fp[2];
- re = new RegExp(mgr0);
- if (re.test(stem))
- w = stem + step2list[suffix];
- }
-
- // Step 3
- re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
- if (re.test(w)) {
- var fp = re.exec(w);
- stem = fp[1];
- suffix = fp[2];
- re = new RegExp(mgr0);
- if (re.test(stem))
- w = stem + step3list[suffix];
- }
-
- // Step 4
- re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
- re2 = /^(.+?)(s|t)(ion)$/;
- if (re.test(w)) {
- var fp = re.exec(w);
- stem = fp[1];
- re = new RegExp(mgr1);
- if (re.test(stem))
- w = stem;
- }
- else if (re2.test(w)) {
- var fp = re2.exec(w);
- stem = fp[1] + fp[2];
- re2 = new RegExp(mgr1);
- if (re2.test(stem))
- w = stem;
- }
-
- // Step 5
- re = /^(.+?)e$/;
- if (re.test(w)) {
- var fp = re.exec(w);
- stem = fp[1];
- re = new RegExp(mgr1);
- re2 = new RegExp(meq1);
- re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
- if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
- w = stem;
- }
- re = /ll$/;
- re2 = new RegExp(mgr1);
- if (re.test(w) && re2.test(w)) {
- re = /.$/;
- w = w.replace(re,"");
- }
-
- // and turn initial Y back to y
- if (firstch == "y")
- w = firstch.toLowerCase() + w.substr(1);
- return w;
- }
-}
-
diff --git a/latest/_static/logo.gif b/latest/_static/logo.gif
deleted file mode 100644
index b3a1bcc2..00000000
Binary files a/latest/_static/logo.gif and /dev/null differ
diff --git a/latest/_static/logo_green.svg b/latest/_static/logo_green.svg
deleted file mode 100644
index 3e3eb9db..00000000
--- a/latest/_static/logo_green.svg
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/latest/_static/logo_grey.svg b/latest/_static/logo_grey.svg
deleted file mode 100644
index f59c51c0..00000000
--- a/latest/_static/logo_grey.svg
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/latest/_static/minus.png b/latest/_static/minus.png
deleted file mode 100644
index d96755fd..00000000
Binary files a/latest/_static/minus.png and /dev/null differ
diff --git a/latest/_static/plus.png b/latest/_static/plus.png
deleted file mode 100644
index 7107cec9..00000000
Binary files a/latest/_static/plus.png and /dev/null differ
diff --git a/latest/_static/print.css b/latest/_static/print.css
deleted file mode 100644
index bd88769f..00000000
--- a/latest/_static/print.css
+++ /dev/null
@@ -1,42 +0,0 @@
-.sy-head {
- position: static;
- border-bottom: 1px solid var(--sy-c-divider);
-}
-
-.sy-head-inner {
- padding: 0;
-}
-
-.sy-breadcrumbs {
- display: none;
-}
-
-h1, h2, h3, h4, h5, h6 {
- page-break-inside: avoid;
- page-break-after: avoid;
-}
-
-.code-block-caption,
-pre, code {
- page-break-inside: avoid;
- white-space: pre-wrap;
-
- -webkit-print-color-adjust: exact;
-}
-
-.yue a.headerlink {
- display: none;
-}
-
-.highlight .linenos {
- box-shadow: none;
-}
-
-.admonition,
-.sd-sphinx-override {
- -webkit-print-color-adjust: exact;
-}
-
-.sd-card {
- page-break-inside: avoid;
-}
diff --git a/latest/_static/pygments.css b/latest/_static/pygments.css
deleted file mode 100644
index 449a846d..00000000
--- a/latest/_static/pygments.css
+++ /dev/null
@@ -1 +0,0 @@
-:root{--syntax-pre-bg: var(--accent-a2);--syntax-cap-bg: var(--accent-a3);--syntax-highlight-bg: var(--accent-a3);--syntax-linenos-divider: var(--gray-a6);--syntax-light-text: #24292f;--syntax-light-meta: #807c87;--syntax-light-comment: #6e7781;--syntax-light-constant: #0550ae;--syntax-light-entity: #268bd2;--syntax-light-property: #8250df;--syntax-light-definition: #24292f;--syntax-light-tag: #085;--syntax-light-builtin: #b58900;--syntax-light-keyword: #cf222e;--syntax-light-exception: #e6212e;--syntax-light-string: #0a3069;--syntax-light-regexp: #e40;--syntax-light-variable: #a4480f;--syntax-light-invalid-illegal-text: #f6f8fa;--syntax-light-invalid-illegal-bg: #82071e;--syntax-light-markup-heading: #0550ae;--syntax-light-markup-italic: #24292f;--syntax-light-markup-bold: #24292f;--syntax-light-markup-deleted-text: #82071e;--syntax-light-markup-deleted-bg: #FFEBE9;--syntax-light-markup-inserted-text: #116329;--syntax-light-markup-inserted-bg: #dafbe1;--syntax-light-markup-changed-text: #953800;--syntax-light-markup-changed-bg: #ffd8b5;--syntax-light-markup-ignored-text: #eaeef2;--syntax-light-markup-ignored-bg: #0550ae;--syntax-light-meta-diff-range: #8250df;--syntax-light-special-bg: #dccafa;--syntax-dark-text: #c9d1d9;--syntax-dark-meta: #6e7781;--syntax-dark-comment: #8b949e;--syntax-dark-constant: #79c0ff;--syntax-dark-entity: #47b0fa;--syntax-dark-property: #d2a8ff;--syntax-dark-definition: #c9d1d9;--syntax-dark-tag: #7ee787;--syntax-dark-builtin: #ffd34c;--syntax-dark-keyword: #ff7b72;--syntax-dark-exception: #da473c;--syntax-dark-string: #a5d6ff;--syntax-dark-regexp: #ef954e;--syntax-dark-variable: #ffa657;--syntax-dark-invalid-illegal-text: #f0f6fc;--syntax-dark-invalid-illegal-bg: #8e1519;--syntax-dark-markup-heading: #1f6feb;--syntax-dark-markup-italic: #c9d1d9;--syntax-dark-markup-bold: #c9d1d9;--syntax-dark-markup-deleted-text: #ffdcd7;--syntax-dark-markup-deleted-bg: #67060c;--syntax-dark-markup-inserted-text: #aff5b4;--syntax-dark-markup-inserted-bg: #033a16;--syntax-dark-markup-changed-text: #ffdfb6;--syntax-dark-markup-changed-bg: #5a1e02;--syntax-dark-markup-ignored-text: #c9d1d9;--syntax-dark-markup-ignored-bg: #1158c7;--syntax-dark-meta-diff-range: #d2a8ff;--syntax-dark-special-bg: #4f425d}:root,html.light{--syntax-text: var(--syntax-light-text);--syntax-meta: var(--syntax-light-meta);--syntax-comment: var(--syntax-light-comment);--syntax-constant: var(--syntax-light-constant);--syntax-entity: var(--syntax-light-entity);--syntax-property: var(--syntax-light-property);--syntax-definition: var(--syntax-light-definition);--syntax-tag: var(--syntax-light-tag);--syntax-builtin: var(--syntax-light-builtin);--syntax-keyword: var(--syntax-light-keyword);--syntax-exception: var(--syntax-light-exception);--syntax-string: var(--syntax-light-string);--syntax-regexp: var(--syntax-light-regexp);--syntax-variable: var(--syntax-light-variable);--syntax-invalid-illegal-text: var(--syntax-light-invalid-illegal-text);--syntax-invalid-illegal-bg: var(--syntax-light-invalid-illegal-bg);--syntax-markup-heading: var(--syntax-light-markup-heading);--syntax-markup-italic: var(--syntax-light-markup-italic);--syntax-markup-bold: var(--syntax-light-markup-bold);--syntax-markup-deleted-text: var(--syntax-light-markup-deleted-text);--syntax-markup-deleted-bg: var(--syntax-light-markup-deleted-bg);--syntax-markup-inserted-text: var(--syntax-light-markup-inserted-text);--syntax-markup-inserted-bg: var(--syntax-light-markup-inserted-bg);--syntax-markup-changed-text: var(--syntax-light-markup-changed-text);--syntax-markup-changed-bg: var(--syntax-light-markup-changed-bg);--syntax-markup-ignored-text: var(--syntax-light-markup-ignored-text);--syntax-markup-ignored-bg: var(--syntax-light-markup-ignored-bg);--syntax-meta-diff-range: var(--syntax-light-meta-diff-range);--syntax-special-bg: var(--syntax-light-special-bg)}@media (prefers-color-scheme: dark){:root{--syntax-text: var(--syntax-dark-text);--syntax-meta: var(--syntax-dark-meta);--syntax-comment: var(--syntax-dark-comment);--syntax-constant: var(--syntax-dark-constant);--syntax-entity: var(--syntax-dark-entity);--syntax-property: var(--syntax-dark-property);--syntax-definition: var(--syntax-dark-definition);--syntax-tag: var(--syntax-dark-tag);--syntax-builtin: var(--syntax-dark-builtin);--syntax-keyword: var(--syntax-dark-keyword);--syntax-exception: var(--syntax-dark-exception);--syntax-string: var(--syntax-dark-string);--syntax-regexp: var(--syntax-dark-regexp);--syntax-variable: var(--syntax-dark-variable);--syntax-invalid-illegal-text: var(--syntax-dark-invalid-illegal-text);--syntax-invalid-illegal-bg: var(--syntax-dark-invalid-illegal-bg);--syntax-markup-heading: var(--syntax-dark-markup-heading);--syntax-markup-italic: var(--syntax-dark-markup-italic);--syntax-markup-bold: var(--syntax-dark-markup-bold);--syntax-markup-deleted-text: var(--syntax-dark-markup-deleted-text);--syntax-markup-deleted-bg: var(--syntax-dark-markup-deleted-bg);--syntax-markup-inserted-text: var(--syntax-dark-markup-inserted-text);--syntax-markup-inserted-bg: var(--syntax-dark-markup-inserted-bg);--syntax-markup-changed-text: var(--syntax-dark-markup-changed-text);--syntax-markup-changed-bg: var(--syntax-dark-markup-changed-bg);--syntax-markup-ignored-text: var(--syntax-dark-markup-ignored-text);--syntax-markup-ignored-bg: var(--syntax-dark-markup-ignored-bg);--syntax-meta-diff-range: var(--syntax-dark-meta-diff-range);--syntax-special-bg: var(--syntax-dark-special-bg)}}html.dark{--syntax-text: var(--syntax-dark-text);--syntax-meta: var(--syntax-dark-meta);--syntax-comment: var(--syntax-dark-comment);--syntax-constant: var(--syntax-dark-constant);--syntax-entity: var(--syntax-dark-entity);--syntax-property: var(--syntax-dark-property);--syntax-definition: var(--syntax-dark-definition);--syntax-tag: var(--syntax-dark-tag);--syntax-builtin: var(--syntax-dark-builtin);--syntax-keyword: var(--syntax-dark-keyword);--syntax-exception: var(--syntax-dark-exception);--syntax-string: var(--syntax-dark-string);--syntax-regexp: var(--syntax-dark-regexp);--syntax-variable: var(--syntax-dark-variable);--syntax-invalid-illegal-text: var(--syntax-dark-invalid-illegal-text);--syntax-invalid-illegal-bg: var(--syntax-dark-invalid-illegal-bg);--syntax-markup-heading: var(--syntax-dark-markup-heading);--syntax-markup-italic: var(--syntax-dark-markup-italic);--syntax-markup-bold: var(--syntax-dark-markup-bold);--syntax-markup-deleted-text: var(--syntax-dark-markup-deleted-text);--syntax-markup-deleted-bg: var(--syntax-dark-markup-deleted-bg);--syntax-markup-inserted-text: var(--syntax-dark-markup-inserted-text);--syntax-markup-inserted-bg: var(--syntax-dark-markup-inserted-bg);--syntax-markup-changed-text: var(--syntax-dark-markup-changed-text);--syntax-markup-changed-bg: var(--syntax-dark-markup-changed-bg);--syntax-markup-ignored-text: var(--syntax-dark-markup-ignored-text);--syntax-markup-ignored-bg: var(--syntax-dark-markup-ignored-bg);--syntax-meta-diff-range: var(--syntax-dark-meta-diff-range);--syntax-special-bg: var(--syntax-dark-special-bg)}.light .dark-code{--syntax-pre-bg: var(--black-a12);--syntax-cap-bg: #1C2024;--syntax-highlight-bg: var(--white-a2);--syntax-linenos-divider: var(--white-a4);--syntax-text: var(--syntax-dark-text);--syntax-meta: var(--syntax-dark-meta);--syntax-comment: var(--syntax-dark-comment);--syntax-constant: var(--syntax-dark-constant);--syntax-entity: var(--syntax-dark-entity);--syntax-property: var(--syntax-dark-property);--syntax-definition: var(--syntax-dark-definition);--syntax-tag: var(--syntax-dark-tag);--syntax-builtin: var(--syntax-dark-builtin);--syntax-keyword: var(--syntax-dark-keyword);--syntax-exception: var(--syntax-dark-exception);--syntax-string: var(--syntax-dark-string);--syntax-regexp: var(--syntax-dark-regexp);--syntax-variable: var(--syntax-dark-variable);--syntax-invalid-illegal-text: var(--syntax-dark-invalid-illegal-text);--syntax-invalid-illegal-bg: var(--syntax-dark-invalid-illegal-bg);--syntax-markup-heading: var(--syntax-dark-markup-heading);--syntax-markup-italic: var(--syntax-dark-markup-italic);--syntax-markup-bold: var(--syntax-dark-markup-bold);--syntax-markup-deleted-text: var(--syntax-dark-markup-deleted-text);--syntax-markup-deleted-bg: var(--syntax-dark-markup-deleted-bg);--syntax-markup-inserted-text: var(--syntax-dark-markup-inserted-text);--syntax-markup-inserted-bg: var(--syntax-dark-markup-inserted-bg);--syntax-markup-changed-text: var(--syntax-dark-markup-changed-text);--syntax-markup-changed-bg: var(--syntax-dark-markup-changed-bg);--syntax-markup-ignored-text: var(--syntax-dark-markup-ignored-text);--syntax-markup-ignored-bg: var(--syntax-dark-markup-ignored-bg);--syntax-meta-diff-range: var(--syntax-dark-meta-diff-range);--syntax-special-bg: var(--syntax-dark-special-bg)}html.light .sd-tab-content,html.light .jupyter_container .cell_output{--syntax-pre-bg: var(--color-surface-accent);--syntax-cap-bg: var(--accent-3);--syntax-highlight-bg: var(--accent-a3);--syntax-text: var(--syntax-light-text);--syntax-meta: var(--syntax-light-meta);--syntax-comment: var(--syntax-light-comment);--syntax-constant: var(--syntax-light-constant);--syntax-entity: var(--syntax-light-entity);--syntax-property: var(--syntax-light-property);--syntax-definition: var(--syntax-light-definition);--syntax-tag: var(--syntax-light-tag);--syntax-builtin: var(--syntax-light-builtin);--syntax-keyword: var(--syntax-light-keyword);--syntax-exception: var(--syntax-light-exception);--syntax-string: var(--syntax-light-string);--syntax-regexp: var(--syntax-light-regexp);--syntax-variable: var(--syntax-light-variable);--syntax-invalid-illegal-text: var(--syntax-light-invalid-illegal-text);--syntax-invalid-illegal-bg: var(--syntax-light-invalid-illegal-bg);--syntax-markup-heading: var(--syntax-light-markup-heading);--syntax-markup-italic: var(--syntax-light-markup-italic);--syntax-markup-bold: var(--syntax-light-markup-bold);--syntax-markup-deleted-text: var(--syntax-light-markup-deleted-text);--syntax-markup-deleted-bg: var(--syntax-light-markup-deleted-bg);--syntax-markup-inserted-text: var(--syntax-light-markup-inserted-text);--syntax-markup-inserted-bg: var(--syntax-light-markup-inserted-bg);--syntax-markup-changed-text: var(--syntax-light-markup-changed-text);--syntax-markup-changed-bg: var(--syntax-light-markup-changed-bg);--syntax-markup-ignored-text: var(--syntax-light-markup-ignored-text);--syntax-markup-ignored-bg: var(--syntax-light-markup-ignored-bg);--syntax-meta-diff-range: var(--syntax-light-meta-diff-range);--syntax-highlight-bg: var(--syntax-light-highlight-bg);--syntax-special-bg: var(--syntax-light-special-bg)}.highlight{color:var(--syntax-text);background-color:transparent}.highlight .hll{display:block;background-color:var(--syntax-highlight-bg)}.highlight .c{color:var(--syntax-comment)}.highlight .err{color:var(--syntax-invalid-illegal-text);background-color:var(--syntax-invalid-illegal-bg)}.highlight .g{color:var(--syntax-meta)}.highlight .k{color:var(--syntax-keyword)}.highlight .l{color:var(--syntax-meta)}.highlight .o{color:var(--syntax-constant)}.highlight .x{color:var(--syntax-meta)}.highlight .cm{color:var(--syntax-comment)}.highlight .cp{color:var(--syntax-constant)}.highlight .c1{color:var(--syntax-comment)}.highlight .cs{color:var(--syntax-comment);background-color:var(--syntax-special-bg)}.highlight .gd{color:var(--syntax-markup-deleted-text);background-color:var(--syntax-markup-deleted-bg)}.highlight .ge{color:var(--syntax-markup-italic);font-style:italic}.highlight .gr{color:var(--syntax-invalid-illegal-text);background-color:var(--syntax-invalid-illegal-bg)}.highlight .gh{color:var(--syntax-markup-heading)}.highlight .gi{color:var(--syntax-markup-inserted-text);background-color:var(--syntax-markup-inserted-bg)}.highlight .go,.highlight .gp{color:var(--syntax-meta)}.highlight .gs{color:var(--syntax-markup-bold);font-weight:700}.highlight .gu{color:var(--syntax-markup-heading)}.highlight .gt{color:var(--syntax-meta)}.highlight .kc{color:var(--syntax-constant)}.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{color:var(--syntax-keyword)}.highlight .kt{color:var(--syntax-entity)}.highlight .ld{color:var(--syntax-meta)}.highlight .m{color:var(--syntax-constant)}.highlight .s{color:var(--syntax-string)}.highlight .il,.highlight .na{color:var(--syntax-constant)}.highlight .nb{color:var(--syntax-builtin)}.highlight .nc{color:var(--syntax-definition)}.highlight .no{color:var(--syntax-constant)}.highlight .nd,.highlight .ni{color:var(--syntax-entity)}.highlight .ne{color:var(--syntax-exception)}.highlight .nf{color:var(--syntax-definition)}.highlight .nt{color:var(--syntax-tag)}.highlight .ow{color:var(--syntax-constant)}.highlight .w{color:var(--syntax-meta)}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:var(--syntax-constant)}.highlight .sb{color:var(--syntax-meta)}.highlight .sc{color:var(--syntax-string)}.highlight .sd{color:var(--syntax-comment)}.highlight .s2,.highlight .se{color:var(--syntax-string)}.highlight .sh{color:var(--syntax-comment)}.highlight .si,.highlight .sx{color:var(--syntax-string)}.highlight .sr{color:var(--syntax-regexp)}.highlight .s1,.highlight .ss{color:var(--syntax-string)}.highlight .bp,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--syntax-variable)}
diff --git a/latest/_static/searchtools.js b/latest/_static/searchtools.js
deleted file mode 100644
index 97d56a74..00000000
--- a/latest/_static/searchtools.js
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * searchtools.js
- * ~~~~~~~~~~~~~~~~
- *
- * Sphinx JavaScript utilities for the full-text search.
- *
- * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-"use strict";
-
-/**
- * Simple result scoring code.
- */
-if (typeof Scorer === "undefined") {
- var Scorer = {
- // Implement the following function to further tweak the score for each result
- // The function takes a result array [docname, title, anchor, descr, score, filename]
- // and returns the new score.
- /*
- score: result => {
- const [docname, title, anchor, descr, score, filename] = result
- return score
- },
- */
-
- // query matches the full name of an object
- objNameMatch: 11,
- // or matches in the last dotted part of the object name
- objPartialMatch: 6,
- // Additive scores depending on the priority of the object
- objPrio: {
- 0: 15, // used to be importantResults
- 1: 5, // used to be objectResults
- 2: -5, // used to be unimportantResults
- },
- // Used when the priority is not in the mapping.
- objPrioDefault: 0,
-
- // query found in title
- title: 15,
- partialTitle: 7,
- // query found in terms
- term: 5,
- partialTerm: 2,
- };
-}
-
-const _removeChildren = (element) => {
- while (element && element.lastChild) element.removeChild(element.lastChild);
-};
-
-/**
- * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
- */
-const _escapeRegExp = (string) =>
- string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
-
-const _displayItem = (item, searchTerms) => {
- const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
- const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT;
- const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
- const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
- const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
-
- const [docName, title, anchor, descr, score, _filename] = item;
-
- let listItem = document.createElement("li");
- let requestUrl;
- let linkUrl;
- if (docBuilder === "dirhtml") {
- // dirhtml builder
- let dirname = docName + "/";
- if (dirname.match(/\/index\/$/))
- dirname = dirname.substring(0, dirname.length - 6);
- else if (dirname === "index/") dirname = "";
- requestUrl = docUrlRoot + dirname;
- linkUrl = requestUrl;
- } else {
- // normal html builders
- requestUrl = docUrlRoot + docName + docFileSuffix;
- linkUrl = docName + docLinkSuffix;
- }
- let linkEl = listItem.appendChild(document.createElement("a"));
- linkEl.href = linkUrl + anchor;
- linkEl.dataset.score = score;
- linkEl.innerHTML = title;
- if (descr)
- listItem.appendChild(document.createElement("span")).innerHTML =
- " (" + descr + ")";
- else if (showSearchSummary)
- fetch(requestUrl)
- .then((responseData) => responseData.text())
- .then((data) => {
- if (data)
- listItem.appendChild(
- Search.makeSearchSummary(data, searchTerms)
- );
- });
- Search.output.appendChild(listItem);
-};
-const _finishSearch = (resultCount) => {
- Search.stopPulse();
- Search.title.innerText = _("Search Results");
- if (!resultCount)
- Search.status.innerText = Documentation.gettext(
- "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
- );
- else
- Search.status.innerText = _(
- `Search finished, found ${resultCount} page(s) matching the search query.`
- );
-};
-const _displayNextItem = (
- results,
- resultCount,
- searchTerms
-) => {
- // results left, load the summary and display it
- // this is intended to be dynamic (don't sub resultsCount)
- if (results.length) {
- _displayItem(results.pop(), searchTerms);
- setTimeout(
- () => _displayNextItem(results, resultCount, searchTerms),
- 5
- );
- }
- // search finished, update title and status message
- else _finishSearch(resultCount);
-};
-
-/**
- * Default splitQuery function. Can be overridden in ``sphinx.search`` with a
- * custom function per language.
- *
- * The regular expression works by splitting the string on consecutive characters
- * that are not Unicode letters, numbers, underscores, or emoji characters.
- * This is the same as ``\W+`` in Python, preserving the surrogate pair area.
- */
-if (typeof splitQuery === "undefined") {
- var splitQuery = (query) => query
- .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu)
- .filter(term => term) // remove remaining empty strings
-}
-
-/**
- * Search Module
- */
-const Search = {
- _index: null,
- _queued_query: null,
- _pulse_status: -1,
-
- htmlToText: (htmlString) => {
- const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html');
- htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() });
- const docContent = htmlElement.querySelector('[role="main"]');
- if (docContent !== undefined) return docContent.textContent;
- console.warn(
- "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template."
- );
- return "";
- },
-
- init: () => {
- const query = new URLSearchParams(window.location.search).get("q");
- document
- .querySelectorAll('input[name="q"]')
- .forEach((el) => (el.value = query));
- if (query) Search.performSearch(query);
- },
-
- loadIndex: (url) =>
- (document.body.appendChild(document.createElement("script")).src = url),
-
- setIndex: (index) => {
- Search._index = index;
- if (Search._queued_query !== null) {
- const query = Search._queued_query;
- Search._queued_query = null;
- Search.query(query);
- }
- },
-
- hasIndex: () => Search._index !== null,
-
- deferQuery: (query) => (Search._queued_query = query),
-
- stopPulse: () => (Search._pulse_status = -1),
-
- startPulse: () => {
- if (Search._pulse_status >= 0) return;
-
- const pulse = () => {
- Search._pulse_status = (Search._pulse_status + 1) % 4;
- Search.dots.innerText = ".".repeat(Search._pulse_status);
- if (Search._pulse_status >= 0) window.setTimeout(pulse, 500);
- };
- pulse();
- },
-
- /**
- * perform a search for something (or wait until index is loaded)
- */
- performSearch: (query) => {
- // create the required interface elements
- const searchText = document.createElement("h2");
- searchText.textContent = _("Searching");
- const searchSummary = document.createElement("p");
- searchSummary.classList.add("search-summary");
- searchSummary.innerText = "";
- const searchList = document.createElement("ul");
- searchList.classList.add("search");
-
- const out = document.getElementById("search-results");
- Search.title = out.appendChild(searchText);
- Search.dots = Search.title.appendChild(document.createElement("span"));
- Search.status = out.appendChild(searchSummary);
- Search.output = out.appendChild(searchList);
-
- const searchProgress = document.getElementById("search-progress");
- // Some themes don't use the search progress node
- if (searchProgress) {
- searchProgress.innerText = _("Preparing search...");
- }
- Search.startPulse();
-
- // index already loaded, the browser was quick!
- if (Search.hasIndex()) Search.query(query);
- else Search.deferQuery(query);
- },
-
- /**
- * execute search (requires search index to be loaded)
- */
- query: (query) => {
- const filenames = Search._index.filenames;
- const docNames = Search._index.docnames;
- const titles = Search._index.titles;
- const allTitles = Search._index.alltitles;
- const indexEntries = Search._index.indexentries;
-
- // stem the search terms and add them to the correct list
- const stemmer = new Stemmer();
- const searchTerms = new Set();
- const excludedTerms = new Set();
- const highlightTerms = new Set();
- const objectTerms = new Set(splitQuery(query.toLowerCase().trim()));
- splitQuery(query.trim()).forEach((queryTerm) => {
- const queryTermLower = queryTerm.toLowerCase();
-
- // maybe skip this "word"
- // stopwords array is from language_data.js
- if (
- stopwords.indexOf(queryTermLower) !== -1 ||
- queryTerm.match(/^\d+$/)
- )
- return;
-
- // stem the word
- let word = stemmer.stemWord(queryTermLower);
- // select the correct list
- if (word[0] === "-") excludedTerms.add(word.substr(1));
- else {
- searchTerms.add(word);
- highlightTerms.add(queryTermLower);
- }
- });
-
- if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js
- localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" "))
- }
-
- // console.debug("SEARCH: searching for:");
- // console.info("required: ", [...searchTerms]);
- // console.info("excluded: ", [...excludedTerms]);
-
- // array of [docname, title, anchor, descr, score, filename]
- let results = [];
- _removeChildren(document.getElementById("search-progress"));
-
- const queryLower = query.toLowerCase();
- for (const [title, foundTitles] of Object.entries(allTitles)) {
- if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) {
- for (const [file, id] of foundTitles) {
- let score = Math.round(100 * queryLower.length / title.length)
- results.push([
- docNames[file],
- titles[file] !== title ? `${titles[file]} > ${title}` : title,
- id !== null ? "#" + id : "",
- null,
- score,
- filenames[file],
- ]);
- }
- }
- }
-
- // search for explicit entries in index directives
- for (const [entry, foundEntries] of Object.entries(indexEntries)) {
- if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) {
- for (const [file, id] of foundEntries) {
- let score = Math.round(100 * queryLower.length / entry.length)
- results.push([
- docNames[file],
- titles[file],
- id ? "#" + id : "",
- null,
- score,
- filenames[file],
- ]);
- }
- }
- }
-
- // lookup as object
- objectTerms.forEach((term) =>
- results.push(...Search.performObjectSearch(term, objectTerms))
- );
-
- // lookup as search terms in fulltext
- results.push(...Search.performTermsSearch(searchTerms, excludedTerms));
-
- // let the scorer override scores with a custom scoring function
- if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item)));
-
- // now sort the results by score (in opposite order of appearance, since the
- // display function below uses pop() to retrieve items) and then
- // alphabetically
- results.sort((a, b) => {
- const leftScore = a[4];
- const rightScore = b[4];
- if (leftScore === rightScore) {
- // same score: sort alphabetically
- const leftTitle = a[1].toLowerCase();
- const rightTitle = b[1].toLowerCase();
- if (leftTitle === rightTitle) return 0;
- return leftTitle > rightTitle ? -1 : 1; // inverted is intentional
- }
- return leftScore > rightScore ? 1 : -1;
- });
-
- // remove duplicate search results
- // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
- let seen = new Set();
- results = results.reverse().reduce((acc, result) => {
- let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(',');
- if (!seen.has(resultStr)) {
- acc.push(result);
- seen.add(resultStr);
- }
- return acc;
- }, []);
-
- results = results.reverse();
-
- // for debugging
- //Search.lastresults = results.slice(); // a copy
- // console.info("search results:", Search.lastresults);
-
- // print the results
- _displayNextItem(results, results.length, searchTerms);
- },
-
- /**
- * search for object names
- */
- performObjectSearch: (object, objectTerms) => {
- const filenames = Search._index.filenames;
- const docNames = Search._index.docnames;
- const objects = Search._index.objects;
- const objNames = Search._index.objnames;
- const titles = Search._index.titles;
-
- const results = [];
-
- const objectSearchCallback = (prefix, match) => {
- const name = match[4]
- const fullname = (prefix ? prefix + "." : "") + name;
- const fullnameLower = fullname.toLowerCase();
- if (fullnameLower.indexOf(object) < 0) return;
-
- let score = 0;
- const parts = fullnameLower.split(".");
-
- // check for different match types: exact matches of full name or
- // "last name" (i.e. last dotted part)
- if (fullnameLower === object || parts.slice(-1)[0] === object)
- score += Scorer.objNameMatch;
- else if (parts.slice(-1)[0].indexOf(object) > -1)
- score += Scorer.objPartialMatch; // matches in last name
-
- const objName = objNames[match[1]][2];
- const title = titles[match[0]];
-
- // If more than one term searched for, we require other words to be
- // found in the name/title/description
- const otherTerms = new Set(objectTerms);
- otherTerms.delete(object);
- if (otherTerms.size > 0) {
- const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase();
- if (
- [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)
- )
- return;
- }
-
- let anchor = match[3];
- if (anchor === "") anchor = fullname;
- else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname;
-
- const descr = objName + _(", in ") + title;
-
- // add custom score for some objects according to scorer
- if (Scorer.objPrio.hasOwnProperty(match[2]))
- score += Scorer.objPrio[match[2]];
- else score += Scorer.objPrioDefault;
-
- results.push([
- docNames[match[0]],
- fullname,
- "#" + anchor,
- descr,
- score,
- filenames[match[0]],
- ]);
- };
- Object.keys(objects).forEach((prefix) =>
- objects[prefix].forEach((array) =>
- objectSearchCallback(prefix, array)
- )
- );
- return results;
- },
-
- /**
- * search for full-text terms in the index
- */
- performTermsSearch: (searchTerms, excludedTerms) => {
- // prepare search
- const terms = Search._index.terms;
- const titleTerms = Search._index.titleterms;
- const filenames = Search._index.filenames;
- const docNames = Search._index.docnames;
- const titles = Search._index.titles;
-
- const scoreMap = new Map();
- const fileMap = new Map();
-
- // perform the search on the required terms
- searchTerms.forEach((word) => {
- const files = [];
- const arr = [
- { files: terms[word], score: Scorer.term },
- { files: titleTerms[word], score: Scorer.title },
- ];
- // add support for partial matches
- if (word.length > 2) {
- const escapedWord = _escapeRegExp(word);
- Object.keys(terms).forEach((term) => {
- if (term.match(escapedWord) && !terms[word])
- arr.push({ files: terms[term], score: Scorer.partialTerm });
- });
- Object.keys(titleTerms).forEach((term) => {
- if (term.match(escapedWord) && !titleTerms[word])
- arr.push({ files: titleTerms[word], score: Scorer.partialTitle });
- });
- }
-
- // no match but word was a required one
- if (arr.every((record) => record.files === undefined)) return;
-
- // found search word in contents
- arr.forEach((record) => {
- if (record.files === undefined) return;
-
- let recordFiles = record.files;
- if (recordFiles.length === undefined) recordFiles = [recordFiles];
- files.push(...recordFiles);
-
- // set score for the word in each file
- recordFiles.forEach((file) => {
- if (!scoreMap.has(file)) scoreMap.set(file, {});
- scoreMap.get(file)[word] = record.score;
- });
- });
-
- // create the mapping
- files.forEach((file) => {
- if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1)
- fileMap.get(file).push(word);
- else fileMap.set(file, [word]);
- });
- });
-
- // now check if the files don't contain excluded terms
- const results = [];
- for (const [file, wordList] of fileMap) {
- // check if all requirements are matched
-
- // as search terms with length < 3 are discarded
- const filteredTermCount = [...searchTerms].filter(
- (term) => term.length > 2
- ).length;
- if (
- wordList.length !== searchTerms.size &&
- wordList.length !== filteredTermCount
- )
- continue;
-
- // ensure that none of the excluded terms is in the search result
- if (
- [...excludedTerms].some(
- (term) =>
- terms[term] === file ||
- titleTerms[term] === file ||
- (terms[term] || []).includes(file) ||
- (titleTerms[term] || []).includes(file)
- )
- )
- break;
-
- // select one (max) score for the file.
- const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w]));
- // add result to the result list
- results.push([
- docNames[file],
- titles[file],
- "",
- null,
- score,
- filenames[file],
- ]);
- }
- return results;
- },
-
- /**
- * helper function to return a node containing the
- * search summary for a given text. keywords is a list
- * of stemmed words.
- */
- makeSearchSummary: (htmlText, keywords) => {
- const text = Search.htmlToText(htmlText);
- if (text === "") return null;
-
- const textLower = text.toLowerCase();
- const actualStartPosition = [...keywords]
- .map((k) => textLower.indexOf(k.toLowerCase()))
- .filter((i) => i > -1)
- .slice(-1)[0];
- const startWithContext = Math.max(actualStartPosition - 120, 0);
-
- const top = startWithContext === 0 ? "" : "...";
- const tail = startWithContext + 240 < text.length ? "..." : "";
-
- let summary = document.createElement("p");
- summary.classList.add("context");
- summary.textContent = top + text.substr(startWithContext, 240).trim() + tail;
-
- return summary;
- },
-};
-
-_ready(Search.init);
diff --git a/latest/_static/shibuya.css b/latest/_static/shibuya.css
deleted file mode 100644
index 87873c8d..00000000
--- a/latest/_static/shibuya.css
+++ /dev/null
@@ -1 +0,0 @@
-/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.collapse{visibility:collapse}.order-last{order:9999}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mr-3{margin-right:.75rem}.block{display:block}.flex{display:flex}.table{display:table}.contents{display:contents}.hidden{display:none}.w-64{width:16rem}.w-8{width:2rem}.w-full{width:100%}.min-w-0{min-width:0}.max-w-6xl{max-width:72rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-x-1{--tw-translate-x:-0.25rem}.-translate-x-1,.-translate-x-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-2{--tw-translate-x:-0.5rem}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pr-3{padding-right:.75rem}.pt-12{padding-top:3rem}.pt-6{padding-top:1.5rem}.pt-8{padding-top:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-sm{font-size:.875rem;line-height:1.25rem}@font-face{font-family:Twemoji Country Flags;unicode-range:u+1f1e6-1f1ff,u+1f3f4,u+e0062-e0063,u+e0065,u+e0067,u+e006c,u+e006e,u+e0073-e0074,u+e0077,u+e007f;src:url(https://cdn.jsdelivr.net/npm/country-flag-emoji-polyfill@0.1/dist/TwemojiCountryFlags.woff2) format("woff2")}::-moz-selection{color:var(--accent-a11);background-color:var(--accent-a3)}::selection{color:var(--accent-a11);background-color:var(--accent-a3)}html{scroll-behavior:smooth}body{font-family:var(--sy-f-text);color:var(--sy-c-text)}.win{font-family:"Twemoji Country Flags",var(--sy-f-text)}h1,h2,h3,h4,h5{color:var(--sy-c-heading);font-family:var(--sy-f-heading)}em,strong{color:var(--sy-c-bold)}.sy-container{max-width:90rem}.sy-scrollbar{overflow-y:auto;scrollbar-gutter:stable}.sy-scrollbar::-webkit-scrollbar{height:.75rem;width:.75rem}.sy-scrollbar::-webkit-scrollbar-thumb{border-radius:10px}.sy-scrollbar::-webkit-scrollbar-track{background-color:initial}.sy-scrollbar:hover::-webkit-scrollbar-thumb{background-color:var(--gray-a3);background-clip:content-box;border:3px solid #0000}.i-icon,.i-lucide,.i-simpleicons{-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;width:1em;height:1em;display:inline-block;vertical-align:middle;font-style:normal;background-color:currentColor}.theme-switch .theme-icon,[data-color-mode=auto] .theme-switch .theme-icon{--icon-url:var(--lucide-laptop-url)}[data-color-mode=light] .theme-switch .theme-icon{--icon-url:var(--lucide-sun-url)}[data-color-mode=dark] .theme-switch .theme-icon{--icon-url:var(--lucide-moon-url)}.light,.light-theme,:root{--tomato-1:#fffcfc;--tomato-2:#fff8f7;--tomato-3:#feebe7;--tomato-4:#ffdcd3;--tomato-5:#ffcdc2;--tomato-6:#fdbdaf;--tomato-7:#f5a898;--tomato-8:#ec8e7b;--tomato-9:#e54d2e;--tomato-10:#dd4425;--tomato-11:#d13415;--tomato-12:#5c271f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--tomato-1:color(display-p3 0.998 0.989 0.988);--tomato-2:color(display-p3 0.994 0.974 0.969);--tomato-3:color(display-p3 0.985 0.924 0.909);--tomato-4:color(display-p3 0.996 0.868 0.835);--tomato-5:color(display-p3 0.98 0.812 0.77);--tomato-6:color(display-p3 0.953 0.75 0.698);--tomato-7:color(display-p3 0.917 0.673 0.611);--tomato-8:color(display-p3 0.875 0.575 0.502);--tomato-9:color(display-p3 0.831 0.345 0.231);--tomato-10:color(display-p3 0.802 0.313 0.2);--tomato-11:color(display-p3 0.755 0.259 0.152);--tomato-12:color(display-p3 0.335 0.165 0.132)}}}.dark,.dark-theme{--tomato-1:#181111;--tomato-2:#1f1513;--tomato-3:#391714;--tomato-4:#4e1511;--tomato-5:#5e1c16;--tomato-6:#6e2920;--tomato-7:#853a2d;--tomato-8:#ac4d39;--tomato-9:#e54d2e;--tomato-10:#ec6142;--tomato-11:#ff977d;--tomato-12:#fbd3cb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--tomato-1:color(display-p3 0.09 0.068 0.067);--tomato-2:color(display-p3 0.115 0.084 0.076);--tomato-3:color(display-p3 0.205 0.097 0.083);--tomato-4:color(display-p3 0.282 0.099 0.077);--tomato-5:color(display-p3 0.339 0.129 0.101);--tomato-6:color(display-p3 0.398 0.179 0.141);--tomato-7:color(display-p3 0.487 0.245 0.194);--tomato-8:color(display-p3 0.629 0.322 0.248);--tomato-9:color(display-p3 0.831 0.345 0.231);--tomato-10:color(display-p3 0.862 0.415 0.298);--tomato-11:color(display-p3 1 0.585 0.455);--tomato-12:color(display-p3 0.959 0.833 0.802)}}}.light,.light-theme,:root{--tomato-a1:#ff000003;--tomato-a2:#ff200008;--tomato-a3:#f52b0018;--tomato-a4:#ff35002c;--tomato-a5:#ff2e003d;--tomato-a6:#f92d0050;--tomato-a7:#e7280067;--tomato-a8:#db250084;--tomato-a9:#df2600d1;--tomato-a10:#d72400da;--tomato-a11:#cd2200ea;--tomato-a12:#460900e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--tomato-a1:color(display-p3 0.675 0.024 0.024/0.012);--tomato-a2:color(display-p3 0.757 0.145 0.02/0.032);--tomato-a3:color(display-p3 0.831 0.184 0.012/0.091);--tomato-a4:color(display-p3 0.976 0.192 0.004/0.165);--tomato-a5:color(display-p3 0.918 0.192 0.004/0.232);--tomato-a6:color(display-p3 0.847 0.173 0.004/0.302);--tomato-a7:color(display-p3 0.788 0.165 0.004/0.389);--tomato-a8:color(display-p3 0.749 0.153 0.004/0.499);--tomato-a9:color(display-p3 0.78 0.149 0/0.769);--tomato-a10:color(display-p3 0.757 0.141 0/0.8);--tomato-a11:color(display-p3 0.755 0.259 0.152);--tomato-a12:color(display-p3 0.335 0.165 0.132)}}}.dark,.dark-theme{--tomato-a1:#f1121208;--tomato-a2:#ff55330f;--tomato-a3:#ff35232b;--tomato-a4:#fd201142;--tomato-a5:#fe332153;--tomato-a6:#ff4f3864;--tomato-a7:#fd644a7d;--tomato-a8:#fe6d4ea7;--tomato-a9:#fe5431e4;--tomato-a10:#ff6847eb;--tomato-a11:#ff977d;--tomato-a12:#ffd6cefb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--tomato-a1:color(display-p3 0.973 0.071 0.071/0.026);--tomato-a2:color(display-p3 0.992 0.376 0.224/0.051);--tomato-a3:color(display-p3 0.996 0.282 0.176/0.148);--tomato-a4:color(display-p3 1 0.204 0.118/0.232);--tomato-a5:color(display-p3 1 0.286 0.192/0.29);--tomato-a6:color(display-p3 1 0.392 0.278/0.353);--tomato-a7:color(display-p3 1 0.459 0.349/0.45);--tomato-a8:color(display-p3 1 0.49 0.369/0.601);--tomato-a9:color(display-p3 1 0.408 0.267/0.82);--tomato-a10:color(display-p3 1 0.478 0.341/0.853);--tomato-a11:color(display-p3 1 0.585 0.455);--tomato-a12:color(display-p3 0.959 0.833 0.802)}}}.light,.light-theme,:root{--red-1:#fffcfc;--red-2:#fff7f7;--red-3:#feebec;--red-4:#ffdbdc;--red-5:#ffcdce;--red-6:#fdbdbe;--red-7:#f4a9aa;--red-8:#eb8e90;--red-9:#e5484d;--red-10:#dc3e42;--red-11:#ce2c31;--red-12:#641723}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--red-1:color(display-p3 0.998 0.989 0.988);--red-2:color(display-p3 0.995 0.971 0.971);--red-3:color(display-p3 0.985 0.925 0.925);--red-4:color(display-p3 0.999 0.866 0.866);--red-5:color(display-p3 0.984 0.812 0.811);--red-6:color(display-p3 0.955 0.751 0.749);--red-7:color(display-p3 0.915 0.675 0.672);--red-8:color(display-p3 0.872 0.575 0.572);--red-9:color(display-p3 0.83 0.329 0.324);--red-10:color(display-p3 0.798 0.294 0.285);--red-11:color(display-p3 0.744 0.234 0.222);--red-12:color(display-p3 0.36 0.115 0.143)}}}.dark,.dark-theme{--red-1:#191111;--red-2:#201314;--red-3:#3b1219;--red-4:#500f1c;--red-5:#611623;--red-6:#72232d;--red-7:#8c333a;--red-8:#b54548;--red-9:#e5484d;--red-10:#ec5d5e;--red-11:#ff9592;--red-12:#ffd1d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--red-1:color(display-p3 0.093 0.068 0.067);--red-2:color(display-p3 0.118 0.077 0.079);--red-3:color(display-p3 0.211 0.081 0.099);--red-4:color(display-p3 0.287 0.079 0.113);--red-5:color(display-p3 0.348 0.11 0.142);--red-6:color(display-p3 0.414 0.16 0.183);--red-7:color(display-p3 0.508 0.224 0.236);--red-8:color(display-p3 0.659 0.298 0.297);--red-9:color(display-p3 0.83 0.329 0.324);--red-10:color(display-p3 0.861 0.403 0.387);--red-11:color(display-p3 1 0.57 0.55);--red-12:color(display-p3 0.971 0.826 0.852)}}}.light,.light-theme,:root{--red-a1:#ff000003;--red-a2:#ff000008;--red-a3:#f3000d14;--red-a4:#ff000824;--red-a5:#ff000632;--red-a6:#f8000442;--red-a7:#df000356;--red-a8:#d2000571;--red-a9:#db0007b7;--red-a10:#d10005c1;--red-a11:#c40006d3;--red-a12:#55000de8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--red-a1:color(display-p3 0.675 0.024 0.024/0.012);--red-a2:color(display-p3 0.863 0.024 0.024/0.028);--red-a3:color(display-p3 0.792 0.008 0.008/0.075);--red-a4:color(display-p3 1 0.008 0.008/0.134);--red-a5:color(display-p3 0.918 0.008 0.008/0.189);--red-a6:color(display-p3 0.831 0.02 0.004/0.251);--red-a7:color(display-p3 0.741 0.016 0.004/0.33);--red-a8:color(display-p3 0.698 0.012 0.004/0.428);--red-a9:color(display-p3 0.749 0.008 0/0.675);--red-a10:color(display-p3 0.714 0.012 0/0.714);--red-a11:color(display-p3 0.744 0.234 0.222);--red-a12:color(display-p3 0.36 0.115 0.143)}}}.dark,.dark-theme{--red-a1:#f4121209;--red-a2:#f22f3e11;--red-a3:#ff173f2d;--red-a4:#fe0a3b44;--red-a5:#ff204756;--red-a6:#ff3e5668;--red-a7:#ff536184;--red-a8:#ff5d61b0;--red-a9:#fe4e54e4;--red-a10:#ff6465eb;--red-a11:#ff9592;--red-a12:#ffd1d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--red-a1:color(display-p3 0.984 0.071 0.071/0.03);--red-a2:color(display-p3 0.996 0.282 0.282/0.055);--red-a3:color(display-p3 1 0.169 0.271/0.156);--red-a4:color(display-p3 1 0.118 0.267/0.236);--red-a5:color(display-p3 1 0.212 0.314/0.303);--red-a6:color(display-p3 1 0.318 0.38/0.374);--red-a7:color(display-p3 1 0.4 0.424/0.475);--red-a8:color(display-p3 1 0.431 0.431/0.635);--red-a9:color(display-p3 1 0.388 0.384/0.82);--red-a10:color(display-p3 1 0.463 0.447/0.853);--red-a11:color(display-p3 1 0.57 0.55);--red-a12:color(display-p3 0.971 0.826 0.852)}}}.light,.light-theme,:root{--ruby-1:#fffcfd;--ruby-2:#fff7f8;--ruby-3:#feeaed;--ruby-4:#ffdce1;--ruby-5:#ffced6;--ruby-6:#f8bfc8;--ruby-7:#efacb8;--ruby-8:#e592a3;--ruby-9:#e54666;--ruby-10:#dc3b5d;--ruby-11:#ca244d;--ruby-12:#64172b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--ruby-1:color(display-p3 0.998 0.989 0.992);--ruby-2:color(display-p3 0.995 0.971 0.974);--ruby-3:color(display-p3 0.983 0.92 0.928);--ruby-4:color(display-p3 0.987 0.869 0.885);--ruby-5:color(display-p3 0.968 0.817 0.839);--ruby-6:color(display-p3 0.937 0.758 0.786);--ruby-7:color(display-p3 0.897 0.685 0.721);--ruby-8:color(display-p3 0.851 0.588 0.639);--ruby-9:color(display-p3 0.83 0.323 0.408);--ruby-10:color(display-p3 0.795 0.286 0.375);--ruby-11:color(display-p3 0.728 0.211 0.311);--ruby-12:color(display-p3 0.36 0.115 0.171)}}}.dark,.dark-theme{--ruby-1:#191113;--ruby-2:#1e1517;--ruby-3:#3a141e;--ruby-4:#4e1325;--ruby-5:#5e1a2e;--ruby-6:#6f2539;--ruby-7:#883447;--ruby-8:#b3445a;--ruby-9:#e54666;--ruby-10:#ec5a72;--ruby-11:#ff949d;--ruby-12:#fed2e1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--ruby-1:color(display-p3 0.093 0.068 0.074);--ruby-2:color(display-p3 0.113 0.083 0.089);--ruby-3:color(display-p3 0.208 0.088 0.117);--ruby-4:color(display-p3 0.279 0.092 0.147);--ruby-5:color(display-p3 0.337 0.12 0.18);--ruby-6:color(display-p3 0.401 0.166 0.223);--ruby-7:color(display-p3 0.495 0.224 0.281);--ruby-8:color(display-p3 0.652 0.295 0.359);--ruby-9:color(display-p3 0.83 0.323 0.408);--ruby-10:color(display-p3 0.857 0.392 0.455);--ruby-11:color(display-p3 1 0.57 0.59);--ruby-12:color(display-p3 0.968 0.83 0.88)}}}.light,.light-theme,:root{--ruby-a1:#ff005503;--ruby-a2:#ff002008;--ruby-a3:#f3002515;--ruby-a4:#ff002523;--ruby-a5:#ff002a31;--ruby-a6:#e4002440;--ruby-a7:#ce002553;--ruby-a8:#c300286d;--ruby-a9:#db002cb9;--ruby-a10:#d2002cc4;--ruby-a11:#c10030db;--ruby-a12:#550016e8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--ruby-a1:color(display-p3 0.675 0.024 0.349/0.012);--ruby-a2:color(display-p3 0.863 0.024 0.024/0.028);--ruby-a3:color(display-p3 0.804 0.008 0.11/0.079);--ruby-a4:color(display-p3 0.91 0.008 0.125/0.13);--ruby-a5:color(display-p3 0.831 0.004 0.133/0.185);--ruby-a6:color(display-p3 0.745 0.004 0.118/0.244);--ruby-a7:color(display-p3 0.678 0.004 0.114/0.314);--ruby-a8:color(display-p3 0.639 0.004 0.125/0.412);--ruby-a9:color(display-p3 0.753 0 0.129/0.679);--ruby-a10:color(display-p3 0.714 0 0.125/0.714);--ruby-a11:color(display-p3 0.728 0.211 0.311);--ruby-a12:color(display-p3 0.36 0.115 0.171)}}}.dark,.dark-theme{--ruby-a1:#f4124a09;--ruby-a2:#fe5a7f0e;--ruby-a3:#ff235d2c;--ruby-a4:#fd195e42;--ruby-a5:#fe2d6b53;--ruby-a6:#ff447665;--ruby-a7:#ff577d80;--ruby-a8:#ff5c7cae;--ruby-a9:#fe4c70e4;--ruby-a10:#ff617beb;--ruby-a11:#ff949d;--ruby-a12:#ffd3e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--ruby-a1:color(display-p3 0.984 0.071 0.329/0.03);--ruby-a2:color(display-p3 0.992 0.376 0.529/0.051);--ruby-a3:color(display-p3 0.996 0.196 0.404/0.152);--ruby-a4:color(display-p3 1 0.173 0.416/0.227);--ruby-a5:color(display-p3 1 0.259 0.459/0.29);--ruby-a6:color(display-p3 1 0.341 0.506/0.358);--ruby-a7:color(display-p3 1 0.412 0.541/0.458);--ruby-a8:color(display-p3 1 0.431 0.537/0.627);--ruby-a9:color(display-p3 1 0.376 0.482/0.82);--ruby-a10:color(display-p3 1 0.447 0.522/0.849);--ruby-a11:color(display-p3 1 0.57 0.59);--ruby-a12:color(display-p3 0.968 0.83 0.88)}}}.light,.light-theme,:root{--crimson-1:#fffcfd;--crimson-2:#fef7f9;--crimson-3:#ffe9f0;--crimson-4:#fedce7;--crimson-5:#facedd;--crimson-6:#f3bed1;--crimson-7:#eaacc3;--crimson-8:#e093b2;--crimson-9:#e93d82;--crimson-10:#df3478;--crimson-11:#cb1d63;--crimson-12:#621639}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--crimson-1:color(display-p3 0.998 0.989 0.992);--crimson-2:color(display-p3 0.991 0.969 0.976);--crimson-3:color(display-p3 0.987 0.917 0.941);--crimson-4:color(display-p3 0.975 0.866 0.904);--crimson-5:color(display-p3 0.953 0.813 0.864);--crimson-6:color(display-p3 0.921 0.755 0.817);--crimson-7:color(display-p3 0.88 0.683 0.761);--crimson-8:color(display-p3 0.834 0.592 0.694);--crimson-9:color(display-p3 0.843 0.298 0.507);--crimson-10:color(display-p3 0.807 0.266 0.468);--crimson-11:color(display-p3 0.731 0.195 0.388);--crimson-12:color(display-p3 0.352 0.111 0.221)}}}.dark,.dark-theme{--crimson-1:#191114;--crimson-2:#201318;--crimson-3:#381525;--crimson-4:#4d122f;--crimson-5:#5c1839;--crimson-6:#6d2545;--crimson-7:#873356;--crimson-8:#b0436e;--crimson-9:#e93d82;--crimson-10:#ee518a;--crimson-11:#ff92ad;--crimson-12:#fdd3e8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--crimson-1:color(display-p3 0.093 0.068 0.078);--crimson-2:color(display-p3 0.117 0.078 0.095);--crimson-3:color(display-p3 0.203 0.091 0.143);--crimson-4:color(display-p3 0.277 0.087 0.182);--crimson-5:color(display-p3 0.332 0.115 0.22);--crimson-6:color(display-p3 0.394 0.162 0.268);--crimson-7:color(display-p3 0.489 0.222 0.336);--crimson-8:color(display-p3 0.638 0.289 0.429);--crimson-9:color(display-p3 0.843 0.298 0.507);--crimson-10:color(display-p3 0.864 0.364 0.539);--crimson-11:color(display-p3 1 0.56 0.66);--crimson-12:color(display-p3 0.966 0.834 0.906)}}}.light,.light-theme,:root{--crimson-a1:#ff005503;--crimson-a2:#e0004008;--crimson-a3:#ff005216;--crimson-a4:#f8005123;--crimson-a5:#e5004f31;--crimson-a6:#d0004b41;--crimson-a7:#bf004753;--crimson-a8:#b6004a6c;--crimson-a9:#e2005bc2;--crimson-a10:#d70056cb;--crimson-a11:#c4004fe2;--crimson-a12:#530026e9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--crimson-a1:color(display-p3 0.675 0.024 0.349/0.012);--crimson-a2:color(display-p3 0.757 0.02 0.267/0.032);--crimson-a3:color(display-p3 0.859 0.008 0.294/0.083);--crimson-a4:color(display-p3 0.827 0.008 0.298/0.134);--crimson-a5:color(display-p3 0.753 0.008 0.275/0.189);--crimson-a6:color(display-p3 0.682 0.004 0.247/0.244);--crimson-a7:color(display-p3 0.62 0.004 0.251/0.318);--crimson-a8:color(display-p3 0.6 0.004 0.251/0.408);--crimson-a9:color(display-p3 0.776 0 0.298/0.702);--crimson-a10:color(display-p3 0.737 0 0.275/0.734);--crimson-a11:color(display-p3 0.731 0.195 0.388);--crimson-a12:color(display-p3 0.352 0.111 0.221)}}}.dark,.dark-theme{--crimson-a1:#f4126709;--crimson-a2:#f22f7a11;--crimson-a3:#fe2a8b2a;--crimson-a4:#fd158741;--crimson-a5:#fd278f51;--crimson-a6:#fe459763;--crimson-a7:#fd559b7f;--crimson-a8:#fe5b9bab;--crimson-a9:#fe418de8;--crimson-a10:#ff5693ed;--crimson-a11:#ff92ad;--crimson-a12:#ffd5eafd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--crimson-a1:color(display-p3 0.984 0.071 0.463/0.03);--crimson-a2:color(display-p3 0.996 0.282 0.569/0.055);--crimson-a3:color(display-p3 0.996 0.227 0.573/0.148);--crimson-a4:color(display-p3 1 0.157 0.569/0.227);--crimson-a5:color(display-p3 1 0.231 0.604/0.286);--crimson-a6:color(display-p3 1 0.337 0.643/0.349);--crimson-a7:color(display-p3 1 0.416 0.663/0.454);--crimson-a8:color(display-p3 0.996 0.427 0.651/0.614);--crimson-a9:color(display-p3 1 0.345 0.596/0.832);--crimson-a10:color(display-p3 1 0.42 0.62/0.853);--crimson-a11:color(display-p3 1 0.56 0.66);--crimson-a12:color(display-p3 0.966 0.834 0.906)}}}.light,.light-theme,:root{--pink-1:#fffcfe;--pink-2:#fef7fb;--pink-3:#fee9f5;--pink-4:#fbdcef;--pink-5:#f6cee7;--pink-6:#efbfdd;--pink-7:#e7acd0;--pink-8:#dd93c2;--pink-9:#d6409f;--pink-10:#cf3897;--pink-11:#c2298a;--pink-12:#651249}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--pink-1:color(display-p3 0.998 0.989 0.996);--pink-2:color(display-p3 0.992 0.97 0.985);--pink-3:color(display-p3 0.981 0.917 0.96);--pink-4:color(display-p3 0.963 0.867 0.932);--pink-5:color(display-p3 0.939 0.815 0.899);--pink-6:color(display-p3 0.907 0.756 0.859);--pink-7:color(display-p3 0.869 0.683 0.81);--pink-8:color(display-p3 0.825 0.59 0.751);--pink-9:color(display-p3 0.775 0.297 0.61);--pink-10:color(display-p3 0.748 0.27 0.581);--pink-11:color(display-p3 0.698 0.219 0.528);--pink-12:color(display-p3 0.363 0.101 0.279)}}}.dark,.dark-theme{--pink-1:#191117;--pink-2:#21121d;--pink-3:#37172f;--pink-4:#4b143d;--pink-5:#591c47;--pink-6:#692955;--pink-7:#833869;--pink-8:#a84885;--pink-9:#d6409f;--pink-10:#de51a8;--pink-11:#ff8dcc;--pink-12:#fdd1ea}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--pink-1:color(display-p3 0.093 0.068 0.089);--pink-2:color(display-p3 0.121 0.073 0.11);--pink-3:color(display-p3 0.198 0.098 0.179);--pink-4:color(display-p3 0.271 0.095 0.231);--pink-5:color(display-p3 0.32 0.127 0.273);--pink-6:color(display-p3 0.382 0.177 0.326);--pink-7:color(display-p3 0.477 0.238 0.405);--pink-8:color(display-p3 0.612 0.304 0.51);--pink-9:color(display-p3 0.775 0.297 0.61);--pink-10:color(display-p3 0.808 0.356 0.645);--pink-11:color(display-p3 1 0.535 0.78);--pink-12:color(display-p3 0.964 0.826 0.912)}}}.light,.light-theme,:root{--pink-a1:#ff00aa03;--pink-a2:#e0008008;--pink-a3:#f4008c16;--pink-a4:#e2008b23;--pink-a5:#d1008331;--pink-a6:#c0007840;--pink-a7:#b6006f53;--pink-a8:#af006f6c;--pink-a9:#c8007fbf;--pink-a10:#c2007ac7;--pink-a11:#b60074d6;--pink-a12:#59003bed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--pink-a1:color(display-p3 0.675 0.024 0.675/0.012);--pink-a2:color(display-p3 0.757 0.02 0.51/0.032);--pink-a3:color(display-p3 0.765 0.008 0.529/0.083);--pink-a4:color(display-p3 0.737 0.008 0.506/0.134);--pink-a5:color(display-p3 0.663 0.004 0.451/0.185);--pink-a6:color(display-p3 0.616 0.004 0.424/0.244);--pink-a7:color(display-p3 0.596 0.004 0.412/0.318);--pink-a8:color(display-p3 0.573 0.004 0.404/0.412);--pink-a9:color(display-p3 0.682 0 0.447/0.702);--pink-a10:color(display-p3 0.655 0 0.424/0.73);--pink-a11:color(display-p3 0.698 0.219 0.528);--pink-a12:color(display-p3 0.363 0.101 0.279)}}}.dark,.dark-theme{--pink-a1:#f412bc09;--pink-a2:#f420bb12;--pink-a3:#fe37cc29;--pink-a4:#fc1ec43f;--pink-a5:#fd35c24e;--pink-a6:#fd51c75f;--pink-a7:#fd62c87b;--pink-a8:#ff68c8a2;--pink-a9:#fe49bcd4;--pink-a10:#ff5cc0dc;--pink-a11:#ff8dcc;--pink-a12:#ffd3ecfd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--pink-a1:color(display-p3 0.984 0.071 0.855/0.03);--pink-a2:color(display-p3 1 0.2 0.8/0.059);--pink-a3:color(display-p3 1 0.294 0.886/0.139);--pink-a4:color(display-p3 1 0.192 0.82/0.219);--pink-a5:color(display-p3 1 0.282 0.827/0.274);--pink-a6:color(display-p3 1 0.396 0.835/0.337);--pink-a7:color(display-p3 1 0.459 0.831/0.442);--pink-a8:color(display-p3 1 0.478 0.827/0.585);--pink-a9:color(display-p3 1 0.373 0.784/0.761);--pink-a10:color(display-p3 1 0.435 0.792/0.795);--pink-a11:color(display-p3 1 0.535 0.78);--pink-a12:color(display-p3 0.964 0.826 0.912)}}}.light,.light-theme,:root{--plum-1:#fefcff;--plum-2:#fdf7fd;--plum-3:#fbebfb;--plum-4:#f7def8;--plum-5:#f2d1f3;--plum-6:#e9c2ec;--plum-7:#deade3;--plum-8:#cf91d8;--plum-9:#ab4aba;--plum-10:#a144af;--plum-11:#953ea3;--plum-12:#53195d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--plum-1:color(display-p3 0.995 0.988 0.999);--plum-2:color(display-p3 0.988 0.971 0.99);--plum-3:color(display-p3 0.973 0.923 0.98);--plum-4:color(display-p3 0.953 0.875 0.966);--plum-5:color(display-p3 0.926 0.825 0.945);--plum-6:color(display-p3 0.89 0.765 0.916);--plum-7:color(display-p3 0.84 0.686 0.877);--plum-8:color(display-p3 0.775 0.58 0.832);--plum-9:color(display-p3 0.624 0.313 0.708);--plum-10:color(display-p3 0.587 0.29 0.667);--plum-11:color(display-p3 0.543 0.263 0.619);--plum-12:color(display-p3 0.299 0.114 0.352)}}}.dark,.dark-theme{--plum-1:#181118;--plum-2:#201320;--plum-3:#351a35;--plum-4:#451d47;--plum-5:#512454;--plum-6:#5e3061;--plum-7:#734079;--plum-8:#92549c;--plum-9:#ab4aba;--plum-10:#b658c4;--plum-11:#e796f3;--plum-12:#f4d4f4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--plum-1:color(display-p3 0.09 0.068 0.092);--plum-2:color(display-p3 0.118 0.077 0.121);--plum-3:color(display-p3 0.192 0.105 0.202);--plum-4:color(display-p3 0.25 0.121 0.271);--plum-5:color(display-p3 0.293 0.152 0.319);--plum-6:color(display-p3 0.343 0.198 0.372);--plum-7:color(display-p3 0.424 0.262 0.461);--plum-8:color(display-p3 0.54 0.341 0.595);--plum-9:color(display-p3 0.624 0.313 0.708);--plum-10:color(display-p3 0.666 0.365 0.748);--plum-11:color(display-p3 0.86 0.602 0.933);--plum-12:color(display-p3 0.936 0.836 0.949)}}}.light,.light-theme,:root{--plum-a1:#aa00ff03;--plum-a2:#c000c008;--plum-a3:#cc00cc14;--plum-a4:#c200c921;--plum-a5:#b700bd2e;--plum-a6:#a400b03d;--plum-a7:#9900a852;--plum-a8:#9000a56e;--plum-a9:#89009eb5;--plum-a10:#7f0092bb;--plum-a11:#730086c1;--plum-a12:#40004be6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--plum-a1:color(display-p3 0.675 0.024 1/0.012);--plum-a2:color(display-p3 0.58 0.024 0.58/0.028);--plum-a3:color(display-p3 0.655 0.008 0.753/0.079);--plum-a4:color(display-p3 0.627 0.008 0.722/0.126);--plum-a5:color(display-p3 0.58 0.004 0.69/0.177);--plum-a6:color(display-p3 0.537 0.004 0.655/0.236);--plum-a7:color(display-p3 0.49 0.004 0.616/0.314);--plum-a8:color(display-p3 0.471 0.004 0.6/0.42);--plum-a9:color(display-p3 0.451 0 0.576/0.687);--plum-a10:color(display-p3 0.42 0 0.529/0.71);--plum-a11:color(display-p3 0.543 0.263 0.619);--plum-a12:color(display-p3 0.299 0.114 0.352)}}}.dark,.dark-theme{--plum-a1:#f112f108;--plum-a2:#f22ff211;--plum-a3:#fd4cfd27;--plum-a4:#f646ff3a;--plum-a5:#f455ff48;--plum-a6:#f66dff56;--plum-a7:#f07cfd70;--plum-a8:#ee84ff95;--plum-a9:#e961feb6;--plum-a10:#ed70ffc0;--plum-a11:#f19cfef3;--plum-a12:#feddfef4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--plum-a1:color(display-p3 0.973 0.071 0.973/0.026);--plum-a2:color(display-p3 0.933 0.267 1/0.059);--plum-a3:color(display-p3 0.918 0.333 0.996/0.148);--plum-a4:color(display-p3 0.91 0.318 1/0.219);--plum-a5:color(display-p3 0.914 0.388 1/0.269);--plum-a6:color(display-p3 0.906 0.463 1/0.328);--plum-a7:color(display-p3 0.906 0.529 1/0.425);--plum-a8:color(display-p3 0.906 0.553 1/0.568);--plum-a9:color(display-p3 0.875 0.427 1/0.69);--plum-a10:color(display-p3 0.886 0.471 0.996/0.732);--plum-a11:color(display-p3 0.86 0.602 0.933);--plum-a12:color(display-p3 0.936 0.836 0.949)}}}.light,.light-theme,:root{--purple-1:#fefcfe;--purple-2:#fbf7fe;--purple-3:#f7edfe;--purple-4:#f2e2fc;--purple-5:#ead5f9;--purple-6:#e0c4f4;--purple-7:#d1afec;--purple-8:#be93e4;--purple-9:#8e4ec6;--purple-10:#8347b9;--purple-11:#8145b5;--purple-12:#402060}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--purple-1:color(display-p3 0.995 0.988 0.996);--purple-2:color(display-p3 0.983 0.971 0.993);--purple-3:color(display-p3 0.963 0.931 0.989);--purple-4:color(display-p3 0.937 0.888 0.981);--purple-5:color(display-p3 0.904 0.837 0.966);--purple-6:color(display-p3 0.86 0.774 0.942);--purple-7:color(display-p3 0.799 0.69 0.91);--purple-8:color(display-p3 0.719 0.583 0.874);--purple-9:color(display-p3 0.523 0.318 0.751);--purple-10:color(display-p3 0.483 0.289 0.7);--purple-11:color(display-p3 0.473 0.281 0.687);--purple-12:color(display-p3 0.234 0.132 0.363)}}}.dark,.dark-theme{--purple-1:#18111b;--purple-2:#1e1523;--purple-3:#301c3b;--purple-4:#3d224e;--purple-5:#48295c;--purple-6:#54346b;--purple-7:#664282;--purple-8:#8457aa;--purple-9:#8e4ec6;--purple-10:#9a5cd0;--purple-11:#d19dff;--purple-12:#ecd9fa}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--purple-1:color(display-p3 0.09 0.068 0.103);--purple-2:color(display-p3 0.113 0.082 0.134);--purple-3:color(display-p3 0.175 0.112 0.224);--purple-4:color(display-p3 0.224 0.137 0.297);--purple-5:color(display-p3 0.264 0.167 0.349);--purple-6:color(display-p3 0.311 0.208 0.406);--purple-7:color(display-p3 0.381 0.266 0.496);--purple-8:color(display-p3 0.49 0.349 0.649);--purple-9:color(display-p3 0.523 0.318 0.751);--purple-10:color(display-p3 0.57 0.373 0.791);--purple-11:color(display-p3 0.8 0.62 1);--purple-12:color(display-p3 0.913 0.854 0.971)}}}.light,.light-theme,:root{--purple-a1:#aa00aa03;--purple-a2:#8000e008;--purple-a3:#8e00f112;--purple-a4:#8d00e51d;--purple-a5:#8000db2a;--purple-a6:#7a01d03b;--purple-a7:#6d00c350;--purple-a8:#6600c06c;--purple-a9:#5c00adb1;--purple-a10:#53009eb8;--purple-a11:#52009aba;--purple-a12:#250049df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--purple-a1:color(display-p3 0.675 0.024 0.675/0.012);--purple-a2:color(display-p3 0.443 0.024 0.722/0.028);--purple-a3:color(display-p3 0.506 0.008 0.835/0.071);--purple-a4:color(display-p3 0.451 0.004 0.831/0.114);--purple-a5:color(display-p3 0.431 0.004 0.788/0.165);--purple-a6:color(display-p3 0.384 0.004 0.745/0.228);--purple-a7:color(display-p3 0.357 0.004 0.71/0.31);--purple-a8:color(display-p3 0.322 0.004 0.702/0.416);--purple-a9:color(display-p3 0.298 0 0.639/0.683);--purple-a10:color(display-p3 0.271 0 0.58/0.71);--purple-a11:color(display-p3 0.473 0.281 0.687);--purple-a12:color(display-p3 0.234 0.132 0.363)}}}.dark,.dark-theme{--purple-a1:#b412f90b;--purple-a2:#b744f714;--purple-a3:#c150ff2d;--purple-a4:#bb53fd42;--purple-a5:#be5cfd51;--purple-a6:#c16dfd61;--purple-a7:#c378fd7a;--purple-a8:#c47effa4;--purple-a9:#b661ffc2;--purple-a10:#bc6fffcd;--purple-a11:#d19dff;--purple-a12:#f1ddfffa}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--purple-a1:color(display-p3 0.686 0.071 0.996/0.038);--purple-a2:color(display-p3 0.722 0.286 0.996/0.072);--purple-a3:color(display-p3 0.718 0.349 0.996/0.169);--purple-a4:color(display-p3 0.702 0.353 1/0.248);--purple-a5:color(display-p3 0.718 0.404 1/0.303);--purple-a6:color(display-p3 0.733 0.455 1/0.366);--purple-a7:color(display-p3 0.753 0.506 1/0.458);--purple-a8:color(display-p3 0.749 0.522 1/0.622);--purple-a9:color(display-p3 0.686 0.408 1/0.736);--purple-a10:color(display-p3 0.71 0.459 1/0.778);--purple-a11:color(display-p3 0.8 0.62 1);--purple-a12:color(display-p3 0.913 0.854 0.971)}}}.light,.light-theme,:root{--violet-1:#fdfcfe;--violet-2:#faf8ff;--violet-3:#f4f0fe;--violet-4:#ebe4ff;--violet-5:#e1d9ff;--violet-6:#d4cafe;--violet-7:#c2b5f5;--violet-8:#aa99ec;--violet-9:#6e56cf;--violet-10:#654dc4;--violet-11:#6550b9;--violet-12:#2f265f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--violet-1:color(display-p3 0.991 0.988 0.995);--violet-2:color(display-p3 0.978 0.974 0.998);--violet-3:color(display-p3 0.953 0.943 0.993);--violet-4:color(display-p3 0.916 0.897 1);--violet-5:color(display-p3 0.876 0.851 1);--violet-6:color(display-p3 0.825 0.793 0.981);--violet-7:color(display-p3 0.752 0.712 0.943);--violet-8:color(display-p3 0.654 0.602 0.902);--violet-9:color(display-p3 0.417 0.341 0.784);--violet-10:color(display-p3 0.381 0.306 0.741);--violet-11:color(display-p3 0.383 0.317 0.702);--violet-12:color(display-p3 0.179 0.15 0.359)}}}.dark,.dark-theme{--violet-1:#14121f;--violet-2:#1b1525;--violet-3:#291f43;--violet-4:#33255b;--violet-5:#3c2e69;--violet-6:#473876;--violet-7:#56468b;--violet-8:#6958ad;--violet-9:#6e56cf;--violet-10:#7d66d9;--violet-11:#baa7ff;--violet-12:#e2ddfe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--violet-1:color(display-p3 0.077 0.071 0.118);--violet-2:color(display-p3 0.101 0.084 0.141);--violet-3:color(display-p3 0.154 0.123 0.256);--violet-4:color(display-p3 0.191 0.148 0.345);--violet-5:color(display-p3 0.226 0.182 0.396);--violet-6:color(display-p3 0.269 0.223 0.449);--violet-7:color(display-p3 0.326 0.277 0.53);--violet-8:color(display-p3 0.399 0.346 0.656);--violet-9:color(display-p3 0.417 0.341 0.784);--violet-10:color(display-p3 0.477 0.402 0.823);--violet-11:color(display-p3 0.72 0.65 1);--violet-12:color(display-p3 0.883 0.867 0.986)}}}.light,.light-theme,:root{--violet-a1:#5500aa03;--violet-a2:#4900ff07;--violet-a3:#4400ee0f;--violet-a4:#4300ff1b;--violet-a5:#3600ff26;--violet-a6:#3100fb35;--violet-a7:#2d01dd4a;--violet-a8:#2b00d066;--violet-a9:#2400b7a9;--violet-a10:#2300abb2;--violet-a11:#1f0099af;--violet-a12:#0b0043d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--violet-a1:color(display-p3 0.349 0.024 0.675/0.012);--violet-a2:color(display-p3 0.161 0.024 0.863/0.028);--violet-a3:color(display-p3 0.204 0.004 0.871/0.059);--violet-a4:color(display-p3 0.196 0.004 1/0.102);--violet-a5:color(display-p3 0.165 0.008 1/0.15);--violet-a6:color(display-p3 0.153 0.004 0.906/0.208);--violet-a7:color(display-p3 0.141 0.004 0.796/0.287);--violet-a8:color(display-p3 0.133 0.004 0.753/0.397);--violet-a9:color(display-p3 0.114 0 0.675/0.659);--violet-a10:color(display-p3 0.11 0 0.627/0.695);--violet-a11:color(display-p3 0.383 0.317 0.702);--violet-a12:color(display-p3 0.179 0.15 0.359)}}}.dark,.dark-theme{--violet-a1:#4422ff0f;--violet-a2:#853ff916;--violet-a3:#8354fe36;--violet-a4:#7d51fd50;--violet-a5:#845ffd5f;--violet-a6:#8f6cfd6d;--violet-a7:#9879ff83;--violet-a8:#977dfea8;--violet-a9:#8668ffcc;--violet-a10:#9176fed7;--violet-a11:#baa7ff;--violet-a12:#e3deff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--violet-a1:color(display-p3 0.282 0.141 0.996/0.055);--violet-a2:color(display-p3 0.51 0.263 1/0.08);--violet-a3:color(display-p3 0.494 0.337 0.996/0.202);--violet-a4:color(display-p3 0.49 0.345 1/0.299);--violet-a5:color(display-p3 0.525 0.392 1/0.353);--violet-a6:color(display-p3 0.569 0.455 1/0.408);--violet-a7:color(display-p3 0.588 0.494 1/0.496);--violet-a8:color(display-p3 0.596 0.51 1/0.631);--violet-a9:color(display-p3 0.522 0.424 1/0.769);--violet-a10:color(display-p3 0.576 0.482 1/0.811);--violet-a11:color(display-p3 0.72 0.65 1);--violet-a12:color(display-p3 0.883 0.867 0.986)}}}.light,.light-theme,:root{--iris-1:#fdfdff;--iris-2:#f8f8ff;--iris-3:#f0f1fe;--iris-4:#e6e7ff;--iris-5:#dadcff;--iris-6:#cbcdff;--iris-7:#b8baf8;--iris-8:#9b9ef0;--iris-9:#5b5bd6;--iris-10:#5151cd;--iris-11:#5753c6;--iris-12:#272962}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--iris-1:color(display-p3 0.992 0.992 0.999);--iris-2:color(display-p3 0.972 0.973 0.998);--iris-3:color(display-p3 0.943 0.945 0.992);--iris-4:color(display-p3 0.902 0.906 1);--iris-5:color(display-p3 0.857 0.861 1);--iris-6:color(display-p3 0.799 0.805 0.987);--iris-7:color(display-p3 0.721 0.727 0.955);--iris-8:color(display-p3 0.61 0.619 0.918);--iris-9:color(display-p3 0.357 0.357 0.81);--iris-10:color(display-p3 0.318 0.318 0.774);--iris-11:color(display-p3 0.337 0.326 0.748);--iris-12:color(display-p3 0.154 0.161 0.371)}}}.dark,.dark-theme{--iris-1:#13131e;--iris-2:#171625;--iris-3:#202248;--iris-4:#262a65;--iris-5:#303374;--iris-6:#3d3e82;--iris-7:#4a4a95;--iris-8:#5958b1;--iris-9:#5b5bd6;--iris-10:#6e6ade;--iris-11:#b1a9ff;--iris-12:#e0dffe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--iris-1:color(display-p3 0.075 0.075 0.114);--iris-2:color(display-p3 0.089 0.086 0.14);--iris-3:color(display-p3 0.128 0.134 0.272);--iris-4:color(display-p3 0.153 0.165 0.382);--iris-5:color(display-p3 0.192 0.201 0.44);--iris-6:color(display-p3 0.239 0.241 0.491);--iris-7:color(display-p3 0.291 0.289 0.565);--iris-8:color(display-p3 0.35 0.345 0.673);--iris-9:color(display-p3 0.357 0.357 0.81);--iris-10:color(display-p3 0.428 0.416 0.843);--iris-11:color(display-p3 0.685 0.662 1);--iris-12:color(display-p3 0.878 0.875 0.986)}}}.light,.light-theme,:root{--iris-a1:#0000ff02;--iris-a2:#0000ff07;--iris-a3:#0011ee0f;--iris-a4:#000bff19;--iris-a5:#000eff25;--iris-a6:#000aff34;--iris-a7:#0008e647;--iris-a8:#0008d964;--iris-a9:#0000c0a4;--iris-a10:#0000b6ae;--iris-a11:#0600abac;--iris-a12:#000246d8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--iris-a1:color(display-p3 0.02 0.02 1/0.008);--iris-a2:color(display-p3 0.024 0.024 0.863/0.028);--iris-a3:color(display-p3 0.004 0.071 0.871/0.059);--iris-a4:color(display-p3 0.012 0.051 1/0.099);--iris-a5:color(display-p3 0.008 0.035 1/0.142);--iris-a6:color(display-p3 0 0.02 0.941/0.2);--iris-a7:color(display-p3 0.004 0.02 0.847/0.279);--iris-a8:color(display-p3 0.004 0.024 0.788/0.389);--iris-a9:color(display-p3 0 0 0.706/0.644);--iris-a10:color(display-p3 0 0 0.667/0.683);--iris-a11:color(display-p3 0.337 0.326 0.748);--iris-a12:color(display-p3 0.154 0.161 0.371)}}}.dark,.dark-theme{--iris-a1:#3636fe0e;--iris-a2:#564bf916;--iris-a3:#525bff3b;--iris-a4:#4d58ff5a;--iris-a5:#5b62fd6b;--iris-a6:#6d6ffd7a;--iris-a7:#7777fe8e;--iris-a8:#7b7afeac;--iris-a9:#6a6afed4;--iris-a10:#7d79ffdc;--iris-a11:#b1a9ff;--iris-a12:#e1e0ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--iris-a1:color(display-p3 0.224 0.224 0.992/0.051);--iris-a2:color(display-p3 0.361 0.314 1/0.08);--iris-a3:color(display-p3 0.357 0.373 1/0.219);--iris-a4:color(display-p3 0.325 0.361 1/0.337);--iris-a5:color(display-p3 0.38 0.4 1/0.4);--iris-a6:color(display-p3 0.447 0.447 1/0.454);--iris-a7:color(display-p3 0.486 0.486 1/0.534);--iris-a8:color(display-p3 0.502 0.494 1/0.652);--iris-a9:color(display-p3 0.431 0.431 1/0.799);--iris-a10:color(display-p3 0.502 0.486 1/0.832);--iris-a11:color(display-p3 0.685 0.662 1);--iris-a12:color(display-p3 0.878 0.875 0.986)}}}.light,.light-theme,:root{--indigo-1:#fdfdfe;--indigo-2:#f7f9ff;--indigo-3:#edf2fe;--indigo-4:#e1e9ff;--indigo-5:#d2deff;--indigo-6:#c1d0ff;--indigo-7:#abbdf9;--indigo-8:#8da4ef;--indigo-9:#3e63dd;--indigo-10:#3358d4;--indigo-11:#3a5bc7;--indigo-12:#1f2d5c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--indigo-1:color(display-p3 0.992 0.992 0.996);--indigo-2:color(display-p3 0.971 0.977 0.998);--indigo-3:color(display-p3 0.933 0.948 0.992);--indigo-4:color(display-p3 0.885 0.914 1);--indigo-5:color(display-p3 0.831 0.87 1);--indigo-6:color(display-p3 0.767 0.814 0.995);--indigo-7:color(display-p3 0.685 0.74 0.957);--indigo-8:color(display-p3 0.569 0.639 0.916);--indigo-9:color(display-p3 0.276 0.384 0.837);--indigo-10:color(display-p3 0.234 0.343 0.801);--indigo-11:color(display-p3 0.256 0.354 0.755);--indigo-12:color(display-p3 0.133 0.175 0.348)}}}.dark,.dark-theme{--indigo-1:#11131f;--indigo-2:#141726;--indigo-3:#182449;--indigo-4:#1d2e62;--indigo-5:#253974;--indigo-6:#304384;--indigo-7:#3a4f97;--indigo-8:#435db1;--indigo-9:#3e63dd;--indigo-10:#5472e4;--indigo-11:#9eb1ff;--indigo-12:#d6e1ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--indigo-1:color(display-p3 0.068 0.074 0.118);--indigo-2:color(display-p3 0.081 0.089 0.144);--indigo-3:color(display-p3 0.105 0.141 0.275);--indigo-4:color(display-p3 0.129 0.18 0.369);--indigo-5:color(display-p3 0.163 0.22 0.439);--indigo-6:color(display-p3 0.203 0.262 0.5);--indigo-7:color(display-p3 0.245 0.309 0.575);--indigo-8:color(display-p3 0.285 0.362 0.674);--indigo-9:color(display-p3 0.276 0.384 0.837);--indigo-10:color(display-p3 0.354 0.445 0.866);--indigo-11:color(display-p3 0.63 0.69 1);--indigo-12:color(display-p3 0.848 0.881 0.99)}}}.light,.light-theme,:root{--indigo-a1:#00008002;--indigo-a2:#0040ff08;--indigo-a3:#0047f112;--indigo-a4:#0044ff1e;--indigo-a5:#0044ff2d;--indigo-a6:#003eff3e;--indigo-a7:#0037ed54;--indigo-a8:#0034dc72;--indigo-a9:#0031d2c1;--indigo-a10:#002ec9cc;--indigo-a11:#002bb7c5;--indigo-a12:#001046e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--indigo-a1:color(display-p3 0.02 0.02 0.51/0.008);--indigo-a2:color(display-p3 0.024 0.161 0.863/0.028);--indigo-a3:color(display-p3 0.008 0.239 0.886/0.067);--indigo-a4:color(display-p3 0.004 0.247 1/0.114);--indigo-a5:color(display-p3 0.004 0.235 1/0.169);--indigo-a6:color(display-p3 0.004 0.208 0.984/0.232);--indigo-a7:color(display-p3 0.004 0.176 0.863/0.314);--indigo-a8:color(display-p3 0.004 0.165 0.812/0.432);--indigo-a9:color(display-p3 0 0.153 0.773/0.726);--indigo-a10:color(display-p3 0 0.137 0.737/0.765);--indigo-a11:color(display-p3 0.256 0.354 0.755);--indigo-a12:color(display-p3 0.133 0.175 0.348)}}}.dark,.dark-theme{--indigo-a1:#1133ff0f;--indigo-a2:#3354fa17;--indigo-a3:#2f62ff3c;--indigo-a4:#3566ff57;--indigo-a5:#4171fd6b;--indigo-a6:#5178fd7c;--indigo-a7:#5a7fff90;--indigo-a8:#5b81feac;--indigo-a9:#4671ffdb;--indigo-a10:#5c7efee3;--indigo-a11:#9eb1ff;--indigo-a12:#d6e1ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--indigo-a1:color(display-p3 0.071 0.212 0.996/0.055);--indigo-a2:color(display-p3 0.251 0.345 0.988/0.085);--indigo-a3:color(display-p3 0.243 0.404 1/0.223);--indigo-a4:color(display-p3 0.263 0.42 1/0.324);--indigo-a5:color(display-p3 0.314 0.451 1/0.4);--indigo-a6:color(display-p3 0.361 0.49 1/0.467);--indigo-a7:color(display-p3 0.388 0.51 1/0.547);--indigo-a8:color(display-p3 0.404 0.518 1/0.652);--indigo-a9:color(display-p3 0.318 0.451 1/0.824);--indigo-a10:color(display-p3 0.404 0.506 1/0.858);--indigo-a11:color(display-p3 0.63 0.69 1);--indigo-a12:color(display-p3 0.848 0.881 0.99)}}}.light,.light-theme,:root{--blue-1:#fbfdff;--blue-2:#f4faff;--blue-3:#e6f4fe;--blue-4:#d5efff;--blue-5:#c2e5ff;--blue-6:#acd8fc;--blue-7:#8ec8f6;--blue-8:#5eb1ef;--blue-9:#0090ff;--blue-10:#0588f0;--blue-11:#0d74ce;--blue-12:#113264}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--blue-1:color(display-p3 0.986 0.992 0.999);--blue-2:color(display-p3 0.96 0.979 0.998);--blue-3:color(display-p3 0.912 0.956 0.991);--blue-4:color(display-p3 0.853 0.932 1);--blue-5:color(display-p3 0.788 0.894 0.998);--blue-6:color(display-p3 0.709 0.843 0.976);--blue-7:color(display-p3 0.606 0.777 0.947);--blue-8:color(display-p3 0.451 0.688 0.917);--blue-9:color(display-p3 0.247 0.556 0.969);--blue-10:color(display-p3 0.234 0.523 0.912);--blue-11:color(display-p3 0.15 0.44 0.84);--blue-12:color(display-p3 0.102 0.193 0.379)}}}.dark,.dark-theme{--blue-1:#0d1520;--blue-2:#111927;--blue-3:#0d2847;--blue-4:#003362;--blue-5:#004074;--blue-6:#104d87;--blue-7:#205d9e;--blue-8:#2870bd;--blue-9:#0090ff;--blue-10:#3b9eff;--blue-11:#70b8ff;--blue-12:#c2e6ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--blue-1:color(display-p3 0.057 0.081 0.122);--blue-2:color(display-p3 0.072 0.098 0.147);--blue-3:color(display-p3 0.078 0.154 0.27);--blue-4:color(display-p3 0.033 0.197 0.37);--blue-5:color(display-p3 0.08 0.245 0.441);--blue-6:color(display-p3 0.14 0.298 0.511);--blue-7:color(display-p3 0.195 0.361 0.6);--blue-8:color(display-p3 0.239 0.434 0.72);--blue-9:color(display-p3 0.247 0.556 0.969);--blue-10:color(display-p3 0.344 0.612 0.973);--blue-11:color(display-p3 0.49 0.72 1);--blue-12:color(display-p3 0.788 0.898 0.99)}}}.light,.light-theme,:root{--blue-a1:#0080ff04;--blue-a2:#008cff0b;--blue-a3:#008ff519;--blue-a4:#009eff2a;--blue-a5:#0093ff3d;--blue-a6:#0088f653;--blue-a7:#0083eb71;--blue-a8:#0084e6a1;--blue-a9:#0090ff;--blue-a10:#0086f0fa;--blue-a11:#006dcbf2;--blue-a12:#002359ee}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--blue-a1:color(display-p3 0.024 0.514 1/0.016);--blue-a2:color(display-p3 0.024 0.514 0.906/0.04);--blue-a3:color(display-p3 0.012 0.506 0.914/0.087);--blue-a4:color(display-p3 0.008 0.545 1/0.146);--blue-a5:color(display-p3 0.004 0.502 0.984/0.212);--blue-a6:color(display-p3 0.004 0.463 0.922/0.291);--blue-a7:color(display-p3 0.004 0.431 0.863/0.393);--blue-a8:color(display-p3 0 0.427 0.851/0.55);--blue-a9:color(display-p3 0 0.412 0.961/0.753);--blue-a10:color(display-p3 0 0.376 0.886/0.765);--blue-a11:color(display-p3 0.15 0.44 0.84);--blue-a12:color(display-p3 0.102 0.193 0.379)}}}.dark,.dark-theme{--blue-a1:#004df211;--blue-a2:#1166fb18;--blue-a3:#0077ff3a;--blue-a4:#0075ff57;--blue-a5:#0081fd6b;--blue-a6:#0f89fd7f;--blue-a7:#2a91fe98;--blue-a8:#3094feb9;--blue-a9:#0090ff;--blue-a10:#3b9eff;--blue-a11:#70b8ff;--blue-a12:#c2e6ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--blue-a1:color(display-p3 0 0.333 1/0.059);--blue-a2:color(display-p3 0.114 0.435 0.988/0.085);--blue-a3:color(display-p3 0.122 0.463 1/0.219);--blue-a4:color(display-p3 0 0.467 1/0.324);--blue-a5:color(display-p3 0.098 0.51 1/0.4);--blue-a6:color(display-p3 0.224 0.557 1/0.475);--blue-a7:color(display-p3 0.294 0.584 1/0.572);--blue-a8:color(display-p3 0.314 0.592 1/0.702);--blue-a9:color(display-p3 0.251 0.573 0.996/0.967);--blue-a10:color(display-p3 0.357 0.631 1/0.971);--blue-a11:color(display-p3 0.49 0.72 1);--blue-a12:color(display-p3 0.788 0.898 0.99)}}}.light,.light-theme,:root{--cyan-1:#fafdfe;--cyan-2:#f2fafb;--cyan-3:#def7f9;--cyan-4:#caf1f6;--cyan-5:#b5e9f0;--cyan-6:#9ddde7;--cyan-7:#7dcedc;--cyan-8:#3db9cf;--cyan-9:#00a2c7;--cyan-10:#0797b9;--cyan-11:#107d98;--cyan-12:#0d3c48}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--cyan-1:color(display-p3 0.982 0.992 0.996);--cyan-2:color(display-p3 0.955 0.981 0.984);--cyan-3:color(display-p3 0.888 0.965 0.975);--cyan-4:color(display-p3 0.821 0.941 0.959);--cyan-5:color(display-p3 0.751 0.907 0.935);--cyan-6:color(display-p3 0.671 0.862 0.9);--cyan-7:color(display-p3 0.564 0.8 0.854);--cyan-8:color(display-p3 0.388 0.715 0.798);--cyan-9:color(display-p3 0.282 0.627 0.765);--cyan-10:color(display-p3 0.264 0.583 0.71);--cyan-11:color(display-p3 0.08 0.48 0.63);--cyan-12:color(display-p3 0.108 0.232 0.277)}}}.dark,.dark-theme{--cyan-1:#0b161a;--cyan-2:#101b20;--cyan-3:#082c36;--cyan-4:#003848;--cyan-5:#004558;--cyan-6:#045468;--cyan-7:#12677e;--cyan-8:#11809c;--cyan-9:#00a2c7;--cyan-10:#23afd0;--cyan-11:#4ccce6;--cyan-12:#b6ecf7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--cyan-1:color(display-p3 0.053 0.085 0.098);--cyan-2:color(display-p3 0.072 0.105 0.122);--cyan-3:color(display-p3 0.073 0.168 0.209);--cyan-4:color(display-p3 0.063 0.216 0.277);--cyan-5:color(display-p3 0.091 0.267 0.336);--cyan-6:color(display-p3 0.137 0.324 0.4);--cyan-7:color(display-p3 0.186 0.398 0.484);--cyan-8:color(display-p3 0.23 0.496 0.6);--cyan-9:color(display-p3 0.282 0.627 0.765);--cyan-10:color(display-p3 0.331 0.675 0.801);--cyan-11:color(display-p3 0.446 0.79 0.887);--cyan-12:color(display-p3 0.757 0.919 0.962)}}}.light,.light-theme,:root{--cyan-a1:#0099cc05;--cyan-a2:#009db10d;--cyan-a3:#00c2d121;--cyan-a4:#00bcd435;--cyan-a5:#01b4cc4a;--cyan-a6:#00a7c162;--cyan-a7:#009fbb82;--cyan-a8:#00a3c0c2;--cyan-a9:#00a2c7;--cyan-a10:#0094b7f8;--cyan-a11:#007491ef;--cyan-a12:#00323ef2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--cyan-a1:color(display-p3 0.02 0.608 0.804/0.02);--cyan-a2:color(display-p3 0.02 0.557 0.647/0.044);--cyan-a3:color(display-p3 0.004 0.694 0.796/0.114);--cyan-a4:color(display-p3 0.004 0.678 0.784/0.181);--cyan-a5:color(display-p3 0.004 0.624 0.733/0.248);--cyan-a6:color(display-p3 0.004 0.584 0.706/0.33);--cyan-a7:color(display-p3 0.004 0.541 0.667/0.436);--cyan-a8:color(display-p3 0 0.533 0.667/0.612);--cyan-a9:color(display-p3 0 0.482 0.675/0.718);--cyan-a10:color(display-p3 0 0.435 0.608/0.738);--cyan-a11:color(display-p3 0.08 0.48 0.63);--cyan-a12:color(display-p3 0.108 0.232 0.277)}}}.dark,.dark-theme{--cyan-a1:#0091f70a;--cyan-a2:#02a7f211;--cyan-a3:#00befd28;--cyan-a4:#00baff3b;--cyan-a5:#00befd4d;--cyan-a6:#00c7fd5e;--cyan-a7:#14cdff75;--cyan-a8:#11cfff95;--cyan-a9:#00cfffc3;--cyan-a10:#28d6ffcd;--cyan-a11:#52e1fee5;--cyan-a12:#bbf3fef7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--cyan-a1:color(display-p3 0 0.647 0.992/0.034);--cyan-a2:color(display-p3 0.133 0.733 1/0.059);--cyan-a3:color(display-p3 0.122 0.741 0.996/0.152);--cyan-a4:color(display-p3 0.051 0.725 1/0.227);--cyan-a5:color(display-p3 0.149 0.757 1/0.29);--cyan-a6:color(display-p3 0.267 0.792 1/0.358);--cyan-a7:color(display-p3 0.333 0.808 1/0.446);--cyan-a8:color(display-p3 0.357 0.816 1/0.572);--cyan-a9:color(display-p3 0.357 0.82 1/0.748);--cyan-a10:color(display-p3 0.4 0.839 1/0.786);--cyan-a11:color(display-p3 0.446 0.79 0.887);--cyan-a12:color(display-p3 0.757 0.919 0.962)}}}.light,.light-theme,:root{--teal-1:#fafefd;--teal-2:#f3fbf9;--teal-3:#e0f8f3;--teal-4:#ccf3ea;--teal-5:#b8eae0;--teal-6:#a1ded2;--teal-7:#83cdc1;--teal-8:#53b9ab;--teal-9:#12a594;--teal-10:#0d9b8a;--teal-11:#008573;--teal-12:#0d3d38}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--teal-1:color(display-p3 0.983 0.996 0.992);--teal-2:color(display-p3 0.958 0.983 0.976);--teal-3:color(display-p3 0.895 0.971 0.952);--teal-4:color(display-p3 0.831 0.949 0.92);--teal-5:color(display-p3 0.761 0.914 0.878);--teal-6:color(display-p3 0.682 0.864 0.825);--teal-7:color(display-p3 0.581 0.798 0.756);--teal-8:color(display-p3 0.433 0.716 0.671);--teal-9:color(display-p3 0.297 0.637 0.581);--teal-10:color(display-p3 0.275 0.599 0.542);--teal-11:color(display-p3 0.08 0.5 0.43);--teal-12:color(display-p3 0.11 0.235 0.219)}}}.dark,.dark-theme{--teal-1:#0d1514;--teal-2:#111c1b;--teal-3:#0d2d2a;--teal-4:#023b37;--teal-5:#084843;--teal-6:#145750;--teal-7:#1c6961;--teal-8:#207e73;--teal-9:#12a594;--teal-10:#0eb39e;--teal-11:#0bd8b6;--teal-12:#adf0dd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--teal-1:color(display-p3 0.059 0.083 0.079);--teal-2:color(display-p3 0.075 0.11 0.107);--teal-3:color(display-p3 0.087 0.175 0.165);--teal-4:color(display-p3 0.087 0.227 0.214);--teal-5:color(display-p3 0.12 0.277 0.261);--teal-6:color(display-p3 0.162 0.335 0.314);--teal-7:color(display-p3 0.205 0.406 0.379);--teal-8:color(display-p3 0.245 0.489 0.453);--teal-9:color(display-p3 0.297 0.637 0.581);--teal-10:color(display-p3 0.319 0.69 0.62);--teal-11:color(display-p3 0.388 0.835 0.719);--teal-12:color(display-p3 0.734 0.934 0.87)}}}.light,.light-theme,:root{--teal-a1:#00cc9905;--teal-a2:#00aa800c;--teal-a3:#00c69d1f;--teal-a4:#00c39633;--teal-a5:#00b49047;--teal-a6:#00a6855e;--teal-a7:#0099807c;--teal-a8:#009783ac;--teal-a9:#009e8ced;--teal-a10:#009684f2;--teal-a11:#008573;--teal-a12:#00332df2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--teal-a1:color(display-p3 0.024 0.757 0.514/0.016);--teal-a2:color(display-p3 0.02 0.647 0.467/0.044);--teal-a3:color(display-p3 0.004 0.741 0.557/0.106);--teal-a4:color(display-p3 0.004 0.702 0.537/0.169);--teal-a5:color(display-p3 0.004 0.643 0.494/0.24);--teal-a6:color(display-p3 0.004 0.569 0.447/0.318);--teal-a7:color(display-p3 0.004 0.518 0.424/0.42);--teal-a8:color(display-p3 0 0.506 0.424/0.569);--teal-a9:color(display-p3 0 0.482 0.404/0.702);--teal-a10:color(display-p3 0 0.451 0.369/0.726);--teal-a11:color(display-p3 0.08 0.5 0.43);--teal-a12:color(display-p3 0.11 0.235 0.219)}}}.dark,.dark-theme{--teal-a1:#00deab05;--teal-a2:#12fbe60c;--teal-a3:#00ffe61e;--teal-a4:#00ffe92d;--teal-a5:#00ffea3b;--teal-a6:#1cffe84b;--teal-a7:#2efde85f;--teal-a8:#32ffe775;--teal-a9:#13ffe49f;--teal-a10:#0dffe0ae;--teal-a11:#0afed5d6;--teal-a12:#b8ffebef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--teal-a1:color(display-p3 0 0.992 0.761/0.017);--teal-a2:color(display-p3 0.235 0.988 0.902/0.047);--teal-a3:color(display-p3 0.235 1 0.898/0.118);--teal-a4:color(display-p3 0.18 0.996 0.929/0.173);--teal-a5:color(display-p3 0.31 1 0.933/0.227);--teal-a6:color(display-p3 0.396 1 0.933/0.286);--teal-a7:color(display-p3 0.443 1 0.925/0.366);--teal-a8:color(display-p3 0.459 1 0.925/0.454);--teal-a9:color(display-p3 0.443 0.996 0.906/0.61);--teal-a10:color(display-p3 0.439 0.996 0.89/0.669);--teal-a11:color(display-p3 0.388 0.835 0.719);--teal-a12:color(display-p3 0.734 0.934 0.87)}}}.light,.light-theme,:root{--jade-1:#fbfefd;--jade-2:#f4fbf7;--jade-3:#e6f7ed;--jade-4:#d6f1e3;--jade-5:#c3e9d7;--jade-6:#acdec8;--jade-7:#8bceb6;--jade-8:#56ba9f;--jade-9:#29a383;--jade-10:#26997b;--jade-11:#208368;--jade-12:#1d3b31}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--jade-1:color(display-p3 0.986 0.996 0.992);--jade-2:color(display-p3 0.962 0.983 0.969);--jade-3:color(display-p3 0.912 0.965 0.932);--jade-4:color(display-p3 0.858 0.941 0.893);--jade-5:color(display-p3 0.795 0.909 0.847);--jade-6:color(display-p3 0.715 0.864 0.791);--jade-7:color(display-p3 0.603 0.802 0.718);--jade-8:color(display-p3 0.44 0.72 0.629);--jade-9:color(display-p3 0.319 0.63 0.521);--jade-10:color(display-p3 0.299 0.592 0.488);--jade-11:color(display-p3 0.15 0.5 0.37);--jade-12:color(display-p3 0.142 0.229 0.194)}}}.dark,.dark-theme{--jade-1:#0d1512;--jade-2:#121c18;--jade-3:#0f2e22;--jade-4:#0b3b2c;--jade-5:#114837;--jade-6:#1b5745;--jade-7:#246854;--jade-8:#2a7e68;--jade-9:#29a383;--jade-10:#27b08b;--jade-11:#1fd8a4;--jade-12:#adf0d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--jade-1:color(display-p3 0.059 0.083 0.071);--jade-2:color(display-p3 0.078 0.11 0.094);--jade-3:color(display-p3 0.091 0.176 0.138);--jade-4:color(display-p3 0.102 0.228 0.177);--jade-5:color(display-p3 0.133 0.279 0.221);--jade-6:color(display-p3 0.174 0.334 0.273);--jade-7:color(display-p3 0.219 0.402 0.335);--jade-8:color(display-p3 0.263 0.488 0.411);--jade-9:color(display-p3 0.319 0.63 0.521);--jade-10:color(display-p3 0.338 0.68 0.555);--jade-11:color(display-p3 0.4 0.835 0.656);--jade-12:color(display-p3 0.734 0.934 0.838)}}}.light,.light-theme,:root{--jade-a1:#00c08004;--jade-a2:#00a3460b;--jade-a3:#00ae4819;--jade-a4:#00a85129;--jade-a5:#00a2553c;--jade-a6:#009a5753;--jade-a7:#00945f74;--jade-a8:#00976ea9;--jade-a9:#00916bd6;--jade-a10:#008764d9;--jade-a11:#007152df;--jade-a12:#002217e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--jade-a1:color(display-p3 0.024 0.757 0.514/0.016);--jade-a2:color(display-p3 0.024 0.612 0.22/0.04);--jade-a3:color(display-p3 0.012 0.596 0.235/0.087);--jade-a4:color(display-p3 0.008 0.588 0.255/0.142);--jade-a5:color(display-p3 0.004 0.561 0.251/0.204);--jade-a6:color(display-p3 0.004 0.525 0.278/0.287);--jade-a7:color(display-p3 0.004 0.506 0.29/0.397);--jade-a8:color(display-p3 0 0.506 0.337/0.561);--jade-a9:color(display-p3 0 0.459 0.298/0.683);--jade-a10:color(display-p3 0 0.42 0.271/0.702);--jade-a11:color(display-p3 0.15 0.5 0.37);--jade-a12:color(display-p3 0.142 0.229 0.194)}}}.dark,.dark-theme{--jade-a1:#00de4505;--jade-a2:#27fba60c;--jade-a3:#02f99920;--jade-a4:#00ffaa2d;--jade-a5:#11ffb63b;--jade-a6:#34ffc24b;--jade-a7:#45fdc75e;--jade-a8:#48ffcf75;--jade-a9:#38feca9d;--jade-a10:#31fec7ab;--jade-a11:#21fec0d6;--jade-a12:#b8ffe1ef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--jade-a1:color(display-p3 0 0.992 0.298/0.017);--jade-a2:color(display-p3 0.318 0.988 0.651/0.047);--jade-a3:color(display-p3 0.267 1 0.667/0.118);--jade-a4:color(display-p3 0.275 0.996 0.702/0.173);--jade-a5:color(display-p3 0.361 1 0.741/0.227);--jade-a6:color(display-p3 0.439 1 0.796/0.286);--jade-a7:color(display-p3 0.49 1 0.804/0.362);--jade-a8:color(display-p3 0.506 1 0.835/0.45);--jade-a9:color(display-p3 0.478 0.996 0.816/0.606);--jade-a10:color(display-p3 0.478 1 0.816/0.656);--jade-a11:color(display-p3 0.4 0.835 0.656);--jade-a12:color(display-p3 0.734 0.934 0.838)}}}.light,.light-theme,:root{--green-1:#fbfefc;--green-2:#f4fbf6;--green-3:#e6f6eb;--green-4:#d6f1df;--green-5:#c4e8d1;--green-6:#adddc0;--green-7:#8eceaa;--green-8:#5bb98b;--green-9:#30a46c;--green-10:#2b9a66;--green-11:#218358;--green-12:#193b2d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--green-1:color(display-p3 0.986 0.996 0.989);--green-2:color(display-p3 0.963 0.983 0.967);--green-3:color(display-p3 0.913 0.964 0.925);--green-4:color(display-p3 0.859 0.94 0.879);--green-5:color(display-p3 0.796 0.907 0.826);--green-6:color(display-p3 0.718 0.863 0.761);--green-7:color(display-p3 0.61 0.801 0.675);--green-8:color(display-p3 0.451 0.715 0.559);--green-9:color(display-p3 0.332 0.634 0.442);--green-10:color(display-p3 0.308 0.595 0.417);--green-11:color(display-p3 0.19 0.5 0.32);--green-12:color(display-p3 0.132 0.228 0.18)}}}.dark,.dark-theme{--green-1:#0e1512;--green-2:#121b17;--green-3:#132d21;--green-4:#113b29;--green-5:#174933;--green-6:#20573e;--green-7:#28684a;--green-8:#2f7c57;--green-9:#30a46c;--green-10:#33b074;--green-11:#3dd68c;--green-12:#b1f1cb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--green-1:color(display-p3 0.062 0.083 0.071);--green-2:color(display-p3 0.079 0.106 0.09);--green-3:color(display-p3 0.1 0.173 0.133);--green-4:color(display-p3 0.115 0.229 0.166);--green-5:color(display-p3 0.147 0.282 0.206);--green-6:color(display-p3 0.185 0.338 0.25);--green-7:color(display-p3 0.227 0.403 0.298);--green-8:color(display-p3 0.27 0.479 0.351);--green-9:color(display-p3 0.332 0.634 0.442);--green-10:color(display-p3 0.357 0.682 0.474);--green-11:color(display-p3 0.434 0.828 0.573);--green-12:color(display-p3 0.747 0.938 0.807)}}}.light,.light-theme,:root{--green-a1:#00c04004;--green-a2:#00a32f0b;--green-a3:#00a43319;--green-a4:#00a83829;--green-a5:#019c393b;--green-a6:#00963c52;--green-a7:#00914071;--green-a8:#00924ba4;--green-a9:#008f4acf;--green-a10:#008647d4;--green-a11:#00713fde;--green-a12:#002616e6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--green-a1:color(display-p3 0.024 0.757 0.267/0.016);--green-a2:color(display-p3 0.024 0.565 0.129/0.036);--green-a3:color(display-p3 0.012 0.596 0.145/0.087);--green-a4:color(display-p3 0.008 0.588 0.145/0.142);--green-a5:color(display-p3 0.004 0.541 0.157/0.204);--green-a6:color(display-p3 0.004 0.518 0.157/0.283);--green-a7:color(display-p3 0.004 0.486 0.165/0.389);--green-a8:color(display-p3 0 0.478 0.2/0.55);--green-a9:color(display-p3 0 0.455 0.165/0.667);--green-a10:color(display-p3 0 0.416 0.153/0.691);--green-a11:color(display-p3 0.19 0.5 0.32);--green-a12:color(display-p3 0.132 0.228 0.18)}}}.dark,.dark-theme{--green-a1:#00de4505;--green-a2:#29f99d0b;--green-a3:#22ff991e;--green-a4:#11ff992d;--green-a5:#2bffa23c;--green-a6:#44ffaa4b;--green-a7:#50fdac5e;--green-a8:#54ffad73;--green-a9:#44ffa49e;--green-a10:#43fea4ab;--green-a11:#46fea5d4;--green-a12:#bbffd7f0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--green-a1:color(display-p3 0 0.992 0.298/0.017);--green-a2:color(display-p3 0.341 0.98 0.616/0.043);--green-a3:color(display-p3 0.376 0.996 0.655/0.114);--green-a4:color(display-p3 0.341 0.996 0.635/0.173);--green-a5:color(display-p3 0.408 1 0.678/0.232);--green-a6:color(display-p3 0.475 1 0.706/0.29);--green-a7:color(display-p3 0.514 1 0.706/0.362);--green-a8:color(display-p3 0.529 1 0.718/0.442);--green-a9:color(display-p3 0.502 0.996 0.682/0.61);--green-a10:color(display-p3 0.506 1 0.682/0.66);--green-a11:color(display-p3 0.434 0.828 0.573);--green-a12:color(display-p3 0.747 0.938 0.807)}}}.light,.light-theme,:root{--grass-1:#fbfefb;--grass-2:#f5fbf5;--grass-3:#e9f6e9;--grass-4:#daf1db;--grass-5:#c9e8ca;--grass-6:#b2ddb5;--grass-7:#94ce9a;--grass-8:#65ba74;--grass-9:#46a758;--grass-10:#3e9b4f;--grass-11:#2a7e3b;--grass-12:#203c25}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--grass-1:color(display-p3 0.986 0.996 0.985);--grass-2:color(display-p3 0.966 0.983 0.964);--grass-3:color(display-p3 0.923 0.965 0.917);--grass-4:color(display-p3 0.872 0.94 0.865);--grass-5:color(display-p3 0.811 0.908 0.802);--grass-6:color(display-p3 0.733 0.864 0.724);--grass-7:color(display-p3 0.628 0.803 0.622);--grass-8:color(display-p3 0.477 0.72 0.482);--grass-9:color(display-p3 0.38 0.647 0.378);--grass-10:color(display-p3 0.344 0.598 0.342);--grass-11:color(display-p3 0.263 0.488 0.261);--grass-12:color(display-p3 0.151 0.233 0.153)}}}.dark,.dark-theme{--grass-1:#0e1511;--grass-2:#141a15;--grass-3:#1b2a1e;--grass-4:#1d3a24;--grass-5:#25482d;--grass-6:#2d5736;--grass-7:#366740;--grass-8:#3e7949;--grass-9:#46a758;--grass-10:#53b365;--grass-11:#71d083;--grass-12:#c2f0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--grass-1:color(display-p3 0.062 0.083 0.067);--grass-2:color(display-p3 0.083 0.103 0.085);--grass-3:color(display-p3 0.118 0.163 0.122);--grass-4:color(display-p3 0.142 0.225 0.15);--grass-5:color(display-p3 0.178 0.279 0.186);--grass-6:color(display-p3 0.217 0.337 0.224);--grass-7:color(display-p3 0.258 0.4 0.264);--grass-8:color(display-p3 0.302 0.47 0.305);--grass-9:color(display-p3 0.38 0.647 0.378);--grass-10:color(display-p3 0.426 0.694 0.426);--grass-11:color(display-p3 0.535 0.807 0.542);--grass-12:color(display-p3 0.797 0.936 0.776)}}}.light,.light-theme,:root{--grass-a1:#00c00004;--grass-a2:#0099000a;--grass-a3:#00970016;--grass-a4:#009f0725;--grass-a5:#00930536;--grass-a6:#008f0a4d;--grass-a7:#018b0f6b;--grass-a8:#008d199a;--grass-a9:#008619b9;--grass-a10:#007b17c1;--grass-a11:#006514d5;--grass-a12:#002006df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--grass-a1:color(display-p3 0.024 0.757 0.024/0.016);--grass-a2:color(display-p3 0.024 0.565 0.024/0.036);--grass-a3:color(display-p3 0.059 0.576 0.008/0.083);--grass-a4:color(display-p3 0.035 0.565 0.008/0.134);--grass-a5:color(display-p3 0.047 0.545 0.008/0.197);--grass-a6:color(display-p3 0.031 0.502 0.004/0.275);--grass-a7:color(display-p3 0.012 0.482 0.004/0.377);--grass-a8:color(display-p3 0 0.467 0.008/0.522);--grass-a9:color(display-p3 0.008 0.435 0/0.624);--grass-a10:color(display-p3 0.008 0.388 0/0.659);--grass-a11:color(display-p3 0.263 0.488 0.261);--grass-a12:color(display-p3 0.151 0.233 0.153)}}}.dark,.dark-theme{--grass-a1:#00de1205;--grass-a2:#5ef7780a;--grass-a3:#70fe8c1b;--grass-a4:#57ff802c;--grass-a5:#68ff8b3b;--grass-a6:#71ff8f4b;--grass-a7:#77fd925d;--grass-a8:#77fd9070;--grass-a9:#65ff82a1;--grass-a10:#72ff8dae;--grass-a11:#89ff9fcd;--grass-a12:#ceffceef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--grass-a1:color(display-p3 0 0.992 0.071/0.017);--grass-a2:color(display-p3 0.482 0.996 0.584/0.038);--grass-a3:color(display-p3 0.549 0.992 0.588/0.106);--grass-a4:color(display-p3 0.51 0.996 0.557/0.169);--grass-a5:color(display-p3 0.553 1 0.588/0.227);--grass-a6:color(display-p3 0.584 1 0.608/0.29);--grass-a7:color(display-p3 0.604 1 0.616/0.358);--grass-a8:color(display-p3 0.608 1 0.62/0.433);--grass-a9:color(display-p3 0.573 1 0.569/0.622);--grass-a10:color(display-p3 0.6 0.996 0.6/0.673);--grass-a11:color(display-p3 0.535 0.807 0.542);--grass-a12:color(display-p3 0.797 0.936 0.776)}}}.light,.light-theme,:root{--orange-1:#fefcfb;--orange-2:#fff7ed;--orange-3:#ffefd6;--orange-4:#ffdfb5;--orange-5:#ffd19a;--orange-6:#ffc182;--orange-7:#f5ae73;--orange-8:#ec9455;--orange-9:#f76b15;--orange-10:#ef5f00;--orange-11:#cc4e00;--orange-12:#582d1d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--orange-1:color(display-p3 0.995 0.988 0.985);--orange-2:color(display-p3 0.994 0.968 0.934);--orange-3:color(display-p3 0.989 0.938 0.85);--orange-4:color(display-p3 1 0.874 0.687);--orange-5:color(display-p3 1 0.821 0.583);--orange-6:color(display-p3 0.975 0.767 0.545);--orange-7:color(display-p3 0.919 0.693 0.486);--orange-8:color(display-p3 0.877 0.597 0.379);--orange-9:color(display-p3 0.9 0.45 0.2);--orange-10:color(display-p3 0.87 0.409 0.164);--orange-11:color(display-p3 0.76 0.34 0);--orange-12:color(display-p3 0.323 0.185 0.127)}}}.dark,.dark-theme{--orange-1:#17120e;--orange-2:#1e160f;--orange-3:#331e0b;--orange-4:#462100;--orange-5:#562800;--orange-6:#66350c;--orange-7:#7e451d;--orange-8:#a35829;--orange-9:#f76b15;--orange-10:#ff801f;--orange-11:#ffa057;--orange-12:#ffe0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--orange-1:color(display-p3 0.088 0.07 0.057);--orange-2:color(display-p3 0.113 0.089 0.061);--orange-3:color(display-p3 0.189 0.12 0.056);--orange-4:color(display-p3 0.262 0.132 0);--orange-5:color(display-p3 0.315 0.168 0.016);--orange-6:color(display-p3 0.376 0.219 0.088);--orange-7:color(display-p3 0.465 0.283 0.147);--orange-8:color(display-p3 0.601 0.359 0.201);--orange-9:color(display-p3 0.9 0.45 0.2);--orange-10:color(display-p3 0.98 0.51 0.23);--orange-11:color(display-p3 1 0.63 0.38);--orange-12:color(display-p3 0.98 0.883 0.775)}}}.light,.light-theme,:root{--orange-a1:#c0400004;--orange-a2:#ff8e0012;--orange-a3:#ff9c0029;--orange-a4:#ff91014a;--orange-a5:#ff8b0065;--orange-a6:#ff81007d;--orange-a7:#ed6c008c;--orange-a8:#e35f00aa;--orange-a9:#f65e00ea;--orange-a10:#ef5f00;--orange-a11:#cc4e00;--orange-a12:#431200e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--orange-a1:color(display-p3 0.757 0.267 0.024/0.016);--orange-a2:color(display-p3 0.886 0.533 0.008/0.067);--orange-a3:color(display-p3 0.922 0.584 0.008/0.15);--orange-a4:color(display-p3 1 0.604 0.004/0.314);--orange-a5:color(display-p3 1 0.569 0.004/0.416);--orange-a6:color(display-p3 0.949 0.494 0.004/0.455);--orange-a7:color(display-p3 0.839 0.408 0/0.514);--orange-a8:color(display-p3 0.804 0.349 0/0.62);--orange-a9:color(display-p3 0.878 0.314 0/0.8);--orange-a10:color(display-p3 0.843 0.29 0/0.836);--orange-a11:color(display-p3 0.76 0.34 0);--orange-a12:color(display-p3 0.323 0.185 0.127)}}}.dark,.dark-theme{--orange-a1:#ec360007;--orange-a2:#fe6d000e;--orange-a3:#fb6a0025;--orange-a4:#ff590039;--orange-a5:#ff61004a;--orange-a6:#fd75045c;--orange-a7:#ff832c75;--orange-a8:#fe84389d;--orange-a9:#fe6d15f7;--orange-a10:#ff801f;--orange-a11:#ffa057;--orange-a12:#ffe0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--orange-a1:color(display-p3 0.961 0.247 0/0.022);--orange-a2:color(display-p3 0.992 0.529 0/0.051);--orange-a3:color(display-p3 0.996 0.486 0/0.131);--orange-a4:color(display-p3 0.996 0.384 0/0.211);--orange-a5:color(display-p3 1 0.455 0/0.265);--orange-a6:color(display-p3 1 0.529 0.129/0.332);--orange-a7:color(display-p3 1 0.569 0.251/0.429);--orange-a8:color(display-p3 1 0.584 0.302/0.572);--orange-a9:color(display-p3 1 0.494 0.216/0.895);--orange-a10:color(display-p3 1 0.522 0.235/0.979);--orange-a11:color(display-p3 1 0.63 0.38);--orange-a12:color(display-p3 0.98 0.883 0.775)}}}.light,.light-theme,:root{--brown-1:#fefdfc;--brown-2:#fcf9f6;--brown-3:#f6eee7;--brown-4:#f0e4d9;--brown-5:#ebdaca;--brown-6:#e4cdb7;--brown-7:#dcbc9f;--brown-8:#cea37e;--brown-9:#ad7f58;--brown-10:#a07553;--brown-11:#815e46;--brown-12:#3e332e}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--brown-1:color(display-p3 0.995 0.992 0.989);--brown-2:color(display-p3 0.987 0.976 0.964);--brown-3:color(display-p3 0.959 0.936 0.909);--brown-4:color(display-p3 0.934 0.897 0.855);--brown-5:color(display-p3 0.909 0.856 0.798);--brown-6:color(display-p3 0.88 0.808 0.73);--brown-7:color(display-p3 0.841 0.742 0.639);--brown-8:color(display-p3 0.782 0.647 0.514);--brown-9:color(display-p3 0.651 0.505 0.368);--brown-10:color(display-p3 0.601 0.465 0.344);--brown-11:color(display-p3 0.485 0.374 0.288);--brown-12:color(display-p3 0.236 0.202 0.183)}}}.dark,.dark-theme{--brown-1:#12110f;--brown-2:#1c1816;--brown-3:#28211d;--brown-4:#322922;--brown-5:#3e3128;--brown-6:#4d3c2f;--brown-7:#614a39;--brown-8:#7c5f46;--brown-9:#ad7f58;--brown-10:#b88c67;--brown-11:#dbb594;--brown-12:#f2e1ca}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--brown-1:color(display-p3 0.071 0.067 0.059);--brown-2:color(display-p3 0.107 0.095 0.087);--brown-3:color(display-p3 0.151 0.13 0.115);--brown-4:color(display-p3 0.191 0.161 0.138);--brown-5:color(display-p3 0.235 0.194 0.162);--brown-6:color(display-p3 0.291 0.237 0.192);--brown-7:color(display-p3 0.365 0.295 0.232);--brown-8:color(display-p3 0.469 0.377 0.287);--brown-9:color(display-p3 0.651 0.505 0.368);--brown-10:color(display-p3 0.697 0.557 0.423);--brown-11:color(display-p3 0.835 0.715 0.597);--brown-12:color(display-p3 0.938 0.885 0.802)}}}.light,.light-theme,:root{--brown-a1:#aa550003;--brown-a2:#aa550009;--brown-a3:#a04b0018;--brown-a4:#9b4a0026;--brown-a5:#9f4d0035;--brown-a6:#a04e0048;--brown-a7:#a34e0060;--brown-a8:#9f4a0081;--brown-a9:#823c00a7;--brown-a10:#723300ac;--brown-a11:#522100b9;--brown-a12:#140600d1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--brown-a1:color(display-p3 0.675 0.349 0.024/0.012);--brown-a2:color(display-p3 0.675 0.349 0.024/0.036);--brown-a3:color(display-p3 0.573 0.314 0.012/0.091);--brown-a4:color(display-p3 0.545 0.302 0.008/0.146);--brown-a5:color(display-p3 0.561 0.29 0.004/0.204);--brown-a6:color(display-p3 0.553 0.294 0.004/0.271);--brown-a7:color(display-p3 0.557 0.286 0.004/0.361);--brown-a8:color(display-p3 0.549 0.275 0.004/0.487);--brown-a9:color(display-p3 0.447 0.22 0/0.632);--brown-a10:color(display-p3 0.388 0.188 0/0.655);--brown-a11:color(display-p3 0.485 0.374 0.288);--brown-a12:color(display-p3 0.236 0.202 0.183)}}}.dark,.dark-theme{--brown-a1:#91110002;--brown-a2:#fba67c0c;--brown-a3:#fcb58c19;--brown-a4:#fbbb8a24;--brown-a5:#fcb88931;--brown-a6:#fdba8741;--brown-a7:#ffbb8856;--brown-a8:#ffbe8773;--brown-a9:#feb87da8;--brown-a10:#ffc18cb3;--brown-a11:#fed1aad9;--brown-a12:#feecd4f2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--brown-a1:color(display-p3 0.855 0.071 0/0.005);--brown-a2:color(display-p3 0.98 0.706 0.525/0.043);--brown-a3:color(display-p3 0.996 0.745 0.576/0.093);--brown-a4:color(display-p3 1 0.765 0.592/0.135);--brown-a5:color(display-p3 1 0.761 0.588/0.181);--brown-a6:color(display-p3 1 0.773 0.592/0.24);--brown-a7:color(display-p3 0.996 0.776 0.58/0.32);--brown-a8:color(display-p3 1 0.78 0.573/0.433);--brown-a9:color(display-p3 1 0.769 0.549/0.627);--brown-a10:color(display-p3 1 0.792 0.596/0.677);--brown-a11:color(display-p3 0.835 0.715 0.597);--brown-a12:color(display-p3 0.938 0.885 0.802)}}}.light,.light-theme,:root{--sky-1:#f9feff;--sky-2:#f1fafd;--sky-3:#e1f6fd;--sky-4:#d1f0fa;--sky-5:#bee7f5;--sky-6:#a9daed;--sky-7:#8dcae3;--sky-8:#60b3d7;--sky-9:#7ce2fe;--sky-10:#74daf8;--sky-11:#00749e;--sky-12:#1d3e56}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--sky-1:color(display-p3 0.98 0.995 0.999);--sky-2:color(display-p3 0.953 0.98 0.99);--sky-3:color(display-p3 0.899 0.963 0.989);--sky-4:color(display-p3 0.842 0.937 0.977);--sky-5:color(display-p3 0.777 0.9 0.954);--sky-6:color(display-p3 0.701 0.851 0.921);--sky-7:color(display-p3 0.604 0.785 0.879);--sky-8:color(display-p3 0.457 0.696 0.829);--sky-9:color(display-p3 0.585 0.877 0.983);--sky-10:color(display-p3 0.555 0.845 0.959);--sky-11:color(display-p3 0.193 0.448 0.605);--sky-12:color(display-p3 0.145 0.241 0.329)}}}.dark,.dark-theme{--sky-1:#0d141f;--sky-2:#111a27;--sky-3:#112840;--sky-4:#113555;--sky-5:#154467;--sky-6:#1b537b;--sky-7:#1f6692;--sky-8:#197cae;--sky-9:#7ce2fe;--sky-10:#a8eeff;--sky-11:#75c7f0;--sky-12:#c2f3ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sky-1:color(display-p3 0.056 0.078 0.116);--sky-2:color(display-p3 0.075 0.101 0.149);--sky-3:color(display-p3 0.089 0.154 0.244);--sky-4:color(display-p3 0.106 0.207 0.323);--sky-5:color(display-p3 0.135 0.261 0.394);--sky-6:color(display-p3 0.17 0.322 0.469);--sky-7:color(display-p3 0.205 0.394 0.557);--sky-8:color(display-p3 0.232 0.48 0.665);--sky-9:color(display-p3 0.585 0.877 0.983);--sky-10:color(display-p3 0.718 0.925 0.991);--sky-11:color(display-p3 0.536 0.772 0.924);--sky-12:color(display-p3 0.799 0.947 0.993)}}}.light,.light-theme,:root{--sky-a1:#00d5ff06;--sky-a2:#00a4db0e;--sky-a3:#00b3ee1e;--sky-a4:#00ace42e;--sky-a5:#00a1d841;--sky-a6:#0092ca56;--sky-a7:#0089c172;--sky-a8:#0085bf9f;--sky-a9:#00c7fe83;--sky-a10:#00bcf38b;--sky-a11:#00749e;--sky-a12:#002540e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--sky-a1:color(display-p3 0.02 0.804 1/0.02);--sky-a2:color(display-p3 0.024 0.592 0.757/0.048);--sky-a3:color(display-p3 0.004 0.655 0.886/0.102);--sky-a4:color(display-p3 0.004 0.604 0.851/0.157);--sky-a5:color(display-p3 0.004 0.565 0.792/0.224);--sky-a6:color(display-p3 0.004 0.502 0.737/0.299);--sky-a7:color(display-p3 0.004 0.459 0.694/0.397);--sky-a8:color(display-p3 0 0.435 0.682/0.542);--sky-a9:color(display-p3 0.004 0.71 0.965/0.416);--sky-a10:color(display-p3 0.004 0.647 0.914/0.444);--sky-a11:color(display-p3 0.193 0.448 0.605);--sky-a12:color(display-p3 0.145 0.241 0.329)}}}.dark,.dark-theme{--sky-a1:#0044ff0f;--sky-a2:#1171fb18;--sky-a3:#1184fc33;--sky-a4:#128fff49;--sky-a5:#1c9dfd5d;--sky-a6:#28a5ff72;--sky-a7:#2badfe8b;--sky-a8:#1db2fea9;--sky-a9:#7ce3ff;--sky-a10:#a8eeff;--sky-a11:#7cd3ffef;--sky-a12:#c2f3ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sky-a1:color(display-p3 0 0.282 0.996/0.055);--sky-a2:color(display-p3 0.157 0.467 0.992/0.089);--sky-a3:color(display-p3 0.192 0.522 0.996/0.19);--sky-a4:color(display-p3 0.212 0.584 1/0.274);--sky-a5:color(display-p3 0.259 0.631 1/0.349);--sky-a6:color(display-p3 0.302 0.655 1/0.433);--sky-a7:color(display-p3 0.329 0.686 1/0.526);--sky-a8:color(display-p3 0.325 0.71 1/0.643);--sky-a9:color(display-p3 0.592 0.894 1/0.984);--sky-a10:color(display-p3 0.722 0.933 1/0.992);--sky-a11:color(display-p3 0.536 0.772 0.924);--sky-a12:color(display-p3 0.799 0.947 0.993)}}}.light,.light-theme,:root{--mint-1:#f9fefd;--mint-2:#f2fbf9;--mint-3:#ddf9f2;--mint-4:#c8f4e9;--mint-5:#b3ecde;--mint-6:#9ce0d0;--mint-7:#7ecfbd;--mint-8:#4cbba5;--mint-9:#86ead4;--mint-10:#7de0cb;--mint-11:#027864;--mint-12:#16433c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--mint-1:color(display-p3 0.98 0.995 0.992);--mint-2:color(display-p3 0.957 0.985 0.977);--mint-3:color(display-p3 0.888 0.972 0.95);--mint-4:color(display-p3 0.819 0.951 0.916);--mint-5:color(display-p3 0.747 0.918 0.873);--mint-6:color(display-p3 0.668 0.87 0.818);--mint-7:color(display-p3 0.567 0.805 0.744);--mint-8:color(display-p3 0.42 0.724 0.649);--mint-9:color(display-p3 0.62 0.908 0.834);--mint-10:color(display-p3 0.585 0.871 0.797);--mint-11:color(display-p3 0.203 0.463 0.397);--mint-12:color(display-p3 0.136 0.259 0.236)}}}.dark,.dark-theme{--mint-1:#0e1515;--mint-2:#0f1b1b;--mint-3:#092c2b;--mint-4:#003a38;--mint-5:#004744;--mint-6:#105650;--mint-7:#1e685f;--mint-8:#277f70;--mint-9:#86ead4;--mint-10:#a8f5e5;--mint-11:#58d5ba;--mint-12:#c4f5e1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mint-1:color(display-p3 0.059 0.082 0.081);--mint-2:color(display-p3 0.068 0.104 0.105);--mint-3:color(display-p3 0.077 0.17 0.168);--mint-4:color(display-p3 0.068 0.224 0.22);--mint-5:color(display-p3 0.104 0.275 0.264);--mint-6:color(display-p3 0.154 0.332 0.313);--mint-7:color(display-p3 0.207 0.403 0.373);--mint-8:color(display-p3 0.258 0.49 0.441);--mint-9:color(display-p3 0.62 0.908 0.834);--mint-10:color(display-p3 0.725 0.954 0.898);--mint-11:color(display-p3 0.482 0.825 0.733);--mint-12:color(display-p3 0.807 0.955 0.887)}}}.light,.light-theme,:root{--mint-a1:#00d5aa06;--mint-a2:#00b18a0d;--mint-a3:#00d29e22;--mint-a4:#00cc9937;--mint-a5:#00c0914c;--mint-a6:#00b08663;--mint-a7:#00a17d81;--mint-a8:#009e7fb3;--mint-a9:#00d3a579;--mint-a10:#00c39982;--mint-a11:#007763fd;--mint-a12:#00312ae9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--mint-a1:color(display-p3 0.02 0.804 0.608/0.02);--mint-a2:color(display-p3 0.02 0.647 0.467/0.044);--mint-a3:color(display-p3 0.004 0.761 0.553/0.114);--mint-a4:color(display-p3 0.004 0.741 0.545/0.181);--mint-a5:color(display-p3 0.004 0.678 0.51/0.255);--mint-a6:color(display-p3 0.004 0.616 0.463/0.334);--mint-a7:color(display-p3 0.004 0.549 0.412/0.432);--mint-a8:color(display-p3 0 0.529 0.392/0.581);--mint-a9:color(display-p3 0.004 0.765 0.569/0.381);--mint-a10:color(display-p3 0.004 0.69 0.51/0.416);--mint-a11:color(display-p3 0.203 0.463 0.397);--mint-a12:color(display-p3 0.136 0.259 0.236)}}}.dark,.dark-theme{--mint-a1:#00dede05;--mint-a2:#00f9f90b;--mint-a3:#00fff61d;--mint-a4:#00fff42c;--mint-a5:#00fff23a;--mint-a6:#0effeb4a;--mint-a7:#34fde55e;--mint-a8:#41ffdf76;--mint-a9:#92ffe7e9;--mint-a10:#aefeedf5;--mint-a11:#67ffded2;--mint-a12:#cbfee9f5}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mint-a1:color(display-p3 0 0.992 0.992/0.017);--mint-a2:color(display-p3 0.071 0.98 0.98/0.043);--mint-a3:color(display-p3 0.176 0.996 0.996/0.11);--mint-a4:color(display-p3 0.071 0.996 0.973/0.169);--mint-a5:color(display-p3 0.243 1 0.949/0.223);--mint-a6:color(display-p3 0.369 1 0.933/0.286);--mint-a7:color(display-p3 0.459 1 0.914/0.362);--mint-a8:color(display-p3 0.49 1 0.89/0.454);--mint-a9:color(display-p3 0.678 0.996 0.914/0.904);--mint-a10:color(display-p3 0.761 1 0.941/0.95);--mint-a11:color(display-p3 0.482 0.825 0.733);--mint-a12:color(display-p3 0.807 0.955 0.887)}}}.light,.light-theme,:root{--lime-1:#fcfdfa;--lime-2:#f8faf3;--lime-3:#eef6d6;--lime-4:#e2f0bd;--lime-5:#d3e7a6;--lime-6:#c2da91;--lime-7:#abc978;--lime-8:#8db654;--lime-9:#bdee63;--lime-10:#b0e64c;--lime-11:#5c7c2f;--lime-12:#37401c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--lime-1:color(display-p3 0.989 0.992 0.981);--lime-2:color(display-p3 0.975 0.98 0.954);--lime-3:color(display-p3 0.939 0.965 0.851);--lime-4:color(display-p3 0.896 0.94 0.76);--lime-5:color(display-p3 0.843 0.903 0.678);--lime-6:color(display-p3 0.778 0.852 0.599);--lime-7:color(display-p3 0.694 0.784 0.508);--lime-8:color(display-p3 0.585 0.707 0.378);--lime-9:color(display-p3 0.78 0.928 0.466);--lime-10:color(display-p3 0.734 0.896 0.397);--lime-11:color(display-p3 0.386 0.482 0.227);--lime-12:color(display-p3 0.222 0.25 0.128)}}}.dark,.dark-theme{--lime-1:#11130c;--lime-2:#151a10;--lime-3:#1f2917;--lime-4:#29371d;--lime-5:#334423;--lime-6:#3d522a;--lime-7:#496231;--lime-8:#577538;--lime-9:#bdee63;--lime-10:#d4ff70;--lime-11:#bde56c;--lime-12:#e3f7ba}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--lime-1:color(display-p3 0.067 0.073 0.048);--lime-2:color(display-p3 0.086 0.1 0.067);--lime-3:color(display-p3 0.13 0.16 0.099);--lime-4:color(display-p3 0.172 0.214 0.126);--lime-5:color(display-p3 0.213 0.266 0.153);--lime-6:color(display-p3 0.257 0.321 0.182);--lime-7:color(display-p3 0.307 0.383 0.215);--lime-8:color(display-p3 0.365 0.456 0.25);--lime-9:color(display-p3 0.78 0.928 0.466);--lime-10:color(display-p3 0.865 0.995 0.519);--lime-11:color(display-p3 0.771 0.893 0.485);--lime-12:color(display-p3 0.905 0.966 0.753)}}}.light,.light-theme,:root{--lime-a1:#66990005;--lime-a2:#6b95000c;--lime-a3:#96c80029;--lime-a4:#8fc60042;--lime-a5:#81bb0059;--lime-a6:#72aa006e;--lime-a7:#61990087;--lime-a8:#559200ab;--lime-a9:#93e4009c;--lime-a10:#8fdc00b3;--lime-a11:#375f00d0;--lime-a12:#1e2900e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--lime-a1:color(display-p3 0.412 0.608 0.02/0.02);--lime-a2:color(display-p3 0.514 0.592 0.024/0.048);--lime-a3:color(display-p3 0.584 0.765 0.008/0.15);--lime-a4:color(display-p3 0.561 0.757 0.004/0.24);--lime-a5:color(display-p3 0.514 0.698 0.004/0.322);--lime-a6:color(display-p3 0.443 0.627 0/0.4);--lime-a7:color(display-p3 0.376 0.561 0.004/0.491);--lime-a8:color(display-p3 0.333 0.529 0/0.624);--lime-a9:color(display-p3 0.588 0.867 0/0.534);--lime-a10:color(display-p3 0.561 0.827 0/0.604);--lime-a11:color(display-p3 0.386 0.482 0.227);--lime-a12:color(display-p3 0.222 0.25 0.128)}}}.dark,.dark-theme{--lime-a1:#11bb0003;--lime-a2:#78f7000a;--lime-a3:#9bfd4c1a;--lime-a4:#a7fe5c29;--lime-a5:#affe6537;--lime-a6:#b2fe6d46;--lime-a7:#b6ff6f57;--lime-a8:#b6fd6d6c;--lime-a9:#caff69ed;--lime-a10:#d4ff70;--lime-a11:#d1fe77e4;--lime-a12:#e9febff7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--lime-a1:color(display-p3 0.067 0.941 0/0.009);--lime-a2:color(display-p3 0.584 0.996 0.071/0.038);--lime-a3:color(display-p3 0.69 1 0.38/0.101);--lime-a4:color(display-p3 0.729 1 0.435/0.16);--lime-a5:color(display-p3 0.745 1 0.471/0.215);--lime-a6:color(display-p3 0.769 1 0.482/0.274);--lime-a7:color(display-p3 0.769 1 0.506/0.341);--lime-a8:color(display-p3 0.784 1 0.51/0.416);--lime-a9:color(display-p3 0.839 1 0.502/0.925);--lime-a10:color(display-p3 0.871 1 0.522/0.996);--lime-a11:color(display-p3 0.771 0.893 0.485);--lime-a12:color(display-p3 0.905 0.966 0.753)}}}.light,.light-theme,:root{--yellow-1:#fdfdf9;--yellow-2:#fefce9;--yellow-3:#fffab8;--yellow-4:#fff394;--yellow-5:#ffe770;--yellow-6:#f3d768;--yellow-7:#e4c767;--yellow-8:#d5ae39;--yellow-9:#ffe629;--yellow-10:#ffdc00;--yellow-11:#9e6c00;--yellow-12:#473b1f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--yellow-1:color(display-p3 0.992 0.992 0.978);--yellow-2:color(display-p3 0.995 0.99 0.922);--yellow-3:color(display-p3 0.997 0.982 0.749);--yellow-4:color(display-p3 0.992 0.953 0.627);--yellow-5:color(display-p3 0.984 0.91 0.51);--yellow-6:color(display-p3 0.934 0.847 0.474);--yellow-7:color(display-p3 0.876 0.785 0.46);--yellow-8:color(display-p3 0.811 0.689 0.313);--yellow-9:color(display-p3 1 0.92 0.22);--yellow-10:color(display-p3 0.977 0.868 0.291);--yellow-11:color(display-p3 0.6 0.44 0);--yellow-12:color(display-p3 0.271 0.233 0.137)}}}.dark,.dark-theme{--yellow-1:#14120b;--yellow-2:#1b180f;--yellow-3:#2d2305;--yellow-4:#362b00;--yellow-5:#433500;--yellow-6:#524202;--yellow-7:#665417;--yellow-8:#836a21;--yellow-9:#ffe629;--yellow-10:#ffff57;--yellow-11:#f5e147;--yellow-12:#f6eeb4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--yellow-1:color(display-p3 0.078 0.069 0.047);--yellow-2:color(display-p3 0.103 0.094 0.063);--yellow-3:color(display-p3 0.168 0.137 0.039);--yellow-4:color(display-p3 0.209 0.169 0);--yellow-5:color(display-p3 0.255 0.209 0);--yellow-6:color(display-p3 0.31 0.261 0.07);--yellow-7:color(display-p3 0.389 0.331 0.135);--yellow-8:color(display-p3 0.497 0.42 0.182);--yellow-9:color(display-p3 1 0.92 0.22);--yellow-10:color(display-p3 1 1 0.456);--yellow-11:color(display-p3 0.948 0.885 0.392);--yellow-12:color(display-p3 0.959 0.934 0.731)}}}.light,.light-theme,:root{--yellow-a1:#aaaa0006;--yellow-a2:#f4dd0016;--yellow-a3:#ffee0047;--yellow-a4:#ffe3016b;--yellow-a5:#ffd5008f;--yellow-a6:#ebbc0097;--yellow-a7:#d2a10098;--yellow-a8:#c99700c6;--yellow-a9:#ffe100d6;--yellow-a10:#ffdc00;--yellow-a11:#9e6c00;--yellow-a12:#2e2000e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--yellow-a1:color(display-p3 0.675 0.675 0.024/0.024);--yellow-a2:color(display-p3 0.953 0.855 0.008/0.079);--yellow-a3:color(display-p3 0.988 0.925 0.004/0.251);--yellow-a4:color(display-p3 0.98 0.875 0.004/0.373);--yellow-a5:color(display-p3 0.969 0.816 0.004/0.491);--yellow-a6:color(display-p3 0.875 0.71 0/0.526);--yellow-a7:color(display-p3 0.769 0.604 0/0.542);--yellow-a8:color(display-p3 0.725 0.549 0/0.687);--yellow-a9:color(display-p3 1 0.898 0/0.781);--yellow-a10:color(display-p3 0.969 0.812 0/0.71);--yellow-a11:color(display-p3 0.6 0.44 0);--yellow-a12:color(display-p3 0.271 0.233 0.137)}}}.dark,.dark-theme{--yellow-a1:#d1510004;--yellow-a2:#f9b4000b;--yellow-a3:#ffaa001e;--yellow-a4:#fdb70028;--yellow-a5:#febb0036;--yellow-a6:#fec40046;--yellow-a7:#fdcb225c;--yellow-a8:#fdca327b;--yellow-a9:#ffe629;--yellow-a10:#ffff57;--yellow-a11:#fee949f5;--yellow-a12:#fef6baf6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--yellow-a1:color(display-p3 0.973 0.369 0/0.013);--yellow-a2:color(display-p3 0.996 0.792 0/0.038);--yellow-a3:color(display-p3 0.996 0.71 0/0.11);--yellow-a4:color(display-p3 0.996 0.741 0/0.152);--yellow-a5:color(display-p3 0.996 0.765 0/0.202);--yellow-a6:color(display-p3 0.996 0.816 0.082/0.261);--yellow-a7:color(display-p3 1 0.831 0.263/0.345);--yellow-a8:color(display-p3 1 0.831 0.314/0.463);--yellow-a9:color(display-p3 1 0.922 0.22);--yellow-a10:color(display-p3 1 1 0.455);--yellow-a11:color(display-p3 0.948 0.885 0.392);--yellow-a12:color(display-p3 0.959 0.934 0.731)}}}.light,.light-theme,:root{--amber-1:#fefdfb;--amber-2:#fefbe9;--amber-3:#fff7c2;--amber-4:#ffee9c;--amber-5:#fbe577;--amber-6:#f3d673;--amber-7:#e9c162;--amber-8:#e2a336;--amber-9:#ffc53d;--amber-10:#ffba18;--amber-11:#ab6400;--amber-12:#4f3422}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--amber-1:color(display-p3 0.995 0.992 0.985);--amber-2:color(display-p3 0.994 0.986 0.921);--amber-3:color(display-p3 0.994 0.969 0.782);--amber-4:color(display-p3 0.989 0.937 0.65);--amber-5:color(display-p3 0.97 0.902 0.527);--amber-6:color(display-p3 0.936 0.844 0.506);--amber-7:color(display-p3 0.89 0.762 0.443);--amber-8:color(display-p3 0.85 0.65 0.3);--amber-9:color(display-p3 1 0.77 0.26);--amber-10:color(display-p3 0.959 0.741 0.274);--amber-11:color(display-p3 0.64 0.4 0);--amber-12:color(display-p3 0.294 0.208 0.145)}}}.dark,.dark-theme{--amber-1:#16120c;--amber-2:#1d180f;--amber-3:#302008;--amber-4:#3f2700;--amber-5:#4d3000;--amber-6:#5c3d05;--amber-7:#714f19;--amber-8:#8f6424;--amber-9:#ffc53d;--amber-10:#ffd60a;--amber-11:#ffca16;--amber-12:#ffe7b3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--amber-1:color(display-p3 0.082 0.07 0.05);--amber-2:color(display-p3 0.111 0.094 0.064);--amber-3:color(display-p3 0.178 0.128 0.049);--amber-4:color(display-p3 0.239 0.156 0);--amber-5:color(display-p3 0.29 0.193 0);--amber-6:color(display-p3 0.344 0.245 0.076);--amber-7:color(display-p3 0.422 0.314 0.141);--amber-8:color(display-p3 0.535 0.399 0.189);--amber-9:color(display-p3 1 0.77 0.26);--amber-10:color(display-p3 1 0.87 0.15);--amber-11:color(display-p3 1 0.8 0.29);--amber-12:color(display-p3 0.984 0.909 0.726)}}}.light,.light-theme,:root{--amber-a1:#c0800004;--amber-a2:#f4d10016;--amber-a3:#ffde003d;--amber-a4:#ffd40063;--amber-a5:#f8cf0088;--amber-a6:#eab5008c;--amber-a7:#dc9b009d;--amber-a8:#da8a00c9;--amber-a9:#ffb300c2;--amber-a10:#ffb300e7;--amber-a11:#ab6400;--amber-a12:#341500dd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--amber-a1:color(display-p3 0.757 0.514 0.024/0.016);--amber-a2:color(display-p3 0.902 0.804 0.008/0.079);--amber-a3:color(display-p3 0.965 0.859 0.004/0.22);--amber-a4:color(display-p3 0.969 0.82 0.004/0.35);--amber-a5:color(display-p3 0.933 0.796 0.004/0.475);--amber-a6:color(display-p3 0.875 0.682 0.004/0.495);--amber-a7:color(display-p3 0.804 0.573 0/0.557);--amber-a8:color(display-p3 0.788 0.502 0/0.699);--amber-a9:color(display-p3 1 0.686 0/0.742);--amber-a10:color(display-p3 0.945 0.643 0/0.726);--amber-a11:color(display-p3 0.64 0.4 0);--amber-a12:color(display-p3 0.294 0.208 0.145)}}}.dark,.dark-theme{--amber-a1:#e63c0006;--amber-a2:#fd9b000d;--amber-a3:#fa820022;--amber-a4:#fc820032;--amber-a5:#fd8b0041;--amber-a6:#fd9b0051;--amber-a7:#ffab2567;--amber-a8:#ffae3587;--amber-a9:#ffc53d;--amber-a10:#ffd60a;--amber-a11:#ffca16;--amber-a12:#ffe7b3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--amber-a1:color(display-p3 0.992 0.298 0/0.017);--amber-a2:color(display-p3 0.988 0.651 0/0.047);--amber-a3:color(display-p3 1 0.6 0/0.118);--amber-a4:color(display-p3 1 0.557 0/0.185);--amber-a5:color(display-p3 1 0.592 0/0.24);--amber-a6:color(display-p3 1 0.659 0.094/0.299);--amber-a7:color(display-p3 1 0.714 0.263/0.383);--amber-a8:color(display-p3 0.996 0.729 0.306/0.5);--amber-a9:color(display-p3 1 0.769 0.259);--amber-a10:color(display-p3 1 0.871 0.149);--amber-a11:color(display-p3 1 0.8 0.29);--amber-a12:color(display-p3 0.984 0.909 0.726)}}}.light,.light-theme,:root{--gold-1:#fdfdfc;--gold-2:#faf9f2;--gold-3:#f2f0e7;--gold-4:#eae6db;--gold-5:#e1dccf;--gold-6:#d8d0bf;--gold-7:#cbc0aa;--gold-8:#b9a88d;--gold-9:#978365;--gold-10:#8c7a5e;--gold-11:#71624b;--gold-12:#3b352b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--gold-1:color(display-p3 0.992 0.992 0.989);--gold-2:color(display-p3 0.98 0.976 0.953);--gold-3:color(display-p3 0.947 0.94 0.909);--gold-4:color(display-p3 0.914 0.904 0.865);--gold-5:color(display-p3 0.88 0.865 0.816);--gold-6:color(display-p3 0.84 0.818 0.756);--gold-7:color(display-p3 0.788 0.753 0.677);--gold-8:color(display-p3 0.715 0.66 0.565);--gold-9:color(display-p3 0.579 0.517 0.41);--gold-10:color(display-p3 0.538 0.479 0.38);--gold-11:color(display-p3 0.433 0.386 0.305);--gold-12:color(display-p3 0.227 0.209 0.173)}}}.dark,.dark-theme{--gold-1:#121211;--gold-2:#1b1a17;--gold-3:#24231f;--gold-4:#2d2b26;--gold-5:#38352e;--gold-6:#444039;--gold-7:#544f46;--gold-8:#696256;--gold-9:#978365;--gold-10:#a39073;--gold-11:#cbb99f;--gold-12:#e8e2d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gold-1:color(display-p3 0.071 0.071 0.067);--gold-2:color(display-p3 0.104 0.101 0.09);--gold-3:color(display-p3 0.141 0.136 0.122);--gold-4:color(display-p3 0.177 0.17 0.152);--gold-5:color(display-p3 0.217 0.207 0.185);--gold-6:color(display-p3 0.265 0.252 0.225);--gold-7:color(display-p3 0.327 0.31 0.277);--gold-8:color(display-p3 0.407 0.384 0.342);--gold-9:color(display-p3 0.579 0.517 0.41);--gold-10:color(display-p3 0.628 0.566 0.463);--gold-11:color(display-p3 0.784 0.728 0.635);--gold-12:color(display-p3 0.906 0.887 0.855)}}}.light,.light-theme,:root{--gold-a1:#55550003;--gold-a2:#9d8a000d;--gold-a3:#75600018;--gold-a4:#6b4e0024;--gold-a5:#60460030;--gold-a6:#64440040;--gold-a7:#63420055;--gold-a8:#633d0072;--gold-a9:#5332009a;--gold-a10:#492d00a1;--gold-a11:#362100b4;--gold-a12:#130c00d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--gold-a1:color(display-p3 0.349 0.349 0.024/0.012);--gold-a2:color(display-p3 0.592 0.514 0.024/0.048);--gold-a3:color(display-p3 0.4 0.357 0.012/0.091);--gold-a4:color(display-p3 0.357 0.298 0.008/0.134);--gold-a5:color(display-p3 0.345 0.282 0.004/0.185);--gold-a6:color(display-p3 0.341 0.263 0.004/0.244);--gold-a7:color(display-p3 0.345 0.235 0.004/0.322);--gold-a8:color(display-p3 0.345 0.22 0.004/0.436);--gold-a9:color(display-p3 0.286 0.18 0/0.589);--gold-a10:color(display-p3 0.255 0.161 0/0.62);--gold-a11:color(display-p3 0.433 0.386 0.305);--gold-a12:color(display-p3 0.227 0.209 0.173)}}}.dark,.dark-theme{--gold-a1:#91911102;--gold-a2:#f9e29d0b;--gold-a3:#f8ecbb15;--gold-a4:#ffeec41e;--gold-a5:#feecc22a;--gold-a6:#feebcb37;--gold-a7:#ffedcd48;--gold-a8:#fdeaca5f;--gold-a9:#ffdba690;--gold-a10:#fedfb09d;--gold-a11:#fee7c6c8;--gold-a12:#fef7ede7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gold-a1:color(display-p3 0.855 0.855 0.071/0.005);--gold-a2:color(display-p3 0.98 0.89 0.616/0.043);--gold-a3:color(display-p3 1 0.949 0.753/0.08);--gold-a4:color(display-p3 1 0.933 0.8/0.118);--gold-a5:color(display-p3 1 0.949 0.804/0.16);--gold-a6:color(display-p3 1 0.925 0.8/0.215);--gold-a7:color(display-p3 1 0.945 0.831/0.278);--gold-a8:color(display-p3 1 0.937 0.82/0.366);--gold-a9:color(display-p3 0.996 0.882 0.69/0.551);--gold-a10:color(display-p3 1 0.894 0.725/0.601);--gold-a11:color(display-p3 0.784 0.728 0.635);--gold-a12:color(display-p3 0.906 0.887 0.855)}}}.light,.light-theme,:root{--bronze-1:#fdfcfc;--bronze-2:#fdf7f5;--bronze-3:#f6edea;--bronze-4:#efe4df;--bronze-5:#e7d9d3;--bronze-6:#dfcdc5;--bronze-7:#d3bcb3;--bronze-8:#c2a499;--bronze-9:#a18072;--bronze-10:#957468;--bronze-11:#7d5e54;--bronze-12:#43302b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--bronze-1:color(display-p3 0.991 0.988 0.988);--bronze-2:color(display-p3 0.989 0.97 0.961);--bronze-3:color(display-p3 0.958 0.932 0.919);--bronze-4:color(display-p3 0.929 0.894 0.877);--bronze-5:color(display-p3 0.898 0.853 0.832);--bronze-6:color(display-p3 0.861 0.805 0.778);--bronze-7:color(display-p3 0.812 0.739 0.706);--bronze-8:color(display-p3 0.741 0.647 0.606);--bronze-9:color(display-p3 0.611 0.507 0.455);--bronze-10:color(display-p3 0.563 0.461 0.414);--bronze-11:color(display-p3 0.471 0.373 0.336);--bronze-12:color(display-p3 0.251 0.191 0.172)}}}.dark,.dark-theme{--bronze-1:#141110;--bronze-2:#1c1917;--bronze-3:#262220;--bronze-4:#302a27;--bronze-5:#3b3330;--bronze-6:#493e3a;--bronze-7:#5a4c47;--bronze-8:#6f5f58;--bronze-9:#a18072;--bronze-10:#ae8c7e;--bronze-11:#d4b3a5;--bronze-12:#ede0d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--bronze-1:color(display-p3 0.076 0.067 0.063);--bronze-2:color(display-p3 0.106 0.097 0.093);--bronze-3:color(display-p3 0.147 0.132 0.125);--bronze-4:color(display-p3 0.185 0.166 0.156);--bronze-5:color(display-p3 0.227 0.202 0.19);--bronze-6:color(display-p3 0.278 0.246 0.23);--bronze-7:color(display-p3 0.343 0.302 0.281);--bronze-8:color(display-p3 0.426 0.374 0.347);--bronze-9:color(display-p3 0.611 0.507 0.455);--bronze-10:color(display-p3 0.66 0.556 0.504);--bronze-11:color(display-p3 0.81 0.707 0.655);--bronze-12:color(display-p3 0.921 0.88 0.854)}}}.light,.light-theme,:root{--bronze-a1:#55000003;--bronze-a2:#cc33000a;--bronze-a3:#92250015;--bronze-a4:#80280020;--bronze-a5:#7423002c;--bronze-a6:#7324003a;--bronze-a7:#6c1f004c;--bronze-a8:#671c0066;--bronze-a9:#551a008d;--bronze-a10:#4c150097;--bronze-a11:#3d0f00ab;--bronze-a12:#1d0600d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--bronze-a1:color(display-p3 0.349 0.024 0.024/0.012);--bronze-a2:color(display-p3 0.71 0.22 0.024/0.04);--bronze-a3:color(display-p3 0.482 0.2 0.008/0.083);--bronze-a4:color(display-p3 0.424 0.133 0.004/0.122);--bronze-a5:color(display-p3 0.4 0.145 0.004/0.169);--bronze-a6:color(display-p3 0.388 0.125 0.004/0.224);--bronze-a7:color(display-p3 0.365 0.11 0.004/0.295);--bronze-a8:color(display-p3 0.341 0.102 0.004/0.393);--bronze-a9:color(display-p3 0.29 0.094 0/0.546);--bronze-a10:color(display-p3 0.255 0.082 0/0.585);--bronze-a11:color(display-p3 0.471 0.373 0.336);--bronze-a12:color(display-p3 0.251 0.191 0.172)}}}.dark,.dark-theme{--bronze-a1:#d1110004;--bronze-a2:#fbbc910c;--bronze-a3:#faceb817;--bronze-a4:#facdb622;--bronze-a5:#ffd2c12d;--bronze-a6:#ffd1c03c;--bronze-a7:#fdd0c04f;--bronze-a8:#ffd6c565;--bronze-a9:#fec7b09b;--bronze-a10:#fecab5a9;--bronze-a11:#ffd7c6d1;--bronze-a12:#fff1e9ec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--bronze-a1:color(display-p3 0.941 0.067 0/0.009);--bronze-a2:color(display-p3 0.98 0.8 0.706/0.043);--bronze-a3:color(display-p3 0.988 0.851 0.761/0.085);--bronze-a4:color(display-p3 0.996 0.839 0.78/0.127);--bronze-a5:color(display-p3 0.996 0.863 0.773/0.173);--bronze-a6:color(display-p3 1 0.863 0.796/0.227);--bronze-a7:color(display-p3 1 0.867 0.8/0.295);--bronze-a8:color(display-p3 1 0.859 0.788/0.387);--bronze-a9:color(display-p3 1 0.82 0.733/0.585);--bronze-a10:color(display-p3 1 0.839 0.761/0.635);--bronze-a11:color(display-p3 0.81 0.707 0.655);--bronze-a12:color(display-p3 0.921 0.88 0.854)}}}.light,.light-theme,:root{--gray-1:#fcfcfc;--gray-2:#f9f9f9;--gray-3:#f0f0f0;--gray-4:#e8e8e8;--gray-5:#e0e0e0;--gray-6:#d9d9d9;--gray-7:#cecece;--gray-8:#bbb;--gray-9:#8d8d8d;--gray-10:#838383;--gray-11:#646464;--gray-12:#202020}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--gray-1:color(display-p3 0.988 0.988 0.988);--gray-2:color(display-p3 0.975 0.975 0.975);--gray-3:color(display-p3 0.939 0.939 0.939);--gray-4:color(display-p3 0.908 0.908 0.908);--gray-5:color(display-p3 0.88 0.88 0.88);--gray-6:color(display-p3 0.849 0.849 0.849);--gray-7:color(display-p3 0.807 0.807 0.807);--gray-8:color(display-p3 0.732 0.732 0.732);--gray-9:color(display-p3 0.553 0.553 0.553);--gray-10:color(display-p3 0.512 0.512 0.512);--gray-11:color(display-p3 0.392 0.392 0.392);--gray-12:color(display-p3 0.125 0.125 0.125)}}}.dark,.dark-theme{--gray-1:#111;--gray-2:#191919;--gray-3:#222;--gray-4:#2a2a2a;--gray-5:#313131;--gray-6:#3a3a3a;--gray-7:#484848;--gray-8:#606060;--gray-9:#6e6e6e;--gray-10:#7b7b7b;--gray-11:#b4b4b4;--gray-12:#eee}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-1:color(display-p3 0.067 0.067 0.067);--gray-2:color(display-p3 0.098 0.098 0.098);--gray-3:color(display-p3 0.135 0.135 0.135);--gray-4:color(display-p3 0.163 0.163 0.163);--gray-5:color(display-p3 0.192 0.192 0.192);--gray-6:color(display-p3 0.228 0.228 0.228);--gray-7:color(display-p3 0.283 0.283 0.283);--gray-8:color(display-p3 0.375 0.375 0.375);--gray-9:color(display-p3 0.431 0.431 0.431);--gray-10:color(display-p3 0.484 0.484 0.484);--gray-11:color(display-p3 0.706 0.706 0.706);--gray-12:color(display-p3 0.933 0.933 0.933)}}}.light,.light-theme,:root{--gray-a1:#00000003;--gray-a2:#00000006;--gray-a3:#0000000f;--gray-a4:#00000017;--gray-a5:#0000001f;--gray-a6:#00000026;--gray-a7:#00000031;--gray-a8:#00000044;--gray-a9:#00000072;--gray-a10:#0000007c;--gray-a11:#0000009b;--gray-a12:#000000df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--gray-a1:color(display-p3 0 0 0/0.012);--gray-a2:color(display-p3 0 0 0/0.024);--gray-a3:color(display-p3 0 0 0/0.063);--gray-a4:color(display-p3 0 0 0/0.09);--gray-a5:color(display-p3 0 0 0/0.122);--gray-a6:color(display-p3 0 0 0/0.153);--gray-a7:color(display-p3 0 0 0/0.192);--gray-a8:color(display-p3 0 0 0/0.267);--gray-a9:color(display-p3 0 0 0/0.447);--gray-a10:color(display-p3 0 0 0/0.486);--gray-a11:color(display-p3 0 0 0/0.608);--gray-a12:color(display-p3 0 0 0/0.875)}}}.dark,.dark-theme{--gray-a1:#0000;--gray-a2:#ffffff09;--gray-a3:#ffffff12;--gray-a4:#ffffff1b;--gray-a5:#ffffff22;--gray-a6:#ffffff2c;--gray-a7:#ffffff3b;--gray-a8:#ffffff55;--gray-a9:#ffffff64;--gray-a10:#ffffff72;--gray-a11:#ffffffaf;--gray-a12:#ffffffed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-a1:color(display-p3 0 0 0/0);--gray-a2:color(display-p3 1 1 1/0.034);--gray-a3:color(display-p3 1 1 1/0.071);--gray-a4:color(display-p3 1 1 1/0.105);--gray-a5:color(display-p3 1 1 1/0.134);--gray-a6:color(display-p3 1 1 1/0.172);--gray-a7:color(display-p3 1 1 1/0.231);--gray-a8:color(display-p3 1 1 1/0.332);--gray-a9:color(display-p3 1 1 1/0.391);--gray-a10:color(display-p3 1 1 1/0.445);--gray-a11:color(display-p3 1 1 1/0.685);--gray-a12:color(display-p3 1 1 1/0.929)}}}.light,.light-theme,:root{--mauve-1:#fdfcfd;--mauve-2:#faf9fb;--mauve-3:#f2eff3;--mauve-4:#eae7ec;--mauve-5:#e3dfe6;--mauve-6:#dbd8e0;--mauve-7:#d0cdd7;--mauve-8:#bcbac7;--mauve-9:#8e8c99;--mauve-10:#84828e;--mauve-11:#65636d;--mauve-12:#211f26}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--mauve-1:color(display-p3 0.991 0.988 0.992);--mauve-2:color(display-p3 0.98 0.976 0.984);--mauve-3:color(display-p3 0.946 0.938 0.952);--mauve-4:color(display-p3 0.915 0.906 0.925);--mauve-5:color(display-p3 0.886 0.876 0.901);--mauve-6:color(display-p3 0.856 0.846 0.875);--mauve-7:color(display-p3 0.814 0.804 0.84);--mauve-8:color(display-p3 0.735 0.728 0.777);--mauve-9:color(display-p3 0.555 0.549 0.596);--mauve-10:color(display-p3 0.514 0.508 0.552);--mauve-11:color(display-p3 0.395 0.388 0.424);--mauve-12:color(display-p3 0.128 0.122 0.147)}}}.dark,.dark-theme{--mauve-1:#121113;--mauve-2:#1a191b;--mauve-3:#232225;--mauve-4:#2b292d;--mauve-5:#323035;--mauve-6:#3c393f;--mauve-7:#49474e;--mauve-8:#625f69;--mauve-9:#6f6d78;--mauve-10:#7c7a85;--mauve-11:#b5b2bc;--mauve-12:#eeeef0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mauve-1:color(display-p3 0.07 0.067 0.074);--mauve-2:color(display-p3 0.101 0.098 0.105);--mauve-3:color(display-p3 0.138 0.134 0.144);--mauve-4:color(display-p3 0.167 0.161 0.175);--mauve-5:color(display-p3 0.196 0.189 0.206);--mauve-6:color(display-p3 0.232 0.225 0.245);--mauve-7:color(display-p3 0.286 0.277 0.302);--mauve-8:color(display-p3 0.383 0.373 0.408);--mauve-9:color(display-p3 0.434 0.428 0.467);--mauve-10:color(display-p3 0.487 0.48 0.519);--mauve-11:color(display-p3 0.707 0.7 0.735);--mauve-12:color(display-p3 0.933 0.933 0.94)}}}.light,.light-theme,:root{--mauve-a1:#55005503;--mauve-a2:#2b005506;--mauve-a3:#30004010;--mauve-a4:#20003618;--mauve-a5:#20003820;--mauve-a6:#14003527;--mauve-a7:#10003332;--mauve-a8:#08003145;--mauve-a9:#05001d73;--mauve-a10:#0500197d;--mauve-a11:#0400119c;--mauve-a12:#020008e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--mauve-a1:color(display-p3 0.349 0.024 0.349/0.012);--mauve-a2:color(display-p3 0.184 0.024 0.349/0.024);--mauve-a3:color(display-p3 0.129 0.008 0.255/0.063);--mauve-a4:color(display-p3 0.094 0.012 0.216/0.095);--mauve-a5:color(display-p3 0.098 0.008 0.224/0.126);--mauve-a6:color(display-p3 0.055 0.004 0.18/0.153);--mauve-a7:color(display-p3 0.067 0.008 0.184/0.197);--mauve-a8:color(display-p3 0.02 0.004 0.176/0.271);--mauve-a9:color(display-p3 0.02 0.004 0.106/0.451);--mauve-a10:color(display-p3 0.012 0.004 0.09/0.491);--mauve-a11:color(display-p3 0.016 0 0.059/0.612);--mauve-a12:color(display-p3 0.008 0 0.027/0.879)}}}.dark,.dark-theme{--mauve-a1:#0000;--mauve-a2:#f5f4f609;--mauve-a3:#ebeaf814;--mauve-a4:#eee5f81d;--mauve-a5:#efe6fe25;--mauve-a6:#f1e6fd30;--mauve-a7:#eee9ff40;--mauve-a8:#eee7ff5d;--mauve-a9:#eae6fd6e;--mauve-a10:#ece9fd7c;--mauve-a11:#f5f1ffb7;--mauve-a12:#fdfdffef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mauve-a1:color(display-p3 0 0 0/0);--mauve-a2:color(display-p3 0.996 0.992 1/0.034);--mauve-a3:color(display-p3 0.937 0.933 0.992/0.077);--mauve-a4:color(display-p3 0.957 0.918 0.996/0.111);--mauve-a5:color(display-p3 0.937 0.906 0.996/0.145);--mauve-a6:color(display-p3 0.953 0.925 0.996/0.183);--mauve-a7:color(display-p3 0.945 0.929 1/0.246);--mauve-a8:color(display-p3 0.937 0.918 1/0.361);--mauve-a9:color(display-p3 0.933 0.918 1/0.424);--mauve-a10:color(display-p3 0.941 0.925 1/0.479);--mauve-a11:color(display-p3 0.965 0.961 1/0.712);--mauve-a12:color(display-p3 0.992 0.992 1/0.937)}}}.light,.light-theme,:root{--slate-1:#fcfcfd;--slate-2:#f9f9fb;--slate-3:#f0f0f3;--slate-4:#e8e8ec;--slate-5:#e0e1e6;--slate-6:#d9d9e0;--slate-7:#cdced6;--slate-8:#b9bbc6;--slate-9:#8b8d98;--slate-10:#80838d;--slate-11:#60646c;--slate-12:#1c2024}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--slate-1:color(display-p3 0.988 0.988 0.992);--slate-2:color(display-p3 0.976 0.976 0.984);--slate-3:color(display-p3 0.94 0.941 0.953);--slate-4:color(display-p3 0.908 0.909 0.925);--slate-5:color(display-p3 0.88 0.881 0.901);--slate-6:color(display-p3 0.85 0.852 0.876);--slate-7:color(display-p3 0.805 0.808 0.838);--slate-8:color(display-p3 0.727 0.733 0.773);--slate-9:color(display-p3 0.547 0.553 0.592);--slate-10:color(display-p3 0.503 0.512 0.549);--slate-11:color(display-p3 0.379 0.392 0.421);--slate-12:color(display-p3 0.113 0.125 0.14)}}}.dark,.dark-theme{--slate-1:#111113;--slate-2:#18191b;--slate-3:#212225;--slate-4:#272a2d;--slate-5:#2e3135;--slate-6:#363a3f;--slate-7:#43484e;--slate-8:#5a6169;--slate-9:#696e77;--slate-10:#777b84;--slate-11:#b0b4ba;--slate-12:#edeef0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--slate-1:color(display-p3 0.067 0.067 0.074);--slate-2:color(display-p3 0.095 0.098 0.105);--slate-3:color(display-p3 0.13 0.135 0.145);--slate-4:color(display-p3 0.156 0.163 0.176);--slate-5:color(display-p3 0.183 0.191 0.206);--slate-6:color(display-p3 0.215 0.226 0.244);--slate-7:color(display-p3 0.265 0.28 0.302);--slate-8:color(display-p3 0.357 0.381 0.409);--slate-9:color(display-p3 0.415 0.431 0.463);--slate-10:color(display-p3 0.469 0.483 0.514);--slate-11:color(display-p3 0.692 0.704 0.728);--slate-12:color(display-p3 0.93 0.933 0.94)}}}.light,.light-theme,:root{--slate-a1:#00005503;--slate-a2:#00005506;--slate-a3:#0000330f;--slate-a4:#00002d17;--slate-a5:#0009321f;--slate-a6:#00002f26;--slate-a7:#00062e32;--slate-a8:#00083046;--slate-a9:#00051d74;--slate-a10:#00071b7f;--slate-a11:#0007149f;--slate-a12:#000509e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--slate-a1:color(display-p3 0.024 0.024 0.349/0.012);--slate-a2:color(display-p3 0.024 0.024 0.349/0.024);--slate-a3:color(display-p3 0.004 0.004 0.204/0.059);--slate-a4:color(display-p3 0.012 0.012 0.184/0.091);--slate-a5:color(display-p3 0.004 0.039 0.2/0.122);--slate-a6:color(display-p3 0.008 0.008 0.165/0.15);--slate-a7:color(display-p3 0.008 0.027 0.184/0.197);--slate-a8:color(display-p3 0.004 0.031 0.176/0.275);--slate-a9:color(display-p3 0.004 0.02 0.106/0.455);--slate-a10:color(display-p3 0.004 0.027 0.098/0.499);--slate-a11:color(display-p3 0 0.02 0.063/0.62);--slate-a12:color(display-p3 0 0.012 0.031/0.887)}}}.dark,.dark-theme{--slate-a1:#0000;--slate-a2:#d8f4f609;--slate-a3:#ddeaf814;--slate-a4:#d3edf81d;--slate-a5:#d9edfe25;--slate-a6:#d6ebfd30;--slate-a7:#d9edff40;--slate-a8:#d9edff5d;--slate-a9:#dfebfd6d;--slate-a10:#e5edfd7b;--slate-a11:#f1f7feb5;--slate-a12:#fcfdffef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--slate-a1:color(display-p3 0 0 0/0);--slate-a2:color(display-p3 0.875 0.992 1/0.034);--slate-a3:color(display-p3 0.882 0.933 0.992/0.077);--slate-a4:color(display-p3 0.882 0.953 0.996/0.111);--slate-a5:color(display-p3 0.878 0.929 0.996/0.145);--slate-a6:color(display-p3 0.882 0.949 0.996/0.183);--slate-a7:color(display-p3 0.882 0.929 1/0.246);--slate-a8:color(display-p3 0.871 0.937 1/0.361);--slate-a9:color(display-p3 0.898 0.937 1/0.42);--slate-a10:color(display-p3 0.918 0.945 1/0.475);--slate-a11:color(display-p3 0.949 0.969 0.996/0.708);--slate-a12:color(display-p3 0.988 0.992 1/0.937)}}}.light,.light-theme,:root{--sage-1:#fbfdfc;--sage-2:#f7f9f8;--sage-3:#eef1f0;--sage-4:#e6e9e8;--sage-5:#dfe2e0;--sage-6:#d7dad9;--sage-7:#cbcfcd;--sage-8:#b8bcba;--sage-9:#868e8b;--sage-10:#7c8481;--sage-11:#5f6563;--sage-12:#1a211e}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--sage-1:color(display-p3 0.986 0.992 0.988);--sage-2:color(display-p3 0.97 0.977 0.974);--sage-3:color(display-p3 0.935 0.944 0.94);--sage-4:color(display-p3 0.904 0.913 0.909);--sage-5:color(display-p3 0.875 0.885 0.88);--sage-6:color(display-p3 0.844 0.854 0.849);--sage-7:color(display-p3 0.8 0.811 0.806);--sage-8:color(display-p3 0.725 0.738 0.732);--sage-9:color(display-p3 0.531 0.556 0.546);--sage-10:color(display-p3 0.492 0.515 0.506);--sage-11:color(display-p3 0.377 0.395 0.389);--sage-12:color(display-p3 0.107 0.129 0.118)}}}.dark,.dark-theme{--sage-1:#101211;--sage-2:#171918;--sage-3:#202221;--sage-4:#272a29;--sage-5:#2e3130;--sage-6:#373b39;--sage-7:#444947;--sage-8:#5b625f;--sage-9:#63706b;--sage-10:#717d79;--sage-11:#adb5b2;--sage-12:#eceeed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sage-1:color(display-p3 0.064 0.07 0.067);--sage-2:color(display-p3 0.092 0.098 0.094);--sage-3:color(display-p3 0.128 0.135 0.131);--sage-4:color(display-p3 0.155 0.164 0.159);--sage-5:color(display-p3 0.183 0.193 0.188);--sage-6:color(display-p3 0.218 0.23 0.224);--sage-7:color(display-p3 0.269 0.285 0.277);--sage-8:color(display-p3 0.362 0.382 0.373);--sage-9:color(display-p3 0.398 0.438 0.421);--sage-10:color(display-p3 0.453 0.49 0.474);--sage-11:color(display-p3 0.685 0.709 0.697);--sage-12:color(display-p3 0.927 0.933 0.93)}}}.light,.light-theme,:root{--sage-a1:#00804004;--sage-a2:#00402008;--sage-a3:#002d1e11;--sage-a4:#001f1519;--sage-a5:#00180820;--sage-a6:#00140d28;--sage-a7:#00140a34;--sage-a8:#000f0847;--sage-a9:#00110b79;--sage-a10:#00100a83;--sage-a11:#000a07a0;--sage-a12:#000805e5}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--sage-a1:color(display-p3 0.024 0.514 0.267/0.016);--sage-a2:color(display-p3 0.02 0.267 0.145/0.032);--sage-a3:color(display-p3 0.008 0.184 0.125/0.067);--sage-a4:color(display-p3 0.012 0.094 0.051/0.095);--sage-a5:color(display-p3 0.008 0.098 0.035/0.126);--sage-a6:color(display-p3 0.004 0.078 0.027/0.157);--sage-a7:color(display-p3 0 0.059 0.039/0.2);--sage-a8:color(display-p3 0.004 0.047 0.031/0.275);--sage-a9:color(display-p3 0.004 0.059 0.035/0.471);--sage-a10:color(display-p3 0 0.047 0.031/0.51);--sage-a11:color(display-p3 0 0.031 0.02/0.624);--sage-a12:color(display-p3 0 0.027 0.012/0.895)}}}.dark,.dark-theme{--sage-a1:#0000;--sage-a2:#f0f2f108;--sage-a3:#f3f5f412;--sage-a4:#f2fefd1a;--sage-a5:#f1fbfa22;--sage-a6:#edfbf42d;--sage-a7:#edfcf73c;--sage-a8:#ebfdf657;--sage-a9:#dffdf266;--sage-a10:#e5fdf674;--sage-a11:#f4fefbb0;--sage-a12:#fdfffeed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sage-a1:color(display-p3 0 0 0/0);--sage-a2:color(display-p3 0.976 0.988 0.984/0.03);--sage-a3:color(display-p3 0.992 0.945 0.941/0.072);--sage-a4:color(display-p3 0.988 0.996 0.992/0.102);--sage-a5:color(display-p3 0.992 1 0.996/0.131);--sage-a6:color(display-p3 0.973 1 0.976/0.173);--sage-a7:color(display-p3 0.957 1 0.976/0.233);--sage-a8:color(display-p3 0.957 1 0.984/0.334);--sage-a9:color(display-p3 0.902 1 0.957/0.397);--sage-a10:color(display-p3 0.929 1 0.973/0.452);--sage-a11:color(display-p3 0.969 1 0.988/0.688);--sage-a12:color(display-p3 0.992 1 0.996/0.929)}}}.light,.light-theme,:root{--olive-1:#fcfdfc;--olive-2:#f8faf8;--olive-3:#eff1ef;--olive-4:#e7e9e7;--olive-5:#dfe2df;--olive-6:#d7dad7;--olive-7:#cccfcc;--olive-8:#b9bcb8;--olive-9:#898e87;--olive-10:#7f847d;--olive-11:#60655f;--olive-12:#1d211c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--olive-1:color(display-p3 0.989 0.992 0.989);--olive-2:color(display-p3 0.974 0.98 0.973);--olive-3:color(display-p3 0.939 0.945 0.937);--olive-4:color(display-p3 0.907 0.914 0.905);--olive-5:color(display-p3 0.878 0.885 0.875);--olive-6:color(display-p3 0.846 0.855 0.843);--olive-7:color(display-p3 0.803 0.812 0.8);--olive-8:color(display-p3 0.727 0.738 0.723);--olive-9:color(display-p3 0.541 0.556 0.532);--olive-10:color(display-p3 0.5 0.515 0.491);--olive-11:color(display-p3 0.38 0.395 0.374);--olive-12:color(display-p3 0.117 0.129 0.111)}}}.dark,.dark-theme{--olive-1:#111210;--olive-2:#181917;--olive-3:#212220;--olive-4:#282a27;--olive-5:#2f312e;--olive-6:#383a36;--olive-7:#454843;--olive-8:#5c625b;--olive-9:#687066;--olive-10:#767d74;--olive-11:#afb5ad;--olive-12:#eceeec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--olive-1:color(display-p3 0.067 0.07 0.063);--olive-2:color(display-p3 0.095 0.098 0.091);--olive-3:color(display-p3 0.131 0.135 0.126);--olive-4:color(display-p3 0.158 0.163 0.153);--olive-5:color(display-p3 0.186 0.192 0.18);--olive-6:color(display-p3 0.221 0.229 0.215);--olive-7:color(display-p3 0.273 0.284 0.266);--olive-8:color(display-p3 0.365 0.382 0.359);--olive-9:color(display-p3 0.414 0.438 0.404);--olive-10:color(display-p3 0.467 0.49 0.458);--olive-11:color(display-p3 0.69 0.709 0.682);--olive-12:color(display-p3 0.927 0.933 0.926)}}}.light,.light-theme,:root{--olive-a1:#00550003;--olive-a2:#00490007;--olive-a3:#00200010;--olive-a4:#00160018;--olive-a5:#00180020;--olive-a6:#00140028;--olive-a7:#000f0033;--olive-a8:#040f0047;--olive-a9:#050f0078;--olive-a10:#040e0082;--olive-a11:#020a00a0;--olive-a12:#010600e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--olive-a1:color(display-p3 0.024 0.349 0.024/0.012);--olive-a2:color(display-p3 0.024 0.302 0.024/0.028);--olive-a3:color(display-p3 0.008 0.129 0.008/0.063);--olive-a4:color(display-p3 0.012 0.094 0.012/0.095);--olive-a5:color(display-p3 0.035 0.098 0.008/0.126);--olive-a6:color(display-p3 0.027 0.078 0.004/0.157);--olive-a7:color(display-p3 0.02 0.059 0/0.2);--olive-a8:color(display-p3 0.02 0.059 0.004/0.279);--olive-a9:color(display-p3 0.02 0.051 0.004/0.467);--olive-a10:color(display-p3 0.024 0.047 0/0.51);--olive-a11:color(display-p3 0.012 0.039 0/0.628);--olive-a12:color(display-p3 0.008 0.024 0/0.891)}}}.dark,.dark-theme{--olive-a1:#0000;--olive-a2:#f1f2f008;--olive-a3:#f4f5f312;--olive-a4:#f3fef21a;--olive-a5:#f2fbf122;--olive-a6:#f4faed2c;--olive-a7:#f2fced3b;--olive-a8:#edfdeb57;--olive-a9:#ebfde766;--olive-a10:#f0fdec74;--olive-a11:#f6fef4b0;--olive-a12:#fdfffded}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--olive-a1:color(display-p3 0 0 0/0);--olive-a2:color(display-p3 0.984 0.988 0.976/0.03);--olive-a3:color(display-p3 0.992 0.996 0.988/0.068);--olive-a4:color(display-p3 0.953 0.996 0.949/0.102);--olive-a5:color(display-p3 0.969 1 0.965/0.131);--olive-a6:color(display-p3 0.973 1 0.969/0.169);--olive-a7:color(display-p3 0.98 1 0.961/0.228);--olive-a8:color(display-p3 0.961 1 0.957/0.334);--olive-a9:color(display-p3 0.949 1 0.922/0.397);--olive-a10:color(display-p3 0.953 1 0.941/0.452);--olive-a11:color(display-p3 0.976 1 0.965/0.688);--olive-a12:color(display-p3 0.992 1 0.992/0.929)}}}.light,.light-theme,:root{--sand-1:#fdfdfc;--sand-2:#f9f9f8;--sand-3:#f1f0ef;--sand-4:#e9e8e6;--sand-5:#e2e1de;--sand-6:#dad9d6;--sand-7:#cfceca;--sand-8:#bcbbb5;--sand-9:#8d8d86;--sand-10:#82827c;--sand-11:#63635e;--sand-12:#21201c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--sand-1:color(display-p3 0.992 0.992 0.989);--sand-2:color(display-p3 0.977 0.977 0.973);--sand-3:color(display-p3 0.943 0.942 0.936);--sand-4:color(display-p3 0.913 0.912 0.903);--sand-5:color(display-p3 0.885 0.883 0.873);--sand-6:color(display-p3 0.854 0.852 0.839);--sand-7:color(display-p3 0.813 0.81 0.794);--sand-8:color(display-p3 0.738 0.734 0.713);--sand-9:color(display-p3 0.553 0.553 0.528);--sand-10:color(display-p3 0.511 0.511 0.488);--sand-11:color(display-p3 0.388 0.388 0.37);--sand-12:color(display-p3 0.129 0.126 0.111)}}}.dark,.dark-theme{--sand-1:#111110;--sand-2:#191918;--sand-3:#222221;--sand-4:#2a2a28;--sand-5:#31312e;--sand-6:#3b3a37;--sand-7:#494844;--sand-8:#62605b;--sand-9:#6f6d66;--sand-10:#7c7b74;--sand-11:#b5b3ad;--sand-12:#eeeeec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sand-1:color(display-p3 0.067 0.067 0.063);--sand-2:color(display-p3 0.098 0.098 0.094);--sand-3:color(display-p3 0.135 0.135 0.129);--sand-4:color(display-p3 0.164 0.163 0.156);--sand-5:color(display-p3 0.193 0.192 0.183);--sand-6:color(display-p3 0.23 0.229 0.217);--sand-7:color(display-p3 0.285 0.282 0.267);--sand-8:color(display-p3 0.384 0.378 0.357);--sand-9:color(display-p3 0.434 0.428 0.403);--sand-10:color(display-p3 0.487 0.481 0.456);--sand-11:color(display-p3 0.707 0.703 0.68);--sand-12:color(display-p3 0.933 0.933 0.926)}}}.light,.light-theme,:root{--sand-a1:#55550003;--sand-a2:#25250007;--sand-a3:#20100010;--sand-a4:#1f150019;--sand-a5:#1f180021;--sand-a6:#19130029;--sand-a7:#19140035;--sand-a8:#1915014a;--sand-a9:#0f0f0079;--sand-a10:#0c0c0083;--sand-a11:#080800a1;--sand-a12:#060500e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.light,.light-theme,:root{--sand-a1:color(display-p3 0.349 0.349 0.024/0.012);--sand-a2:color(display-p3 0.161 0.161 0.024/0.028);--sand-a3:color(display-p3 0.067 0.067 0.008/0.063);--sand-a4:color(display-p3 0.129 0.129 0.012/0.099);--sand-a5:color(display-p3 0.098 0.067 0.008/0.126);--sand-a6:color(display-p3 0.102 0.075 0.004/0.161);--sand-a7:color(display-p3 0.098 0.098 0.004/0.208);--sand-a8:color(display-p3 0.086 0.075 0.004/0.287);--sand-a9:color(display-p3 0.051 0.051 0.004/0.471);--sand-a10:color(display-p3 0.047 0.047 0/0.514);--sand-a11:color(display-p3 0.031 0.031 0/0.632);--sand-a12:color(display-p3 0.024 0.02 0/0.891)}}}.dark,.dark-theme{--sand-a1:#0000;--sand-a2:#f4f4f309;--sand-a3:#f6f6f513;--sand-a4:#fefef31b;--sand-a5:#fbfbeb23;--sand-a6:#fffaed2d;--sand-a7:#fffbed3c;--sand-a8:#fff9eb57;--sand-a9:#fffae965;--sand-a10:#fffdee73;--sand-a11:#fffcf4b0;--sand-a12:#fffffded}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sand-a1:color(display-p3 0 0 0/0);--sand-a2:color(display-p3 0.992 0.992 0.988/0.034);--sand-a3:color(display-p3 0.996 0.996 0.992/0.072);--sand-a4:color(display-p3 0.992 0.992 0.953/0.106);--sand-a5:color(display-p3 1 1 0.965/0.135);--sand-a6:color(display-p3 1 0.976 0.929/0.177);--sand-a7:color(display-p3 1 0.984 0.929/0.236);--sand-a8:color(display-p3 1 0.976 0.925/0.341);--sand-a9:color(display-p3 1 0.98 0.925/0.395);--sand-a10:color(display-p3 1 0.992 0.933/0.45);--sand-a11:color(display-p3 1 0.996 0.961/0.685);--sand-a12:color(display-p3 1 1 0.992/0.929)}}}:root{--black-a1:#0000000d;--black-a2:#0000001a;--black-a3:#00000026;--black-a4:#0003;--black-a5:#0000004d;--black-a6:#0006;--black-a7:#00000080;--black-a8:#0009;--black-a9:#000000b3;--black-a10:#000c;--black-a11:#000000e6;--black-a12:#000000f2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root{--black-a1:color(display-p3 0 0 0/0.05);--black-a2:color(display-p3 0 0 0/0.1);--black-a3:color(display-p3 0 0 0/0.15);--black-a4:color(display-p3 0 0 0/0.2);--black-a5:color(display-p3 0 0 0/0.3);--black-a6:color(display-p3 0 0 0/0.4);--black-a7:color(display-p3 0 0 0/0.5);--black-a8:color(display-p3 0 0 0/0.6);--black-a9:color(display-p3 0 0 0/0.7);--black-a10:color(display-p3 0 0 0/0.8);--black-a11:color(display-p3 0 0 0/0.9);--black-a12:color(display-p3 0 0 0/0.95)}}}:root{--white-a1:#ffffff0d;--white-a2:#ffffff1a;--white-a3:#ffffff26;--white-a4:#fff3;--white-a5:#ffffff4d;--white-a6:#fff6;--white-a7:#ffffff80;--white-a8:#fff9;--white-a9:#ffffffb3;--white-a10:#fffc;--white-a11:#ffffffe6;--white-a12:#fffffff2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root{--white-a1:color(display-p3 1 1 1/0.05);--white-a2:color(display-p3 1 1 1/0.1);--white-a3:color(display-p3 1 1 1/0.15);--white-a4:color(display-p3 1 1 1/0.2);--white-a5:color(display-p3 1 1 1/0.3);--white-a6:color(display-p3 1 1 1/0.4);--white-a7:color(display-p3 1 1 1/0.5);--white-a8:color(display-p3 1 1 1/0.6);--white-a9:color(display-p3 1 1 1/0.7);--white-a10:color(display-p3 1 1 1/0.8);--white-a11:color(display-p3 1 1 1/0.9);--white-a12:color(display-p3 1 1 1/0.95)}}}:root{--tomato-9-contrast:#fff;--red-9-contrast:#fff;--ruby-9-contrast:#fff;--crimson-9-contrast:#fff;--pink-9-contrast:#fff;--plum-9-contrast:#fff;--purple-9-contrast:#fff;--violet-9-contrast:#fff;--iris-9-contrast:#fff;--indigo-9-contrast:#fff;--blue-9-contrast:#fff;--cyan-9-contrast:#fff;--teal-9-contrast:#fff;--jade-9-contrast:#fff;--green-9-contrast:#fff;--grass-9-contrast:#fff;--orange-9-contrast:#fff;--brown-9-contrast:#fff;--sky-9-contrast:#1c2024;--mint-9-contrast:#1a211e;--lime-9-contrast:#1d211c;--yellow-9-contrast:#21201c;--amber-9-contrast:#21201c;--gold-9-contrast:#fff;--bronze-9-contrast:#fff;--gray-9-contrast:#fff}.light,.light-theme,:root{--gray-surface:#fffc;--mauve-surface:#fffc;--slate-surface:#fffc;--sage-surface:#fffc;--olive-surface:#fffc;--sand-surface:#fffc;--tomato-surface:#fff6f5cc;--red-surface:#fff5f5cc;--ruby-surface:#fff5f6cc;--crimson-surface:#fef5f8cc;--pink-surface:#fef5facc;--plum-surface:#fdf5fdcc;--purple-surface:#faf5fecc;--violet-surface:#f9f6ffcc;--iris-surface:#f6f6ffcc;--indigo-surface:#f5f8ffcc;--blue-surface:#f1f9ffcc;--cyan-surface:#eff9facc;--teal-surface:#f0faf8cc;--jade-surface:#f1faf5cc;--green-surface:#f1faf4cc;--grass-surface:#f3faf3cc;--brown-surface:#fbf8f4cc;--bronze-surface:#fdf5f3cc;--gold-surface:#f9f8efcc;--sky-surface:#eef9fdcc;--mint-surface:#effaf8cc;--lime-surface:#f6f9f0cc;--yellow-surface:#fefbe4cc;--amber-surface:#fefae4cc;--orange-surface:#fff5e9cc;@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){&{--gray-surface:color(display-p3 1 1 1/0.8);--mauve-surface:color(display-p3 1 1 1/0.8);--slate-surface:color(display-p3 1 1 1/0.8);--sage-surface:color(display-p3 1 1 1/0.8);--olive-surface:color(display-p3 1 1 1/0.8);--sand-surface:color(display-p3 1 1 1/0.8);--tomato-surface:color(display-p3 0.9922 0.9647 0.9608/0.8);--red-surface:color(display-p3 0.9961 0.9647 0.9647/0.8);--ruby-surface:color(display-p3 0.9961 0.9647 0.9647/0.8);--crimson-surface:color(display-p3 0.9922 0.9608 0.9725/0.8);--pink-surface:color(display-p3 0.9922 0.9608 0.9804/0.8);--plum-surface:color(display-p3 0.9843 0.9647 0.9843/0.8);--purple-surface:color(display-p3 0.9804 0.9647 0.9922/0.8);--violet-surface:color(display-p3 0.9725 0.9647 0.9961/0.8);--iris-surface:color(display-p3 0.9647 0.9647 0.9961/0.8);--indigo-surface:color(display-p3 0.9647 0.9725 0.9961/0.8);--blue-surface:color(display-p3 0.9529 0.9765 0.9961/0.8);--cyan-surface:color(display-p3 0.9412 0.9765 0.9804/0.8);--teal-surface:color(display-p3 0.9451 0.9804 0.9725/0.8);--jade-surface:color(display-p3 0.9529 0.9804 0.9608/0.8);--green-surface:color(display-p3 0.9569 0.9804 0.9608/0.8);--grass-surface:color(display-p3 0.9569 0.9804 0.9569/0.8);--brown-surface:color(display-p3 0.9843 0.9725 0.9569/0.8);--bronze-surface:color(display-p3 0.9843 0.9608 0.9529/0.8);--gold-surface:color(display-p3 0.9765 0.9725 0.9412/0.8);--sky-surface:color(display-p3 0.9412 0.9765 0.9843/0.8);--mint-surface:color(display-p3 0.9451 0.9804 0.9725/0.8);--lime-surface:color(display-p3 0.9725 0.9765 0.9412/0.8);--yellow-surface:color(display-p3 0.9961 0.9922 0.902/0.8);--amber-surface:color(display-p3 0.9922 0.9843 0.902/0.8);--orange-surface:color(display-p3 0.9961 0.9608 0.9176/0.8)}}}}.dark,.dark-theme{--gray-surface:#21212180;--mauve-surface:#22212380;--slate-surface:#1f212380;--sage-surface:#1e201f80;--olive-surface:#1f201e80;--sand-surface:#21212080;--tomato-surface:#2d191580;--red-surface:#2f151780;--ruby-surface:#2b191d80;--crimson-surface:#2f151f80;--pink-surface:#31132980;--plum-surface:#2f152f80;--purple-surface:#2b173580;--violet-surface:#25193980;--iris-surface:#1d1b3980;--indigo-surface:#171d3b80;--blue-surface:#11213d80;--cyan-surface:#11252d80;--teal-surface:#13272580;--jade-surface:#13271f80;--green-surface:#15251d80;--grass-surface:#19231b80;--brown-surface:#271f1b80;--bronze-surface:#27211d80;--gold-surface:#25231d80;--sky-surface:#13233b80;--mint-surface:#15272780;--lime-surface:#1b211580;--yellow-surface:#231f1380;--amber-surface:#271f1380;--orange-surface:#271d1380;@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){&{--gray-surface:color(display-p3 0.1255 0.1255 0.1255/0.5);--mauve-surface:color(display-p3 0.1333 0.1255 0.1333/0.5);--slate-surface:color(display-p3 0.1176 0.1255 0.1333/0.5);--sage-surface:color(display-p3 0.1176 0.1255 0.1176/0.5);--olive-surface:color(display-p3 0.1176 0.1255 0.1176/0.5);--sand-surface:color(display-p3 0.1255 0.1255 0.1255/0.5);--tomato-surface:color(display-p3 0.1569 0.0941 0.0784/0.5);--red-surface:color(display-p3 0.1647 0.0863 0.0863/0.5);--ruby-surface:color(display-p3 0.1569 0.0941 0.1098/0.5);--crimson-surface:color(display-p3 0.1647 0.0863 0.1176/0.5);--pink-surface:color(display-p3 0.1725 0.0784 0.149/0.5);--plum-surface:color(display-p3 0.1647 0.0863 0.1725/0.5);--purple-surface:color(display-p3 0.149 0.0941 0.1961/0.5);--violet-surface:color(display-p3 0.1333 0.102 0.2118/0.5);--iris-surface:color(display-p3 0.1098 0.102 0.2118/0.5);--indigo-surface:color(display-p3 0.0941 0.1098 0.2196/0.5);--blue-surface:color(display-p3 0.0706 0.1255 0.2196/0.5);--cyan-surface:color(display-p3 0.0784 0.1412 0.1725/0.5);--teal-surface:color(display-p3 0.0863 0.149 0.1412/0.5);--jade-surface:color(display-p3 0.0863 0.149 0.1176/0.5);--green-surface:color(display-p3 0.0941 0.1412 0.1098/0.5);--grass-surface:color(display-p3 0.102 0.1333 0.102/0.5);--brown-surface:color(display-p3 0.1412 0.1176 0.102/0.5);--bronze-surface:color(display-p3 0.1412 0.1255 0.1176/0.5);--gold-surface:color(display-p3 0.1412 0.1333 0.1098/0.5);--sky-surface:color(display-p3 0.0863 0.1333 0.2196/0.5);--mint-surface:color(display-p3 0.0941 0.149 0.1412/0.5);--lime-surface:color(display-p3 0.1098 0.1255 0.0784/0.5);--yellow-surface:color(display-p3 0.1333 0.1176 0.0706/0.5);--amber-surface:color(display-p3 0.1412 0.1176 0.0784/0.5);--orange-surface:color(display-p3 0.1412 0.1098 0.0706/0.5)}}}}[data-accent-color=tomato]{--color-surface-accent:var(--tomato-surface);--accent-1:var(--tomato-1);--accent-2:var(--tomato-2);--accent-3:var(--tomato-3);--accent-4:var(--tomato-4);--accent-5:var(--tomato-5);--accent-6:var(--tomato-6);--accent-7:var(--tomato-7);--accent-8:var(--tomato-8);--accent-9:var(--tomato-9);--accent-9-contrast:var(--tomato-9-contrast);--accent-10:var(--tomato-10);--accent-11:var(--tomato-11);--accent-12:var(--tomato-12);--accent-a1:var(--tomato-a1);--accent-a2:var(--tomato-a2);--accent-a3:var(--tomato-a3);--accent-a4:var(--tomato-a4);--accent-a5:var(--tomato-a5);--accent-a6:var(--tomato-a6);--accent-a7:var(--tomato-a7);--accent-a8:var(--tomato-a8);--accent-a9:var(--tomato-a9);--accent-a10:var(--tomato-a10);--accent-a11:var(--tomato-a11);--accent-a12:var(--tomato-a12)}[data-accent-color=red]{--color-surface-accent:var(--red-surface);--accent-1:var(--red-1);--accent-2:var(--red-2);--accent-3:var(--red-3);--accent-4:var(--red-4);--accent-5:var(--red-5);--accent-6:var(--red-6);--accent-7:var(--red-7);--accent-8:var(--red-8);--accent-9:var(--red-9);--accent-9-contrast:var(--red-9-contrast);--accent-10:var(--red-10);--accent-11:var(--red-11);--accent-12:var(--red-12);--accent-a1:var(--red-a1);--accent-a2:var(--red-a2);--accent-a3:var(--red-a3);--accent-a4:var(--red-a4);--accent-a5:var(--red-a5);--accent-a6:var(--red-a6);--accent-a7:var(--red-a7);--accent-a8:var(--red-a8);--accent-a9:var(--red-a9);--accent-a10:var(--red-a10);--accent-a11:var(--red-a11);--accent-a12:var(--red-a12)}[data-accent-color=ruby]{--color-surface-accent:var(--ruby-surface);--accent-1:var(--ruby-1);--accent-2:var(--ruby-2);--accent-3:var(--ruby-3);--accent-4:var(--ruby-4);--accent-5:var(--ruby-5);--accent-6:var(--ruby-6);--accent-7:var(--ruby-7);--accent-8:var(--ruby-8);--accent-9:var(--ruby-9);--accent-9-contrast:var(--ruby-9-contrast);--accent-10:var(--ruby-10);--accent-11:var(--ruby-11);--accent-12:var(--ruby-12);--accent-a1:var(--ruby-a1);--accent-a2:var(--ruby-a2);--accent-a3:var(--ruby-a3);--accent-a4:var(--ruby-a4);--accent-a5:var(--ruby-a5);--accent-a6:var(--ruby-a6);--accent-a7:var(--ruby-a7);--accent-a8:var(--ruby-a8);--accent-a9:var(--ruby-a9);--accent-a10:var(--ruby-a10);--accent-a11:var(--ruby-a11);--accent-a12:var(--ruby-a12)}[data-accent-color=crimson]{--color-surface-accent:var(--crimson-surface);--accent-1:var(--crimson-1);--accent-2:var(--crimson-2);--accent-3:var(--crimson-3);--accent-4:var(--crimson-4);--accent-5:var(--crimson-5);--accent-6:var(--crimson-6);--accent-7:var(--crimson-7);--accent-8:var(--crimson-8);--accent-9:var(--crimson-9);--accent-9-contrast:var(--crimson-9-contrast);--accent-10:var(--crimson-10);--accent-11:var(--crimson-11);--accent-12:var(--crimson-12);--accent-a1:var(--crimson-a1);--accent-a2:var(--crimson-a2);--accent-a3:var(--crimson-a3);--accent-a4:var(--crimson-a4);--accent-a5:var(--crimson-a5);--accent-a6:var(--crimson-a6);--accent-a7:var(--crimson-a7);--accent-a8:var(--crimson-a8);--accent-a9:var(--crimson-a9);--accent-a10:var(--crimson-a10);--accent-a11:var(--crimson-a11);--accent-a12:var(--crimson-a12)}[data-accent-color=pink]{--color-surface-accent:var(--pink-surface);--accent-1:var(--pink-1);--accent-2:var(--pink-2);--accent-3:var(--pink-3);--accent-4:var(--pink-4);--accent-5:var(--pink-5);--accent-6:var(--pink-6);--accent-7:var(--pink-7);--accent-8:var(--pink-8);--accent-9:var(--pink-9);--accent-9-contrast:var(--pink-9-contrast);--accent-10:var(--pink-10);--accent-11:var(--pink-11);--accent-12:var(--pink-12);--accent-a1:var(--pink-a1);--accent-a2:var(--pink-a2);--accent-a3:var(--pink-a3);--accent-a4:var(--pink-a4);--accent-a5:var(--pink-a5);--accent-a6:var(--pink-a6);--accent-a7:var(--pink-a7);--accent-a8:var(--pink-a8);--accent-a9:var(--pink-a9);--accent-a10:var(--pink-a10);--accent-a11:var(--pink-a11);--accent-a12:var(--pink-a12)}[data-accent-color=plum]{--color-surface-accent:var(--plum-surface);--accent-1:var(--plum-1);--accent-2:var(--plum-2);--accent-3:var(--plum-3);--accent-4:var(--plum-4);--accent-5:var(--plum-5);--accent-6:var(--plum-6);--accent-7:var(--plum-7);--accent-8:var(--plum-8);--accent-9:var(--plum-9);--accent-9-contrast:var(--plum-9-contrast);--accent-10:var(--plum-10);--accent-11:var(--plum-11);--accent-12:var(--plum-12);--accent-a1:var(--plum-a1);--accent-a2:var(--plum-a2);--accent-a3:var(--plum-a3);--accent-a4:var(--plum-a4);--accent-a5:var(--plum-a5);--accent-a6:var(--plum-a6);--accent-a7:var(--plum-a7);--accent-a8:var(--plum-a8);--accent-a9:var(--plum-a9);--accent-a10:var(--plum-a10);--accent-a11:var(--plum-a11);--accent-a12:var(--plum-a12)}[data-accent-color=purple]{--color-surface-accent:var(--purple-surface);--accent-1:var(--purple-1);--accent-2:var(--purple-2);--accent-3:var(--purple-3);--accent-4:var(--purple-4);--accent-5:var(--purple-5);--accent-6:var(--purple-6);--accent-7:var(--purple-7);--accent-8:var(--purple-8);--accent-9:var(--purple-9);--accent-9-contrast:var(--purple-9-contrast);--accent-10:var(--purple-10);--accent-11:var(--purple-11);--accent-12:var(--purple-12);--accent-a1:var(--purple-a1);--accent-a2:var(--purple-a2);--accent-a3:var(--purple-a3);--accent-a4:var(--purple-a4);--accent-a5:var(--purple-a5);--accent-a6:var(--purple-a6);--accent-a7:var(--purple-a7);--accent-a8:var(--purple-a8);--accent-a9:var(--purple-a9);--accent-a10:var(--purple-a10);--accent-a11:var(--purple-a11);--accent-a12:var(--purple-a12)}[data-accent-color=violet]{--color-surface-accent:var(--violet-surface);--accent-1:var(--violet-1);--accent-2:var(--violet-2);--accent-3:var(--violet-3);--accent-4:var(--violet-4);--accent-5:var(--violet-5);--accent-6:var(--violet-6);--accent-7:var(--violet-7);--accent-8:var(--violet-8);--accent-9:var(--violet-9);--accent-9-contrast:var(--violet-9-contrast);--accent-10:var(--violet-10);--accent-11:var(--violet-11);--accent-12:var(--violet-12);--accent-a1:var(--violet-a1);--accent-a2:var(--violet-a2);--accent-a3:var(--violet-a3);--accent-a4:var(--violet-a4);--accent-a5:var(--violet-a5);--accent-a6:var(--violet-a6);--accent-a7:var(--violet-a7);--accent-a8:var(--violet-a8);--accent-a9:var(--violet-a9);--accent-a10:var(--violet-a10);--accent-a11:var(--violet-a11);--accent-a12:var(--violet-a12)}[data-accent-color=iris]{--color-surface-accent:var(--iris-surface);--accent-1:var(--iris-1);--accent-2:var(--iris-2);--accent-3:var(--iris-3);--accent-4:var(--iris-4);--accent-5:var(--iris-5);--accent-6:var(--iris-6);--accent-7:var(--iris-7);--accent-8:var(--iris-8);--accent-9:var(--iris-9);--accent-9-contrast:var(--iris-9-contrast);--accent-10:var(--iris-10);--accent-11:var(--iris-11);--accent-12:var(--iris-12);--accent-a1:var(--iris-a1);--accent-a2:var(--iris-a2);--accent-a3:var(--iris-a3);--accent-a4:var(--iris-a4);--accent-a5:var(--iris-a5);--accent-a6:var(--iris-a6);--accent-a7:var(--iris-a7);--accent-a8:var(--iris-a8);--accent-a9:var(--iris-a9);--accent-a10:var(--iris-a10);--accent-a11:var(--iris-a11);--accent-a12:var(--iris-a12)}[data-accent-color=indigo]{--color-surface-accent:var(--indigo-surface);--accent-1:var(--indigo-1);--accent-2:var(--indigo-2);--accent-3:var(--indigo-3);--accent-4:var(--indigo-4);--accent-5:var(--indigo-5);--accent-6:var(--indigo-6);--accent-7:var(--indigo-7);--accent-8:var(--indigo-8);--accent-9:var(--indigo-9);--accent-9-contrast:var(--indigo-9-contrast);--accent-10:var(--indigo-10);--accent-11:var(--indigo-11);--accent-12:var(--indigo-12);--accent-a1:var(--indigo-a1);--accent-a2:var(--indigo-a2);--accent-a3:var(--indigo-a3);--accent-a4:var(--indigo-a4);--accent-a5:var(--indigo-a5);--accent-a6:var(--indigo-a6);--accent-a7:var(--indigo-a7);--accent-a8:var(--indigo-a8);--accent-a9:var(--indigo-a9);--accent-a10:var(--indigo-a10);--accent-a11:var(--indigo-a11);--accent-a12:var(--indigo-a12)}[data-accent-color=blue]{--color-surface-accent:var(--blue-surface);--accent-1:var(--blue-1);--accent-2:var(--blue-2);--accent-3:var(--blue-3);--accent-4:var(--blue-4);--accent-5:var(--blue-5);--accent-6:var(--blue-6);--accent-7:var(--blue-7);--accent-8:var(--blue-8);--accent-9:var(--blue-9);--accent-9-contrast:var(--blue-9-contrast);--accent-10:var(--blue-10);--accent-11:var(--blue-11);--accent-12:var(--blue-12);--accent-a1:var(--blue-a1);--accent-a2:var(--blue-a2);--accent-a3:var(--blue-a3);--accent-a4:var(--blue-a4);--accent-a5:var(--blue-a5);--accent-a6:var(--blue-a6);--accent-a7:var(--blue-a7);--accent-a8:var(--blue-a8);--accent-a9:var(--blue-a9);--accent-a10:var(--blue-a10);--accent-a11:var(--blue-a11);--accent-a12:var(--blue-a12)}[data-accent-color=cyan]{--color-surface-accent:var(--cyan-surface);--accent-1:var(--cyan-1);--accent-2:var(--cyan-2);--accent-3:var(--cyan-3);--accent-4:var(--cyan-4);--accent-5:var(--cyan-5);--accent-6:var(--cyan-6);--accent-7:var(--cyan-7);--accent-8:var(--cyan-8);--accent-9:var(--cyan-9);--accent-9-contrast:var(--cyan-9-contrast);--accent-10:var(--cyan-10);--accent-11:var(--cyan-11);--accent-12:var(--cyan-12);--accent-a1:var(--cyan-a1);--accent-a2:var(--cyan-a2);--accent-a3:var(--cyan-a3);--accent-a4:var(--cyan-a4);--accent-a5:var(--cyan-a5);--accent-a6:var(--cyan-a6);--accent-a7:var(--cyan-a7);--accent-a8:var(--cyan-a8);--accent-a9:var(--cyan-a9);--accent-a10:var(--cyan-a10);--accent-a11:var(--cyan-a11);--accent-a12:var(--cyan-a12)}[data-accent-color=teal]{--color-surface-accent:var(--teal-surface);--accent-1:var(--teal-1);--accent-2:var(--teal-2);--accent-3:var(--teal-3);--accent-4:var(--teal-4);--accent-5:var(--teal-5);--accent-6:var(--teal-6);--accent-7:var(--teal-7);--accent-8:var(--teal-8);--accent-9:var(--teal-9);--accent-9-contrast:var(--teal-9-contrast);--accent-10:var(--teal-10);--accent-11:var(--teal-11);--accent-12:var(--teal-12);--accent-a1:var(--teal-a1);--accent-a2:var(--teal-a2);--accent-a3:var(--teal-a3);--accent-a4:var(--teal-a4);--accent-a5:var(--teal-a5);--accent-a6:var(--teal-a6);--accent-a7:var(--teal-a7);--accent-a8:var(--teal-a8);--accent-a9:var(--teal-a9);--accent-a10:var(--teal-a10);--accent-a11:var(--teal-a11);--accent-a12:var(--teal-a12)}[data-accent-color=jade]{--color-surface-accent:var(--jade-surface);--accent-1:var(--jade-1);--accent-2:var(--jade-2);--accent-3:var(--jade-3);--accent-4:var(--jade-4);--accent-5:var(--jade-5);--accent-6:var(--jade-6);--accent-7:var(--jade-7);--accent-8:var(--jade-8);--accent-9:var(--jade-9);--accent-9-contrast:var(--jade-9-contrast);--accent-10:var(--jade-10);--accent-11:var(--jade-11);--accent-12:var(--jade-12);--accent-a1:var(--jade-a1);--accent-a2:var(--jade-a2);--accent-a3:var(--jade-a3);--accent-a4:var(--jade-a4);--accent-a5:var(--jade-a5);--accent-a6:var(--jade-a6);--accent-a7:var(--jade-a7);--accent-a8:var(--jade-a8);--accent-a9:var(--jade-a9);--accent-a10:var(--jade-a10);--accent-a11:var(--jade-a11);--accent-a12:var(--jade-a12)}[data-accent-color=green]{--color-surface-accent:var(--green-surface);--accent-1:var(--green-1);--accent-2:var(--green-2);--accent-3:var(--green-3);--accent-4:var(--green-4);--accent-5:var(--green-5);--accent-6:var(--green-6);--accent-7:var(--green-7);--accent-8:var(--green-8);--accent-9:var(--green-9);--accent-9-contrast:var(--green-9-contrast);--accent-10:var(--green-10);--accent-11:var(--green-11);--accent-12:var(--green-12);--accent-a1:var(--green-a1);--accent-a2:var(--green-a2);--accent-a3:var(--green-a3);--accent-a4:var(--green-a4);--accent-a5:var(--green-a5);--accent-a6:var(--green-a6);--accent-a7:var(--green-a7);--accent-a8:var(--green-a8);--accent-a9:var(--green-a9);--accent-a10:var(--green-a10);--accent-a11:var(--green-a11);--accent-a12:var(--green-a12)}[data-accent-color=grass]{--color-surface-accent:var(--grass-surface);--accent-1:var(--grass-1);--accent-2:var(--grass-2);--accent-3:var(--grass-3);--accent-4:var(--grass-4);--accent-5:var(--grass-5);--accent-6:var(--grass-6);--accent-7:var(--grass-7);--accent-8:var(--grass-8);--accent-9:var(--grass-9);--accent-9-contrast:var(--grass-9-contrast);--accent-10:var(--grass-10);--accent-11:var(--grass-11);--accent-12:var(--grass-12);--accent-a1:var(--grass-a1);--accent-a2:var(--grass-a2);--accent-a3:var(--grass-a3);--accent-a4:var(--grass-a4);--accent-a5:var(--grass-a5);--accent-a6:var(--grass-a6);--accent-a7:var(--grass-a7);--accent-a8:var(--grass-a8);--accent-a9:var(--grass-a9);--accent-a10:var(--grass-a10);--accent-a11:var(--grass-a11);--accent-a12:var(--grass-a12)}[data-accent-color=orange]{--color-surface-accent:var(--orange-surface);--accent-1:var(--orange-1);--accent-2:var(--orange-2);--accent-3:var(--orange-3);--accent-4:var(--orange-4);--accent-5:var(--orange-5);--accent-6:var(--orange-6);--accent-7:var(--orange-7);--accent-8:var(--orange-8);--accent-9:var(--orange-9);--accent-9-contrast:var(--orange-9-contrast);--accent-10:var(--orange-10);--accent-11:var(--orange-11);--accent-12:var(--orange-12);--accent-a1:var(--orange-a1);--accent-a2:var(--orange-a2);--accent-a3:var(--orange-a3);--accent-a4:var(--orange-a4);--accent-a5:var(--orange-a5);--accent-a6:var(--orange-a6);--accent-a7:var(--orange-a7);--accent-a8:var(--orange-a8);--accent-a9:var(--orange-a9);--accent-a10:var(--orange-a10);--accent-a11:var(--orange-a11);--accent-a12:var(--orange-a12)}[data-accent-color=brown]{--color-surface-accent:var(--brown-surface);--accent-1:var(--brown-1);--accent-2:var(--brown-2);--accent-3:var(--brown-3);--accent-4:var(--brown-4);--accent-5:var(--brown-5);--accent-6:var(--brown-6);--accent-7:var(--brown-7);--accent-8:var(--brown-8);--accent-9:var(--brown-9);--accent-9-contrast:var(--brown-9-contrast);--accent-10:var(--brown-10);--accent-11:var(--brown-11);--accent-12:var(--brown-12);--accent-a1:var(--brown-a1);--accent-a2:var(--brown-a2);--accent-a3:var(--brown-a3);--accent-a4:var(--brown-a4);--accent-a5:var(--brown-a5);--accent-a6:var(--brown-a6);--accent-a7:var(--brown-a7);--accent-a8:var(--brown-a8);--accent-a9:var(--brown-a9);--accent-a10:var(--brown-a10);--accent-a11:var(--brown-a11);--accent-a12:var(--brown-a12)}[data-accent-color=sky]{--color-surface-accent:var(--sky-surface);--accent-1:var(--sky-1);--accent-2:var(--sky-2);--accent-3:var(--sky-3);--accent-4:var(--sky-4);--accent-5:var(--sky-5);--accent-6:var(--sky-6);--accent-7:var(--sky-7);--accent-8:var(--sky-8);--accent-9:var(--sky-9);--accent-9-contrast:var(--sky-9-contrast);--accent-10:var(--sky-10);--accent-11:var(--sky-11);--accent-12:var(--sky-12);--accent-a1:var(--sky-a1);--accent-a2:var(--sky-a2);--accent-a3:var(--sky-a3);--accent-a4:var(--sky-a4);--accent-a5:var(--sky-a5);--accent-a6:var(--sky-a6);--accent-a7:var(--sky-a7);--accent-a8:var(--sky-a8);--accent-a9:var(--sky-a9);--accent-a10:var(--sky-a10);--accent-a11:var(--sky-a11);--accent-a12:var(--sky-a12)}[data-accent-color=mint]{--color-surface-accent:var(--mint-surface);--accent-1:var(--mint-1);--accent-2:var(--mint-2);--accent-3:var(--mint-3);--accent-4:var(--mint-4);--accent-5:var(--mint-5);--accent-6:var(--mint-6);--accent-7:var(--mint-7);--accent-8:var(--mint-8);--accent-9:var(--mint-9);--accent-9-contrast:var(--mint-9-contrast);--accent-10:var(--mint-10);--accent-11:var(--mint-11);--accent-12:var(--mint-12);--accent-a1:var(--mint-a1);--accent-a2:var(--mint-a2);--accent-a3:var(--mint-a3);--accent-a4:var(--mint-a4);--accent-a5:var(--mint-a5);--accent-a6:var(--mint-a6);--accent-a7:var(--mint-a7);--accent-a8:var(--mint-a8);--accent-a9:var(--mint-a9);--accent-a10:var(--mint-a10);--accent-a11:var(--mint-a11);--accent-a12:var(--mint-a12)}[data-accent-color=lime]{--color-surface-accent:var(--lime-surface);--accent-1:var(--lime-1);--accent-2:var(--lime-2);--accent-3:var(--lime-3);--accent-4:var(--lime-4);--accent-5:var(--lime-5);--accent-6:var(--lime-6);--accent-7:var(--lime-7);--accent-8:var(--lime-8);--accent-9:var(--lime-9);--accent-9-contrast:var(--lime-9-contrast);--accent-10:var(--lime-10);--accent-11:var(--lime-11);--accent-12:var(--lime-12);--accent-a1:var(--lime-a1);--accent-a2:var(--lime-a2);--accent-a3:var(--lime-a3);--accent-a4:var(--lime-a4);--accent-a5:var(--lime-a5);--accent-a6:var(--lime-a6);--accent-a7:var(--lime-a7);--accent-a8:var(--lime-a8);--accent-a9:var(--lime-a9);--accent-a10:var(--lime-a10);--accent-a11:var(--lime-a11);--accent-a12:var(--lime-a12)}[data-accent-color=yellow]{--color-surface-accent:var(--yellow-surface);--accent-1:var(--yellow-1);--accent-2:var(--yellow-2);--accent-3:var(--yellow-3);--accent-4:var(--yellow-4);--accent-5:var(--yellow-5);--accent-6:var(--yellow-6);--accent-7:var(--yellow-7);--accent-8:var(--yellow-8);--accent-9:var(--yellow-9);--accent-9-contrast:var(--yellow-9-contrast);--accent-10:var(--yellow-10);--accent-11:var(--yellow-11);--accent-12:var(--yellow-12);--accent-a1:var(--yellow-a1);--accent-a2:var(--yellow-a2);--accent-a3:var(--yellow-a3);--accent-a4:var(--yellow-a4);--accent-a5:var(--yellow-a5);--accent-a6:var(--yellow-a6);--accent-a7:var(--yellow-a7);--accent-a8:var(--yellow-a8);--accent-a9:var(--yellow-a9);--accent-a10:var(--yellow-a10);--accent-a11:var(--yellow-a11);--accent-a12:var(--yellow-a12)}[data-accent-color=amber]{--color-surface-accent:var(--amber-surface);--accent-1:var(--amber-1);--accent-2:var(--amber-2);--accent-3:var(--amber-3);--accent-4:var(--amber-4);--accent-5:var(--amber-5);--accent-6:var(--amber-6);--accent-7:var(--amber-7);--accent-8:var(--amber-8);--accent-9:var(--amber-9);--accent-9-contrast:var(--amber-9-contrast);--accent-10:var(--amber-10);--accent-11:var(--amber-11);--accent-12:var(--amber-12);--accent-a1:var(--amber-a1);--accent-a2:var(--amber-a2);--accent-a3:var(--amber-a3);--accent-a4:var(--amber-a4);--accent-a5:var(--amber-a5);--accent-a6:var(--amber-a6);--accent-a7:var(--amber-a7);--accent-a8:var(--amber-a8);--accent-a9:var(--amber-a9);--accent-a10:var(--amber-a10);--accent-a11:var(--amber-a11);--accent-a12:var(--amber-a12)}[data-accent-color=gold]{--color-surface-accent:var(--gold-surface);--accent-1:var(--gold-1);--accent-2:var(--gold-2);--accent-3:var(--gold-3);--accent-4:var(--gold-4);--accent-5:var(--gold-5);--accent-6:var(--gold-6);--accent-7:var(--gold-7);--accent-8:var(--gold-8);--accent-9:var(--gold-9);--accent-9-contrast:var(--gold-9-contrast);--accent-10:var(--gold-10);--accent-11:var(--gold-11);--accent-12:var(--gold-12);--accent-a1:var(--gold-a1);--accent-a2:var(--gold-a2);--accent-a3:var(--gold-a3);--accent-a4:var(--gold-a4);--accent-a5:var(--gold-a5);--accent-a6:var(--gold-a6);--accent-a7:var(--gold-a7);--accent-a8:var(--gold-a8);--accent-a9:var(--gold-a9);--accent-a10:var(--gold-a10);--accent-a11:var(--gold-a11);--accent-a12:var(--gold-a12)}[data-accent-color=bronze]{--color-surface-accent:var(--bronze-surface);--accent-1:var(--bronze-1);--accent-2:var(--bronze-2);--accent-3:var(--bronze-3);--accent-4:var(--bronze-4);--accent-5:var(--bronze-5);--accent-6:var(--bronze-6);--accent-7:var(--bronze-7);--accent-8:var(--bronze-8);--accent-9:var(--bronze-9);--accent-9-contrast:var(--bronze-9-contrast);--accent-10:var(--bronze-10);--accent-11:var(--bronze-11);--accent-12:var(--bronze-12);--accent-a1:var(--bronze-a1);--accent-a2:var(--bronze-a2);--accent-a3:var(--bronze-a3);--accent-a4:var(--bronze-a4);--accent-a5:var(--bronze-a5);--accent-a6:var(--bronze-a6);--accent-a7:var(--bronze-a7);--accent-a8:var(--bronze-a8);--accent-a9:var(--bronze-a9);--accent-a10:var(--bronze-a10);--accent-a11:var(--bronze-a11);--accent-a12:var(--bronze-a12)}[data-accent-color=gray]{--color-surface-accent:var(--gray-surface);--accent-1:var(--gray-1);--accent-2:var(--gray-2);--accent-3:var(--gray-3);--accent-4:var(--gray-4);--accent-5:var(--gray-5);--accent-6:var(--gray-6);--accent-7:var(--gray-7);--accent-8:var(--gray-8);--accent-9:var(--gray-9);--accent-9-contrast:var(--gray-9-contrast);--accent-10:var(--gray-10);--accent-11:var(--gray-11);--accent-12:var(--gray-12);--accent-a1:var(--gray-a1);--accent-a2:var(--gray-a2);--accent-a3:var(--gray-a3);--accent-a4:var(--gray-a4);--accent-a5:var(--gray-a5);--accent-a6:var(--gray-a6);--accent-a7:var(--gray-a7);--accent-a8:var(--gray-a8);--accent-a9:var(--gray-a9);--accent-a10:var(--gray-a10);--accent-a11:var(--gray-a11);--accent-a12:var(--gray-a12)}:root{--sy-f-sys:-apple-system,BlinkMacSystemFont,Segoe UI,Oxygen,Ubuntu,Droid Sans,Helvetica Neue;--sy-f-cjk:PingFang SC,Hiragino Sans GB,Droid Sans Fallback,Microsoft YaHei;--sy-f-heading:var(--sy-f-sys),var(--sy-f-cjk),sans-serif;--sy-f-text:var(--sy-f-sys),var(--sy-f-cjk),sans-serif;--sy-f-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--sy-s-banner-height:0rem;--sy-s-navbar-height:56px;--sy-s-offset-top:calc(var(--sy-s-navbar-height) + var(--sy-s-banner-height));--sy-c-divider:var(--gray-4);--sy-c-border:var(--gray-5);--sy-c-text:var(--gray-12);--sy-c-light:var(--gray-11);--sy-c-bold:var(--slate-12);--sy-c-heading:var(--sage-12);--sy-c-link:var(--accent-9);--sy-c-link-hover:var(--accent-a11);--sy-c-background:#fff;--sy-c-surface:var(--gray-a2);--sy-c-overlay:var(--black-a5);--sy-c-background-contrast:#000;--sy-c-foot-text:var(--sy-c-text);--sy-c-foot-background:var(--slate-2);--sy-c-foot-divider:var(--sy-c-divider);--sy-dropdown-shadow:0 12px 32px var(--gray-a6),0 2px 6px var(--gray-a4)}[data-accent-color=amber],[data-accent-color=lime],[data-accent-color=mint],[data-accent-color=sky],[data-accent-color=yellow]{--sy-c-link:var(--accent-a10)}html.light{color-scheme:light;--sy-c-background:#fff;--sy-c-background-contrast:#000}html.dark{color-scheme:dark;--sy-c-background:var(--slate-1);--sy-c-overlay:var(--white-a2);--sy-c-background-contrast:var(--white-a10);--sy-c-foot-background:var(--black-a11);--sy-c-foot-divider:var(--black-a12)}html{color:var(--sy-c-text);background-color:var(--sy-c-background)}:root{--lucide-alert-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3zM12 9v4m0 4h.01'/%3E%3C/svg%3E");--lucide-arrows-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m7 15 5 5 5-5M7 9l5-5 5 5'/%3E%3C/svg%3E");--lucide-award-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='8' r='6'/%3E%3Cpath d='M15.477 12.89 17 22l-5-3-5 3 1.523-9.11'/%3E%3C/svg%3E");--lucide-bell-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9m-4.27 13a2 2 0 0 1-3.46 0'/%3E%3C/svg%3E");--lucide-bookmark-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z'/%3E%3C/svg%3E");--lucide-calendar-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='18' height='18' x='3' y='4' rx='2' ry='2'/%3E%3Cpath d='M16 2v4M8 2v4m-5 4h18'/%3E%3C/svg%3E");--lucide-check-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");--lucide-chevron-down-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-down'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");--lucide-chevron-left-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-left'%3E%3Cpath d='m15 18-6-6 6-6'/%3E%3C/svg%3E");--lucide-chevron-right-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-right'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E");--lucide-chevron-up-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-up'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E");--lucide-close-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--lucide-external-link-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M13 5h6v6m0-6L5 19'/%3E%3C/svg%3E");--lucide-flame-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z'/%3E%3C/svg%3E");--lucide-git-fork-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='18' r='3'/%3E%3Ccircle cx='6' cy='6' r='3'/%3E%3Ccircle cx='18' cy='6' r='3'/%3E%3Cpath d='M18 9v1a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V9m6 3v3'/%3E%3C/svg%3E");--lucide-help-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3m.08 4h.01'/%3E%3C/svg%3E");--lucide-languages-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-languages'%3E%3Cpath d='m5 8 6 6m-7 0 6-6 2-3M2 5h12M7 2h1m14 20-5-10-5 10m2-4h6'/%3E%3C/svg%3E");--lucide-laptop-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='18' height='12' x='3' y='4' rx='2' ry='2'/%3E%3Cpath d='M2 20h20'/%3E%3C/svg%3E");--lucide-link-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E");--lucide-menu-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-menu'%3E%3Cpath d='M4 12h16M4 6h16M4 18h16'/%3E%3C/svg%3E");--lucide-milestone-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6zm-6 7v8m0-18v3'/%3E%3C/svg%3E");--lucide-moon-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M12 3a6.364 6.364 0 0 0 9 9 9 9 0 1 1-9-9z'/%3E%3C/svg%3E");--lucide-outdent-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m7 8-4 4 4 4m14-4H11m10-6H11m10 12H11'/%3E%3C/svg%3E");--lucide-rocket-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09zM12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z'/%3E%3Cpath d='M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0m1 7v5s3.03-.55 4-2c1.08-1.62 0-5 0-5'/%3E%3C/svg%3E");--lucide-skull-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='9' cy='12' r='1'/%3E%3Ccircle cx='15' cy='12' r='1'/%3E%3Cpath d='M8 20v2h8v-2m-3.5-3-.5-1-.5 1h1z'/%3E%3Cpath d='M16 20a2 2 0 0 0 1.56-3.25 8 8 0 1 0-11.12 0A2 2 0 0 0 8 20'/%3E%3C/svg%3E");--lucide-star-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/%3E%3C/svg%3E");--lucide-sun-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32 1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E");--lucide-zap-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M13 2 3 14h9l-1 8 10-12h-9l1-8z'/%3E%3C/svg%3E")}.i-icon.alert,.i-lucide.alert{--icon-url:var(--lucide-alert-url)}.i-icon.arrows,.i-lucide.arrows{--icon-url:var(--lucide-arrows-url)}.i-icon.award,.i-lucide.award{--icon-url:var(--lucide-award-url)}.i-icon.bell,.i-lucide.bell{--icon-url:var(--lucide-bell-url)}.i-icon.bookmark,.i-lucide.bookmark{--icon-url:var(--lucide-bookmark-url)}.i-icon.calendar,.i-lucide.calendar{--icon-url:var(--lucide-calendar-url)}.i-icon.check,.i-lucide.check{--icon-url:var(--lucide-check-url)}.i-icon.chevron-down,.i-lucide.chevron-down{--icon-url:var(--lucide-chevron-down-url)}.i-icon.chevron-left,.i-lucide.chevron-left{--icon-url:var(--lucide-chevron-left-url)}.i-icon.chevron-right,.i-lucide.chevron-right{--icon-url:var(--lucide-chevron-right-url)}.i-icon.chevron-up,.i-lucide.chevron-up{--icon-url:var(--lucide-chevron-up-url)}.i-icon.close,.i-lucide.close{--icon-url:var(--lucide-close-url)}.i-icon.external-link,.i-lucide.external-link{--icon-url:var(--lucide-external-link-url)}.i-icon.flame,.i-lucide.flame{--icon-url:var(--lucide-flame-url)}.i-icon.git-fork,.i-lucide.git-fork{--icon-url:var(--lucide-git-fork-url)}.i-icon.help,.i-lucide.help{--icon-url:var(--lucide-help-url)}.i-icon.languages,.i-lucide.languages{--icon-url:var(--lucide-languages-url)}.i-icon.laptop,.i-lucide.laptop{--icon-url:var(--lucide-laptop-url)}.i-icon.link,.i-lucide.link{--icon-url:var(--lucide-link-url)}.i-icon.menu,.i-lucide.menu{--icon-url:var(--lucide-menu-url)}.i-icon.milestone,.i-lucide.milestone{--icon-url:var(--lucide-milestone-url)}.i-icon.moon,.i-lucide.moon{--icon-url:var(--lucide-moon-url)}.i-icon.outdent,.i-lucide.outdent{--icon-url:var(--lucide-outdent-url)}.i-icon.rocket,.i-lucide.rocket{--icon-url:var(--lucide-rocket-url)}.i-icon.skull,.i-lucide.skull{--icon-url:var(--lucide-skull-url)}.i-icon.star,.i-lucide.star{--icon-url:var(--lucide-star-url)}.i-icon.sun,.i-lucide.sun{--icon-url:var(--lucide-sun-url)}.i-icon.zap,.i-lucide.zap{--icon-url:var(--lucide-zap-url)}:root{--simpleicons-bitbucket-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M.778 1.213a.768.768 0 0 0-.768.892l3.263 19.81c.084.5.515.868 1.022.873H19.95a.772.772 0 0 0 .77-.646l3.27-20.03a.768.768 0 0 0-.768-.891zM14.52 15.53H9.522L8.17 8.466h7.561z'/%3E%3C/svg%3E");--simpleicons-discord-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z'/%3E%3C/svg%3E");--simpleicons-git-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.546 10.93 13.067.452a1.55 1.55 0 0 0-2.188 0L8.708 2.627l2.76 2.76a1.838 1.838 0 0 1 2.327 2.341l2.658 2.66a1.838 1.838 0 0 1 1.9 3.039 1.837 1.837 0 0 1-2.6 0 1.846 1.846 0 0 1-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348a1.848 1.848 0 0 1 0 2.6 1.844 1.844 0 0 1-2.609 0 1.834 1.834 0 0 1 0-2.598c.182-.18.387-.316.605-.406V8.835a1.834 1.834 0 0 1-.996-2.41L7.636 3.7.45 10.881c-.6.605-.6 1.584 0 2.189l10.48 10.477a1.545 1.545 0 0 0 2.186 0l10.43-10.43a1.544 1.544 0 0 0 0-2.187'/%3E%3C/svg%3E");--simpleicons-github-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E");--simpleicons-gitlab-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m23.6 9.593-.033-.086L20.3.98a.851.851 0 0 0-.336-.405.875.875 0 0 0-1 .054.875.875 0 0 0-.29.44L16.47 7.818H7.537L5.332 1.07a.857.857 0 0 0-.29-.441.875.875 0 0 0-1-.054.859.859 0 0 0-.336.405L.433 9.502l-.032.086a6.066 6.066 0 0 0 2.012 7.01l.01.009.03.021 4.977 3.727 2.462 1.863 1.5 1.132a1.008 1.008 0 0 0 1.22 0l1.499-1.132 2.461-1.863 5.006-3.75.013-.01a6.068 6.068 0 0 0 2.01-7.002z'/%3E%3C/svg%3E");--simpleicons-linkedin-url:url("data:image/svg+xml;utf8,%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3ELinkedIn%3C/title%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E");--simpleicons-mastodon-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E");--simpleicons-readthedocs-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.732 0a59.316 59.316 0 0 0-4.977.218V24a62.933 62.933 0 0 1 3.619-.687c.17-.028.34-.053.509-.078.215-.033.43-.066.644-.096l.205-.03zm1.18.003V22.96a61.042 61.042 0 0 1 12.333-.213V1.485A60.859 60.859 0 0 0 8.912.003zm1.707 1.81a.59.59 0 0 1 .015 0c3.06.088 6.125.404 9.167.95a.59.59 0 0 1 .476.686.59.59 0 0 1-.569.484.59.59 0 0 1-.116-.009 60.622 60.622 0 0 0-8.992-.931.59.59 0 0 1-.573-.607.59.59 0 0 1 .592-.572zm-4.212.028a.59.59 0 0 1 .578.565.59.59 0 0 1-.564.614 59.74 59.74 0 0 0-2.355.144.59.59 0 0 1-.04.002.59.59 0 0 1-.595-.542.59.59 0 0 1 .54-.635c.8-.065 1.6-.114 2.401-.148a.59.59 0 0 1 .035 0zm4.202 2.834a.59.59 0 0 1 .015 0 61.6 61.6 0 0 1 9.167.8.59.59 0 0 1 .488.677.59.59 0 0 1-.602.494.59.59 0 0 1-.076-.006 60.376 60.376 0 0 0-8.99-.786.59.59 0 0 1-.584-.596.59.59 0 0 1 .582-.583zm-4.211.097a.59.59 0 0 1 .587.555.59.59 0 0 1-.554.622c-.786.046-1.572.107-2.356.184a.59.59 0 0 1-.04.003.59.59 0 0 1-.603-.533.59.59 0 0 1 .53-.644c.8-.078 1.599-.14 2.4-.187a.59.59 0 0 1 .036 0zM10.6 7.535a.59.59 0 0 1 .015 0c3.06-.013 6.125.204 9.167.65a.59.59 0 0 1 .498.67.59.59 0 0 1-.593.504.59.59 0 0 1-.076-.006 60.142 60.142 0 0 0-8.992-.638.59.59 0 0 1-.592-.588.59.59 0 0 1 .573-.592zm1.153 2.846a61.093 61.093 0 0 1 8.02.515.59.59 0 0 1 .509.66.59.59 0 0 1-.586.514.59.59 0 0 1-.076-.005 59.982 59.982 0 0 0-8.99-.492.59.59 0 0 1-.603-.577.59.59 0 0 1 .578-.603c.382-.008.765-.012 1.148-.012zm1.139 2.832a60.92 60.92 0 0 1 6.871.394.59.59 0 0 1 .52.652.59.59 0 0 1-.577.523.59.59 0 0 1-.076-.004 59.936 59.936 0 0 0-8.991-.344.59.59 0 0 1-.61-.568.59.59 0 0 1 .567-.611c.765-.028 1.53-.042 2.296-.042z'/%3E%3C/svg%3E");--simpleicons-reddit-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286A.72.72 0 0 0 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0Zm4.388 3.199a1.999 1.999 0 1 1-1.947 2.46v.002a2.368 2.368 0 0 0-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363a2.802 2.802 0 1 1 2.908 4.753c-.088 3.256-3.637 5.876-7.997 5.876-4.361 0-7.905-2.617-7.998-5.87a2.8 2.8 0 0 1 1.189-5.34c.645 0 1.239.218 1.712.585 1.275-.79 2.881-1.291 4.64-1.365v-.01a3.229 3.229 0 0 1 2.88-3.207 2 2 0 0 1 1.959-1.595Zm-8.085 8.376c-.784 0-1.459.78-1.506 1.797-.047 1.016.64 1.429 1.426 1.429.786 0 1.371-.369 1.418-1.385.047-1.017-.553-1.841-1.338-1.841Zm7.406 0c-.786 0-1.385.824-1.338 1.841.047 1.017.634 1.385 1.418 1.385.785 0 1.473-.413 1.426-1.429-.046-1.017-.721-1.797-1.506-1.797Zm-3.703 4.013c-.974 0-1.907.048-2.77.135a.222.222 0 0 0-.183.305 3.199 3.199 0 0 0 2.953 1.964 3.2 3.2 0 0 0 2.953-1.964.222.222 0 0 0-.184-.305 27.75 27.75 0 0 0-2.769-.135Z'/%3E%3C/svg%3E");--simpleicons-slack-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z'/%3E%3C/svg%3E");--simpleicons-x-twitter-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'/%3E%3C/svg%3E");--simpleicons-youtube-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E")}.i-icon.bitbucket,.i-simpleicons.bitbucket{--icon-url:var(--simpleicons-bitbucket-url)}.i-icon.discord,.i-simpleicons.discord{--icon-url:var(--simpleicons-discord-url)}.i-icon.git,.i-simpleicons.git{--icon-url:var(--simpleicons-git-url)}.i-icon.github,.i-simpleicons.github{--icon-url:var(--simpleicons-github-url)}.i-icon.gitlab,.i-simpleicons.gitlab{--icon-url:var(--simpleicons-gitlab-url)}.i-icon.linkedin,.i-simpleicons.linkedin{--icon-url:var(--simpleicons-linkedin-url)}.i-icon.mastodon,.i-simpleicons.mastodon{--icon-url:var(--simpleicons-mastodon-url)}.i-icon.readthedocs,.i-simpleicons.readthedocs{--icon-url:var(--simpleicons-readthedocs-url)}.i-icon.reddit,.i-simpleicons.reddit{--icon-url:var(--simpleicons-reddit-url)}.i-icon.slack,.i-simpleicons.slack{--icon-url:var(--simpleicons-slack-url)}.i-icon.x-twitter,.i-simpleicons.x-twitter{--icon-url:var(--simpleicons-x-twitter-url)}.i-icon.youtube,.i-simpleicons.youtube{--icon-url:var(--simpleicons-youtube-url)}.hamburger{position:relative;display:inline-block;width:16px;height:14px;overflow:hidden;cursor:pointer}.hamburger>span{position:absolute;width:16px;height:2px;left:0;background-color:var(--sy-c-text);transition:top .25s,transform .25s}.hamburger_1{top:0}.hamburger_2{top:6px}.hamburger_3{top:12px}button[aria-expanded=true] .hamburger .hamburger_1{top:6px;transform:translate(0) rotate(225deg)}button[aria-expanded=true] .hamburger .hamburger_2{top:6px;transform:translate(18px)}button[aria-expanded=true] .hamburger .hamburger_3{top:6px;transform:translate(0) rotate(135deg)}.searchbox{position:relative}.searchbox input{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;padding:6px 12px;font-size:.92rem;font-family:var(--sy-f-text);border-radius:6px;outline:0;background:var(--sy-c-surface)}.searchbox button,.searchbox kbd{position:absolute;font-size:.68rem;font-weight:600;font-family:var(--sy-f-mono);padding:2px 6px;margin:6px;right:0;border-radius:3px;border:1px solid var(--sy-c-border);background-color:var(--sy-c-background);opacity:1;transition:opacity .2s ease}.searchbox input:focus+kbd{opacity:0}.searchform{display:flex;position:relative;align-items:center}.searchform input[name=q]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;padding:6px 12px;font-size:.92rem;font-family:var(--sy-f-text);border-radius:6px;outline:0;background:var(--sy-c-surface)}.searchform input[name=q]+button{position:absolute;font-size:.68rem;font-weight:600;font-family:var(--sy-f-text);padding:2px 6px;margin:6px;right:0;border-radius:3px;border:1px solid var(--sy-c-divider);background-color:var(--sy-c-background);opacity:1;transition:opacity .2s ease}.search .highlighted{background-color:var(--accent-a4)}#search-results{border-top:1px solid var(--sy-c-border)}#search-results h2{margin-top:2rem;margin-bottom:.725rem}#search-results .search-summary{font-weight:500;color:var(--sy-c-light)}#search-results ul.search{list-style-type:none;margin-left:0;padding-left:0;padding-top:.625rem;padding-bottom:2rem}#search-results ul.search>li{padding-left:0}#search-results ul.search>li+li{padding-top:1rem;border-top:1px solid var(--sy-c-divider)}#search-results ul.search li>a{font-weight:600}#search-results ul.search p.context{margin-top:.5rem;font-size:.875rem}.demo{border:1px solid var(--sy-c-border);border-radius:6px}.demo-code .highlight>pre{border-bottom-left-radius:0;border-bottom-right-radius:0}.demo-result{padding:1rem}.container.image-1{border:.5rem solid var(--accent-a3);border-radius:6px}.container.image-1>img{border-radius:4px;margin:0}.container.image-2{border:1px solid var(--sy-c-border);padding:1rem;border-radius:6px}.container.image-2>img{margin:0}.container.buttons{margin:2rem 0 4.2rem}.container.buttons>p{display:flex;gap:1rem}.container.buttons a{display:inline-block;padding:0 2rem;line-height:2.6rem;border-radius:2.6rem;border:2px solid var(--sy-c-border);font-weight:600;background-color:var(--sy-c-surface);transition:all .2s ease}.container.buttons a:first-child{color:var(--accent-9-contrast);background-color:var(--accent-9);border-color:var(--accent-9)}.container.buttons a:hover{color:var(--sy-c-bold);border-color:var(--accent-9);background-color:var(--sy-c-background)}#ethical-ad-placement .ethical-sidebar{position:relative;background-color:var(--sy-c-surface);border:none;padding:.8rem}#ethical-ad-placement .ethical-text a{color:var(--sy-c-text)!important}#ethical-ad-placement .ethical-text a:hover{color:var(--sy-c-link-hover)!important}.sy-main #ethical-ad-placement .ethical-sidebar{margin-left:0;max-width:380px}.sy-main #ethical-ad-placement .ethical-image-link{flex-shrink:0;margin-right:.4rem}.sy-main #ethical-ad-placement .ethical-content{display:flex}.sy-main #ethical-ad-placement .ethical-text{margin-top:0}.sy-main #ethical-ad-placement .ethical-callout{position:absolute;right:.4rem;bottom:.4rem}#carbonads{margin:1rem 0;position:relative;display:block;background-color:var(--sy-c-surface);border:none;border-radius:8px;padding:.8rem .8rem 1.6rem}#carbonads a{border:0;font-weight:400}#carbonads img{margin:0}.carbon-wrap{display:flex;align-items:center;justify-content:space-between;flex-direction:column}.carbon-text{display:block;margin:.5rem 0;line-height:1.42;font-size:.78rem;text-align:center}.carbon-text:hover{color:var(--sy-c-link-hover)}.carbon-poweredby{position:absolute;opacity:.68;right:.8rem;bottom:.5rem;font-size:.68rem;text-transform:uppercase}.carbon-poweredby:hover{text-decoration:underline}.sy-main #carbonads{max-width:380px;padding:1rem;margin-top:1.6rem}.sy-main .carbon-wrap{flex-direction:row;align-items:flex-start}.sy-main .carbon-text{text-align:left;margin-top:0;margin-left:1rem;font-size:.86rem}.bsa-bar{justify-content:space-between;padding:15px 20px;border-radius:10px;box-shadow:inset 0 0 2px #00000026;text-decoration:none}.bsa-bar,.bsa-main{display:flex;flex-flow:row nowrap;align-items:center}.bsa-main{flex-grow:1;justify-content:center;margin:0 auto}.bsa-img{max-height:40px;margin-right:20px;line-height:0}.bsa-details{display:flex;flex-flow:column nowrap;margin-right:20px}.bsa-tagline{margin-bottom:3px;font-weight:600;font-size:9px;line-height:1;letter-spacing:1.5px;text-transform:uppercase}.bsa-desc{max-width:600px;font-weight:400;font-size:12px;line-height:1.4;letter-spacing:1px}.bsa-cta{padding:10px 16px;transform:translateY(-1px);border-radius:3px;font-weight:600;font-size:10px;line-height:1;letter-spacing:1px;text-transform:uppercase;white-space:nowrap;transition:all .3s ease-in-out}@media (max-width:940px){.bsa-details{font-size:14px;margin-right:0}.bsa-cta{display:none}}@media (min-width:768px) and (max-width:820px){.bsa-img{display:none}}@media (max-width:480px){.bsa-img{display:none}}.repo-stats{margin-bottom:1rem;padding:.5rem;border:1px solid var(--sy-c-divider);border-radius:6px}.repo-stats:hover{background-color:var(--sy-c-surface)}.repo-stats-count{color:var(--sy-c-light)}.repo-stats strong{font-weight:500;font-family:var(--sy-f-mono);color:inherit}.edit-this-page{border-top:1px solid var(--sy-c-divider);margin:1rem 0;padding:.5rem 0;font-size:.8rem;font-weight:600}.repo-stats+.edit-this-page{border-top:0;margin-top:0;padding-top:0}.edit-this-page a{color:var(--sy-c-text)}.edit-this-page a:hover{color:var(--sy-c-link-hover)}.edit-this-page a:after{content:" →"}.back-to-top{display:none;align-items:center;gap:.25rem;position:fixed;z-index:10;bottom:68px;left:50%;transform:translateX(-50%);background:var(--sy-c-background);border-radius:2rem;box-shadow:0 .2rem .5rem #0000000d,0 0 1px 0 #6b728080;font-size:.8rem;padding:.4rem .8rem .4rem .6rem}.dark .back-to-top{background:var(--slate-2);box-shadow:0 .2rem .5rem #ffffff0d,0 0 1px 0 #9aa4b880}.back-to-top:hover{color:var(--accent-9-contrast);background:var(--accent-9)}.back-to-top svg{height:1rem;width:1rem;fill:currentColor;display:inline-block}.back-to-top[data-visible=true]{display:flex}.icon-link,.icon-link span{display:inline-block}.icon-link span{vertical-align:middle}.icon-link .icon{padding:.1rem;border-radius:6px;border:1px solid var(--sy-c-border);margin-right:.4rem;opacity:.8}.icon-link svg{width:1.5rem;height:1.5rem}.icon-link:hover .icon{opacity:1}.announcement{position:sticky;top:0;left:0;width:100%;padding:.8rem 2rem;display:flex;align-items:center;color:var(--sy-c-banner,var(--accent-9-contrast));background-color:var(--sy-c-banner-bg,var(--accent-a11));z-index:20}.announcement a{text-decoration:underline}.announcement ::-moz-selection{color:var(--sy-c-banner,var(--accent-9-contrast))}.announcement ::selection{color:var(--sy-c-banner,var(--accent-9-contrast))}.announcement-inner{width:100%}.announcement-close{position:absolute;top:.8rem;right:1rem}.sy-head{position:sticky;top:var(--sy-s-banner-height);height:var(--sy-s-navbar-height);background-color:initial;z-index:20}.sy-head-blur{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);background-color:var(--sand-a1);box-shadow:0 0 var(--sy-c-background-contrast),0 2px 4px var(--gray-a1),0 1px 0 var(--sy-c-divider);z-index:-1}.sy-head-inner{display:flex;padding-left:max(env(safe-area-inset-right),1.5rem);padding-right:max(env(safe-area-inset-right),1rem);justify-content:space-between;align-items:center;height:var(--sy-s-navbar-height)}.sy-head-brand img{height:28px}.sy-head-brand .dark-logo,.sy-head-brand img+strong{display:none}.dark .sy-head-brand .dark-logo{display:inline}.dark .sy-head-brand .light-logo{display:none}.light .sy-head-brand .light-logo{display:inline}.light .sy-head-brand .dark-logo{display:none}.sy-head-links a,.sy-head-links button{padding:.5rem;font-size:.95rem;font-weight:500;white-space:nowrap}.sy-head-links .link i.external-link{font-size:68%;opacity:.6;color:var(--sy-c-light);margin-left:2px}.sy-head-links .link>ul a{display:block;white-space:normal}.sy-head-links .link>ul a:hover{background:var(--sy-c-surface);border-radius:6px}.sy-head-links .link>ul small{display:block;color:var(--sy-c-light);font-weight:400}.sy-head-socials,.sy-head-socials a{display:flex;align-items:center}.sy-head-socials a{padding:.5rem}.sy-head-actions button{height:var(--sy-s-navbar-height);padding:0 .5rem}@media (max-width:767px){body[data-expanded-headnav=true]{overflow:hidden}.sy-head-nav{display:none;position:fixed;top:var(--sy-s-offset-top);bottom:0;left:0;right:0;padding:4rem 1.8rem 0;width:100%;box-sizing:border-box;border-top:1px solid var(--sy-c-divider);background-color:var(--sy-c-background);overflow-y:auto}.sy-head-nav._expanded{display:block}.sy-head-links{margin-left:auto;margin-right:auto}.sy-head-links .link{margin:.5rem 0}.sy-head-links .link i.chevron{display:none}.sy-head-links .link>ul{margin:.5rem 0 .5rem 1rem}.sy-head-extra form.searchbox{position:absolute;top:1rem;left:1.8rem;right:1.8rem}.sy-head-extra{flex-direction:column;padding:2rem 0 1rem;width:100%}}@media (min-width:768px){.sy-head-inner{padding-right:max(env(safe-area-inset-right),1.5rem)}.sy-head-nav{display:flex;flex-grow:1;align-items:center;justify-content:space-between}.sy-head-links[data-align=right]{--head-links-justify-content:flex-end}.sy-head-links[data-align=center]{--head-links-justify-content:center}.sy-head-links{display:flex;flex-grow:1;white-space:nowrap;overflow:auto;padding:0 1rem;justify-content:var(--head-links-justify-content,flex-start)}.sy-head-links .link{display:inline-flex;align-items:center;height:var(--sy-s-navbar-height)}.sy-head-links a:hover{color:var(--sy-c-link-hover)}.sy-head-links .link:hover>a{background-color:var(--sy-c-surface);border-radius:6px}.sy-head-links .link i.chevron-down{color:var(--sy-c-light)}.sy-head-links .link>ul{position:absolute;height:0;visibility:hidden;background-color:var(--sy-c-background);top:var(--sy-s-navbar-height);margin-top:-10px;padding:15px;border-radius:6px;border:1px solid var(--sy-c-divider);box-shadow:var(--sy-dropdown-shadow);z-index:9;max-width:320px}.sy-head-links .link:hover>ul{height:auto;visibility:visible}.sy-head-links .link>ul>li{padding:.2rem 0}.sy-head-socials{margin-left:.5rem}}.sy-foot{border-top:1px solid var(--sy-c-foot-divider);padding-top:1.5rem;padding-bottom:1rem;color:var(--sy-c-foot-text);background-color:var(--sy-c-foot-background)}.sy-foot-inner{padding-left:max(env(safe-area-inset-right),1.5rem);padding-right:max(env(safe-area-inset-right),1.5rem)}.sy-foot-copyright{font-size:.84rem}.sy-foot-copyright a{font-weight:500}.sy-foot-copyright a:hover{text-decoration:underline}.sy-foot-socials a{font-size:1.4rem;color:var(--sy-c-foot-text)}.sy-foot-socials a+a{margin-left:.5rem}.sy-foot-socials a svg{display:inline-block;width:1.4rem;height:1.4rem}.sy-lside .sidebar-links{margin-bottom:2rem}@media (min-width:768px){.sy-lside .sy-lside-inner{top:var(--sy-s-offset-top)}.sy-lside .sy-scrollbar{height:calc(100vh - var(--sy-s-offset-top));overflow-x:hidden}}.yue *{scroll-margin-top:calc(var(--sy-s-offset-top) + 68px)}.sy-content{max-width:64rem;min-height:calc(100vh - var(--sy-s-offset-top) - 80px)}@media (max-width:767px){#lside{position:fixed;z-index:18;top:var(--sy-s-offset-top);left:0;bottom:0;width:300px;max-width:100%;height:calc(100vh - var(---sy-s-offset-top));overflow:auto;background:var(--sy-c-background);transform:translateX(-100%);transition:transform .2s ease}#lside._expanded{transform:translateX(0)}.lside-overlay{position:fixed;top:var(--sy-s-offset-top);left:0;width:0;height:0;background-color:var(--sy-c-overlay);opacity:0;transition:width 0 .25s,height 0 .25s,opacity .25s}#lside._expanded+.lside-overlay{width:100%;height:100%;opacity:1;z-index:16}}@media (max-width:1279px){.sy-rside{position:fixed;z-index:25;top:0;right:0;bottom:0;width:20rem;max-width:100%;padding-top:2rem;padding-bottom:1rem;overflow:auto;background:var(--sy-c-background);transform:translateX(110%);transition:transform .2s ease;box-shadow:0 0 var(--sy-c-background-contrast),-12px 0 16px var(--gray-a1)}#rside._expanded{transform:translateX(0)}.rside-close{position:absolute;top:16px;right:16px;width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;font-size:1.4rem}.rside-overlay{position:fixed;top:0;left:0;width:0;height:0;background-color:var(--sy-c-overlay);opacity:0;transition:width 0 .25s,height 0 .25s,opacity .25s}#rside._expanded+.rside-overlay{width:100%;height:100%;opacity:1;z-index:22}}@media (min-width:768px){.sy-main{width:calc(100% - 18rem);max-width:52rem}}@media (min-width:1280px){.sy-main{width:calc(100% - 34rem);max-width:none}.sy-rside .sy-scrollbar{max-height:calc(100vh - var(--sy-s-offset-top) - env(safe-area-inset-bottom))}.yue *{scroll-margin-top:calc(var(--sy-s-offset-top) + 24px)}}.nav-languages button,.nav-versions button{cursor:pointer;padding:0;margin:0;background:#0000;border:0;white-space:nowrap}.nav-versions .chevron-down{color:var(--sy-c-light)}@media (max-width:767px){.nav-languages,.nav-versions{width:100%;background-color:var(--sy-c-surface);border-radius:6px;padding-bottom:.6rem;margin-bottom:1rem}.nav-languages button,.nav-versions button{padding:.5rem 1rem;font-weight:500;font-size:.76rem;color:var(--sy-c-light)}.nav-languages button>i,.nav-versions button>i{display:none}.nav-versions ul{padding:0 .6rem}.nav-versions li{padding:.2rem .4rem;display:inline-block}.nav-languages li{font-size:.94rem;padding:.32rem 1rem}}@media (min-width:768px){.nav-languages,.nav-versions{display:flex;align-items:center;position:relative;width:auto;height:var(--sy-s-navbar-height);background:#0000;color:var(--sy-c-text)}.nav-languages button,.nav-versions button{padding:0 .5rem;border-right:1px solid var(--gray-3)}.nav-languages-choices,.nav-versions-choices{position:absolute;visibility:hidden;top:3rem;right:-.6rem;min-width:120px;max-height:60vh;box-sizing:border-box;background-color:var(--sy-c-background);border-radius:6px;overflow-x:hidden;overflow-y:auto;padding:.8rem 1rem;box-shadow:var(--sy-dropdown-shadow)}.nav-languages:hover .nav-languages-choices,.nav-versions:hover .nav-versions-choices{visibility:visible}.nav-languages li,.nav-versions li{padding:.1rem 0}.nav-languages a,.nav-versions a{display:block;padding:.2rem .6rem;color:var(--sy-c-text);white-space:nowrap}.nav-languages a:hover,.nav-versions a:hover{color:var(--sy-c-link-hover);background:var(--sy-c-surface);border-radius:6px}}.sy-breadcrumbs{position:sticky;top:var(--sy-s-offset-top);background-color:var(--sy-c-background);padding:0 1.5rem;z-index:5}.sy-breadcrumbs-inner{padding:.8rem 0;border-bottom:1px solid var(--sy-c-divider)}.sy-breadcrumbs ol{display:flex;font-size:.94rem;white-space:nowrap;overflow:auto}.sy-breadcrumbs button{display:flex;align-items:center}.sy-breadcrumbs ol a{color:var(--sy-c-light)}.sy-breadcrumbs ol a:hover{color:var(--sy-c-bold)}.sy-breadcrumbs ol a+span{padding:0 .4rem;font-weight:300;color:var(--sy-c-light)}@media (min-width:1280px){.sy-breadcrumbs{display:none}}@media (min-width:768px){.sy-breadcrumbs-inner{padding:1.5rem 0 1rem}}.globaltoc{padding-bottom:20px}.globaltoc .caption{font-size:.86rem;font-weight:500;font-family:var(--sy-f-heading);color:var(--sy-c-light);text-transform:uppercase;letter-spacing:.4px;padding:.8rem 0 .4rem;border-top:1px solid var(--sy-c-divider)}.globaltoc>p.caption:first-of-type{padding-top:0;border-top:none}.globaltoc .caption+ul{margin-bottom:1.5rem}.globaltoc ul+.caption{margin-top:2.5rem}.globaltoc li{margin:.6rem 0}.globaltoc li>ul{margin-left:.6rem;font-size:.96rem}.globaltoc li.toctree-l1>ul{margin-left:.2rem;border-left:1px solid var(--gray-3)}.globaltoc li.toctree-l2{padding-left:.9rem;margin-left:-1px;border-left:1px solid #0000}.globaltoc li.toctree-l2.current{border-color:var(--sy-c-link)}.globaltoc>ul a.current{font-weight:500;color:var(--sy-c-link)}.globaltoc>ul a:hover{color:var(--sy-c-link-hover)}.globaltoc a.external:after{content:"";-webkit-mask:var(--lucide-external-link-url) no-repeat;mask:var(--lucide-external-link-url) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;width:.825rem;height:.825rem;margin-left:.2rem;display:inline-block;vertical-align:middle;font-style:normal;background-color:var(--sy-c-light)}.globaltoc li{position:relative}.globaltoc li>button{position:absolute;top:.2rem;right:0;display:flex;justify-content:center;align-items:center;width:1.2rem;height:1.2rem;border-radius:3px}.globaltoc li>button:hover{background-color:var(--sy-c-surface)}.globaltoc li._expand>ul,.globaltoc li.current>ul{display:block}.globaltoc li._collapse>ul,.globaltoc li>ul{display:none}.globaltoc li>button>i{transform:rotate(0deg);transition:transform .2s ease}.globaltoc li._expand>button>i,.globaltoc li.current>button>i{transform:rotate(90deg)}.globaltoc li._collapse>button>i{transform:rotate(0deg)}.sy-deprecated{padding:.8rem;font-size:.85rem;background-color:#ffdd001a;border-radius:6px}.sy-deprecated a{color:var(--sy-c-link);text-decoration:underline}.sy-deprecated a:hover{color:var(--sy-c-link-hover)}.sy-rside-inner>div{margin-bottom:1rem}.sy-rside-inner>div>h3{font-size:.8rem;font-weight:500;letter-spacing:.4px;text-transform:uppercase;margin-bottom:1rem}html[lang=ja] .sy-rside-inner>div>h3,html[lang=ko] .sy-rside-inner>div>h3,html[lang=zh-TW] .sy-rside-inner>div>h3,html[lang=zh] .sy-rside-inner>div>h3{letter-spacing:0;font-size:.86rem;font-weight:600}.localtoc>ul li{margin-top:.36rem;margin-bottom:.36rem}.localtoc>ul li>a:hover{color:var(--sy-c-link-hover)}.localtoc>ul li.active>a{font-weight:500;color:var(--sy-c-link)}.localtoc>ul>li ul{padding-left:.8rem}.sy-rside ul.this-page-menu{margin-top:-.6rem}.sy-rside ul.this-page-menu a{font-size:.96rem}.sy-rside ul.this-page-menu a:hover{color:var(--sy-c-link-hover)}.navigation{gap:2rem;margin-top:2rem;padding-top:1rem;border-top:1px solid var(--sy-c-divider)}.navigation>div{width:100%}.navigation a{display:inline-flex;align-items:center}.navigation a:hover{color:var(--sy-c-link-hover)}.navigation-next{text-align:right}.navigation-next a{justify-content:end}.navigation .page-info{padding:0 8px}.navigation .page-info>span{font-size:.8rem;color:var(--sy-c-light)}:root{--yue-c-text:var(--sy-c-text);--yue-c-heading:var(--sy-c-heading);--yue-c-bold:var(--sy-c-bold);--yue-c-link-1:var(--sy-c-text);--yue-c-link-2:var(--sy-c-bold);--yue-c-link-border:var(--sy-c-link);--yue-c-ol-marker:var(--gray-9);--yue-c-ul-marker:var(--sage-a5);--yue-c-hr:var(--sy-c-border);--yue-c-quote:var(--sy-c-text);--yue-c-quote-border:var(--accent-a3);--yue-c-quote-symbol:var(--accent-9);--yue-c-caption:var(--sy-c-light);--yue-c-code-text:var(--accent-a11);--yue-c-code-background:var(--accent-a3);--yue-c-table-border:var(--gray-a5);--yue-c-th-background:var(--color-surface-accent);--yue-c-th-border:var(--gray-a5);--yue-c-td-border:var(--gray-a4);--yue-c-row-background:var(--sy-c-surface)}.yue{font-size:1rem;line-height:1.75;color:var(--yue-c-text)}.yue p{margin-top:1rem;margin-bottom:1.25rem}.yue a{color:var(--yue-c-link-1);font-weight:500;text-decoration:none;border-bottom:1px solid var(--yue-c-link-border)}.yue a:hover{color:var(--yue-c-link-2);border-bottom-width:2px}.yue pre a,.yue pre a:hover{border-bottom:none}.yue strong{color:var(--yue-c-bold);font-weight:600}.yue a strong,.yue blockquote strong,.yue thead th strong{color:inherit}.yue ol{margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.yue ol,.yue ol[type="1"]{list-style-type:decimal}.yue ol.upperalpha,.yue ol[type=A]{list-style-type:upper-alpha}.yue ol.loweralpha,.yue ol[type=a]{list-style-type:lower-alpha}.yue ol.upperroman,.yue ol[type=I]{list-style-type:upper-roman}.yue ol.lowerroman,.yue ol[type=i]{list-style-type:lower-roman}.yue ul{list-style-type:disc;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.yue ol>li::marker{font-weight:400;color:var(--yue-c-ol-marker)}.yue ul>li::marker{color:var(--yue-c-ul-marker)}.yue dl{margin-top:1.5rem;margin-bottom:1.5rem}.yue dt{color:var(--yue-c-bold);font-weight:600}.yue dd{margin-left:1.5rem}.yue hr{border-color:var(--yue-c-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.yue blockquote{color:var(--yue-c-quote);border-left-width:.25rem;border-left-color:var(--yue-c-quote-border);margin-top:1.2rem;margin-bottom:1.2rem;padding-left:1rem}.yue blockquote .attribution{font-size:.85em;font-style:italic}[lang=ja] .yue blockquote .attribution,[lang=ko] .yue blockquote .attribution,[lang^=zh] .yue blockquote .attribution{font-style:normal}.yue h1{color:var(--yue-c-heading);font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.yue h1 strong{font-weight:900;color:inherit}.yue h2{color:var(--yue-c-heading);font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.yue h2 strong{font-weight:800;color:inherit}.yue h3{color:var(--yue-c-heading);font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.yue h3 strong{font-weight:700;color:inherit}.yue h4{color:var(--yue-c-heading);font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.yue h4 strong{font-weight:700;color:inherit}.yue h5,.yue h6{color:var(--yue-c-heading);font-weight:600}.yue img{display:inline;margin-top:2em;margin-bottom:2em}.yue img.rounded{border-radius:.5rem}.yue a>img,.yue figure img,.yue figure>*{margin-top:0;margin-bottom:0}.yue figcaption{color:var(--yue-c-caption);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.yue figcaption>p{margin-top:0}.yue code{color:var(--yue-c-code-text);font-weight:600;font-size:.875em}.yue a code,.yue blockquote code,.yue h1 code,.yue h2 code,.yue h3 code,.yue h4 code,.yue th code{color:inherit}.yue h2 code{font-size:.875em}.yue li>code,.yue p>code{padding:2px 4px;border-radius:3px;font-weight:500;background-color:var(--yue-c-code-background)}.yue h3 code{font-size:.9em}.yue kbd{font-family:var(--sy-f-mono)}.yue figure,.yue video{margin-top:2em;margin-bottom:2em}.yue li{margin-top:.5em;margin-bottom:.5em}.yue ol>li,.yue ul>li{padding-left:.375em}.yue ol ol,.yue ol ul,.yue ul ol,.yue ul ul{margin-top:.75em;margin-bottom:.75em}.yue h2+*,.yue h3+*,.yue h4+*,.yue hr+*{margin-top:0}.yue table{width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.86em;line-height:1.7}.yue table>caption{margin-bottom:.4rem;color:var(--yue-c-caption)}.yue thead tr{border-bottom-width:1px;border-bottom-color:var(--yue-c-th-border)}.yue thead th{color:var(--yue-c-heading);font-weight:600;vertical-align:middle}.yue tbody tr{border-bottom-width:1px;border-bottom-color:var(--yue-c-td-border)}.yue tbody tr:last-child{border-bottom-width:0}.yue tbody td{vertical-align:middle}.yue tfoot{border-top-width:1px;border-top-color:var(--yue-c-th-border)}.yue tfoot td{vertical-align:top}.yue td>p{margin:.25rem 0}.yue thead th>p{margin:0}.yue tbody td,.yue tfoot td,.yue thead th{padding:.5rem}.yue section{clear:both}.yue section>div{margin-bottom:2rem}.yue dd>p:first-child{margin-top:0}.yue p.lead{font-size:1.2rem;color:var(--sy-c-light);margin-bottom:0}.yue p.lead+hr{margin-top:1rem}.yue p.rubric{color:var(--yue-c-heading);font-weight:600;margin-top:2rem}.yue .sidebar{background-color:var(--sy-c-surface);border:1px solid var(--sy-c-border);border-radius:6px;clear:right;float:right;margin-left:1rem;margin-bottom:1rem;margin-right:0;width:30%}@media (max-width:767px){.yue .sidebar{float:none;width:100%;margin-left:0}}.yue .sidebar>*{padding-left:1rem;padding-right:1rem}.yue .sidebar img{margin-top:1rem;margin-bottom:1rem}.yue .sidebar-title{font-weight:500;border-bottom:1px solid var(--sy-c-border);margin:0;padding-top:.5rem;padding-bottom:.5rem}.yue dl.simple>dd>p,.yue ol.simple>li>p,.yue ul.simple>li>p{margin:0}.yue a.headerlink{visibility:hidden;margin-left:6px;color:var(--sy-c-light);font-weight:300;font-size:58%;font-family:var(--sy-f-mono);--icon-url:var(--lucide-link-url);-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;width:1em;height:1em;display:inline-block;vertical-align:middle;font-style:normal;background-color:currentColor}.yue .math a.headerlink,h1:hover a.headerlink,h2:hover a.headerlink,h3:hover a.headerlink,h4:hover a.headerlink,h5:hover a.headerlink,h6:hover a.headerlink{visibility:visible}.yue .toctree-wrapper a,.yue a.image-reference{border-bottom:none}.yue .toctree-wrapper p.caption{font-size:.86rem;font-weight:500;font-family:var(--sy-f-heading);color:var(--sy-c-light);text-transform:uppercase;letter-spacing:.4px;padding:.8rem 0 .4rem;border-bottom:1px solid var(--sy-c-divider)}.yue .align-left{clear:left;float:left;margin:0 1rem 1rem}.yue .align-right{clear:right;float:right;margin:0 1rem 1rem}.yue .align-center{display:block;text-align:center}.yue .align-center,.yue figure.align-center img{margin-left:auto;margin-right:auto}a.footnote-reference{font-size:.65rem;vertical-align:top}aside.footnote>span,div.citation>span{float:left;font-weight:500;padding-right:.25rem}aside.footnote>p,div.citation>p{margin-bottom:.5rem;margin-top:.5rem;margin-left:2rem}.yue kbd.kbd:not(.compound){font-size:.86rem;padding:2px 5px;border-radius:3px;margin-right:.25rem}.yue kbd.compound>kbd{margin-left:.25rem}.yue .menuselection{font-weight:500;font-size:.86rem}.light .searchbox kbd,.light .yue kbd.kbd:not(.compound){border:0;background:linear-gradient(-225deg,#e6e6e6,#f8f8f8);box-shadow:inset 0 -2px #dbdbdb,inset 0 0 1px 1px #fff,0 1px 2px 1px #50505066}.dark .searchbox kbd,.dark .yue kbd.kbd:not(.compound){border:0;background:linear-gradient(-225deg,#353434,#141414);box-shadow:inset 0 -2px #373737,inset 0 0 1px 1px #222,0 1px 2px 1px #000}.yue p.centered{text-align:center}.hlist td{vertical-align:top}.dark .dark-hidden,.dark .light-only,.light .dark-only,.light .light-hidden{display:none}.yue .genindex-jumpbox,.yue .modindex-jumpbox{border-top:1px solid var(--sy-c-border);border-bottom:1px solid var(--sy-c-border);padding:2px .4rem}.yue table.modindextable td:first-of-type{width:28px}.yue table.modindextable img.toggler{margin:0}.yue table.modindextable tr.cap{font-size:1.12rem;background:var(--sy-c-surface);font-family:var(--sy-f-mono)}.yue h2+table.indextable,.yue table.indextable ul{margin-top:0}:root{--attention-icon:var(--lucide-alert-url);--attention-1:var(--crimson-surface);--attention-2:var(--crimson-a3);--attention-3:var(--crimson-9);--attention-4:var(--crimson-a11);--caution-icon:var(--lucide-zap-url);--caution-1:var(--amber-surface);--caution-2:var(--amber-a3);--caution-3:var(--amber-9);--caution-4:var(--amber-11);--danger-icon:var(--lucide-skull-url);--danger-1:var(--ruby-surface);--danger-2:var(--ruby-a3);--danger-3:var(--ruby-9);--danger-4:var(--ruby-a11);--error-icon:var(--lucide-close-url);--error-1:var(--red-surface);--error-2:var(--red-a3);--error-3:var(--red-9);--error-4:var(--red-a11);--hint-icon:var(--lucide-bell-url);--hint-1:var(--cyan-surface);--hint-2:var(--cyan-a3);--hint-3:var(--cyan-9);--hint-4:var(--cyan-a11);--important-icon:var(--lucide-flame-url);--important-1:var(--violet-surface);--important-2:var(--violet-a3);--important-3:var(--violet-9);--important-4:var(--violet-a11);--note-icon:var(--lucide-calendar-url);--note-1:var(--blue-surface);--note-2:var(--blue-a3);--note-3:var(--blue-9);--note-4:var(--blue-a11);--tip-icon:var(--lucide-rocket-url);--tip-1:var(--green-surface);--tip-2:var(--green-a3);--tip-3:var(--green-9);--tip-4:var(--green-a11);--warning-icon:var(--lucide-zap-url);--warning-1:var(--orange-surface);--warning-2:var(--orange-a3);--warning-3:var(--orange-9);--warning-4:var(--orange-a11);--seealso-icon:var(--lucide-link-url);--seealso-1:var(--gold-surface);--seealso-2:var(--gold-a3);--seealso-3:var(--gold-9);--seealso-4:var(--gold-a11);--todo-icon:var(--lucide-bookmark-url);--todo-1:var(--bronze-surface);--todo-2:var(--bronze-a3);--todo-3:var(--bronze-9);--todo-4:var(--bronze-a11);--versionadded-1:var(--green-surface);--versionadded-2:var(--green-9);--versionchanged-1:var(--amber-surface);--versionchanged-2:var(--amber-9);--deprecated-1:var(--red-surface);--deprecated-2:var(--red-9)}.admonition{--icon-url:var(--lucide-bell-url);--color-1:var(--color-surface-accent);--color-2:var(--accent-a3);--color-3:var(--accent-9);--color-4:var(--accent-a11);display:flex;flex-direction:column;position:relative;padding:.825rem 1rem;margin-top:1rem;margin-bottom:1rem;border-left:4px solid var(--color-3);background-color:var(--color-1)}.admonition:before{position:absolute;content:"";top:6px;left:-12px;width:20px;height:20px;border-radius:100%;background-color:var(--color-3)}.admonition:after{position:absolute;content:"";top:10px;left:-8px;-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;font-style:normal;width:12px;height:12px;background-color:#fff}.admonition p.admonition-title{position:relative;margin:-.825rem -1rem .825rem -19px;padding:4px 18px;font-size:.85rem;font-weight:600;line-height:1.72;color:var(--color-4);background-color:var(--color-2);--yue-c-code:var(--color-4);--yue-c-bold:var(--color-4)}.admonition p.admonition-title svg{display:inline-block}.admonition.attention{--icon-url:var(--attention-icon);--color-1:var(--attention-1);--color-2:var(--attention-2);--color-3:var(--attention-3);--color-4:var(--attention-4)}.admonition.caution{--icon-url:var(--caution-icon);--color-1:var(--caution-1);--color-2:var(--caution-2);--color-3:var(--caution-3);--color-4:var(--caution-4)}.admonition.danger{--icon-url:var(--danger-icon);--color-1:var(--danger-1);--color-2:var(--danger-2);--color-3:var(--danger-3);--color-4:var(--danger-4)}.admonition.error{--icon-url:var(--error-icon);--color-1:var(--error-1);--color-2:var(--error-2);--color-3:var(--error-3);--color-4:var(--error-4)}.admonition.hint{--icon-url:var(--hint-icon);--color-1:var(--hint-1);--color-2:var(--hint-2);--color-3:var(--hint-3);--color-4:var(--hint-4)}.admonition.important{--icon-url:var(--important-icon);--color-1:var(--important-1);--color-2:var(--important-2);--color-3:var(--important-3);--color-4:var(--important-4)}.admonition.note{--icon-url:var(--note-icon);--color-1:var(--note-1);--color-2:var(--note-2);--color-3:var(--note-3);--color-4:var(--note-4)}.admonition.tip{--icon-url:var(--tip-icon);--color-1:var(--tip-1);--color-2:var(--tip-2);--color-3:var(--tip-3);--color-4:var(--tip-4)}.admonition.warning{--icon-url:var(--warning-icon);--color-1:var(--warning-1);--color-2:var(--warning-2);--color-3:var(--warning-3);--color-4:var(--warning-4)}.admonition.seealso{--icon-url:var(--seealso-icon);--color-1:var(--seealso-1);--color-2:var(--seealso-2);--color-3:var(--seealso-3);--color-4:var(--seealso-4)}.admonition.admonition-todo{--icon-url:var(--todo-icon);--color-1:var(--todo-1);--color-2:var(--todo-2);--color-3:var(--todo-3);--color-4:var(--todo-4)}.admonition p.admonition-title+p{margin-top:0}.admonition>:last-child{margin-bottom:0}span.versionmodified{color:var(--sy-c-bold);font-weight:600}div.deprecated,div.versionadded,div.versionchanged{position:relative;padding:6px 1rem;margin:1rem 0;border-left:4px solid var(--color-2);background-color:var(--color-1);line-height:1.72}div.deprecated:before,div.versionadded:before,div.versionchanged:before{position:absolute;content:var(--version-icon);top:10px;left:-12px;color:#fff;width:20px;height:20px;border-radius:100%;background-color:var(--color-2);text-align:center;font:normal 700 14px/20px var(--sy-f-mono)}div.versionadded{--color-1:var(--versionadded-1);--color-2:var(--versionadded-2);--version-icon:"#"}div.versionchanged{--color-1:var(--versionchanged-1);--color-2:var(--versionchanged-2);--version-icon:"%"}div.deprecated{--color-1:var(--deprecated-1);--color-2:var(--deprecated-2);--version-icon:"!"}div.deprecated>p,div.versionadded>p,div.versionchanged>p{margin:0}.yue blockquote.epigraph{padding:1rem 2.4rem;border-left:0;text-align:center}.yue blockquote.highlights{border-left-width:4px;padding-top:.2rem;padding-bottom:.2rem;background-color:var(--sy-c-surface)}.yue blockquote.pull-quote{position:relative;font-size:1.24rem;padding:2.4rem 3.6rem 1.2rem;border-left:0}.yue blockquote.pull-quote:before{content:"\201c";position:absolute;top:0;left:.5rem;color:var(--yue-c-quote-symbol);font:700 4rem/1 Times New Roman,Georgia,Palatino,Times,serif}.yue blockquote.pull-quote .attribution{text-align:right}pre.literal-block{line-height:1.48;padding:1rem;font-size:.96rem;background-color:var(--syntax-pre-bg);border-radius:6px;overflow:auto}.highlight,.literal-block-wrapper{--margin:1rem;--radius:6px}.literal-block-wrapper div[class^=highlight-]{display:flex}.literal-block-wrapper .highlight{width:100%}.highlight>pre{line-height:1.48;padding:var(--margin);font-size:.96rem;font-family:var(--sy-f-mono);background-color:var(--syntax-pre-bg);border-radius:var(--radius);overflow:auto}.win .highlight>pre{font-family:"Twemoji Country Flags",var(--sy-f-mono)}.highlight .linenos{display:inline-block;box-shadow:-.05rem 0 var(--syntax-linenos-divider) inset;-webkit-user-select:none;-moz-user-select:none;user-select:none;margin-right:.8rem;padding-right:.8rem;opacity:.6}.highlight .hll{margin-left:calc(0rem - var(--margin));margin-right:calc(0rem - var(--margin));padding:0 var(--margin)}.code-block-caption{display:flex;font-size:.84rem;font-weight:600;color:var(--syntax-text);background-color:var(--syntax-cap-bg);padding:.4rem var(--margin);border-radius:var(--radius) var(--radius) 0 0}.code-block-caption+div>.highlight>pre{border-top-left-radius:0;border-top-right-radius:0}div[class^=highlight]>.highlight>pre{display:grid}.yue .table-wrapper{width:100%;overflow-x:auto;margin-top:2rem;margin-bottom:2rem;border:1px solid var(--yue-c-table-border);border-radius:6px}.yue .table-wrapper table{margin:0}.yue .table-wrapper thead tr{border-top:1px solid var(--yue-c-td-border)}.yue .table-wrapper thead tr:first-child{border-top:0}.yue .table-wrapper th{background-color:var(--yue-c-th-background);border-left:1px solid var(--yue-c-td-border);padding:.725rem 1rem}.yue .table-wrapper td{border-left:1px solid var(--yue-c-td-border);padding:.5rem 1rem}.yue .table-wrapper tr>td:first-child,.yue .table-wrapper tr>th:first-child{border-left:0}.yue .table-wrapper caption{padding:.5rem;margin:0;border-bottom:1px solid var(--yue-c-th-border)}.yue .table-wrapper tbody tr.row-odd{background-color:var(--yue-c-row-background)}.yue table.hlist td{vertical-align:top}.table-wrapper{overflow-x:auto;scrollbar-gutter:auto}.table-wrapper::-webkit-scrollbar{height:.75rem;width:.75rem}.table-wrapper::-webkit-scrollbar-thumb{border-radius:10px}.table-wrapper::-webkit-scrollbar-track{background-color:initial}.table-wrapper:hover::-webkit-scrollbar-thumb{background-color:#9b9b9b33;background-clip:content-box;border:3px solid #0000}.yue table.ghost td,.yue table.ghost th{border-left:0;border-right:0;background-color:initial}.yue table.ghost caption{margin-bottom:0;padding-bottom:.5rem;border-bottom:3px solid var(--yue-c-td-border)}.yue table.ghost thead tr:first-child{border-top:0;border-bottom-width:3px}.yue .table-wrapper.ghost{border:0}:root{--sig-property:var(--syntax-keyword);--sig-name:var(--syntax-property);--sig-typehint:var(--syntax-constant);--sig-param:var(--syntax-meta)}dt.sig{position:relative;font-size:.92rem;padding:.25rem .5rem .25rem 3rem;text-indent:-2.4rem;border-radius:6px}dt.sig:after{content:"";display:table;clear:both}dt.sig:hover{background:var(--sy-c-surface)}dt.sig+dd{font-size:.92rem;margin-left:2rem}dt.sig>em.property:first-child{color:var(--sig-property)}dl.field-list a{font-weight:400}dt.sig+dd>div{margin-bottom:1rem}dt.sig+dd>dl.field-list>dt{text-transform:uppercase;font-size:.76rem}em.property,em.sig-param{font-style:normal}em.sig-param{color:var(--sy-c-light)}span.sig-name,span.sig-prename{color:var(--sig-name)}span.sig-name{font-weight:600}span.sig-return-icon{color:var(--sy-c-light)}span.sig-return-typehint,span.sig-return-typehint>a{color:var(--sig-typehint)}span.pre,span.sig-paren{font-family:var(--sy-f-mono)}dt.sig>a.internal{font-size:.82rem;border:0;color:var(--sy-c-light)}dt.sig>a.internal:before{content:"\a";white-space:pre}.viewcode-block{position:relative}.viewcode-back{position:absolute;top:-1.5rem;font-size:.8rem}.classifier{font-style:oblique;font-weight:400}.classifier:before{font-style:normal;margin-left:.1rem;margin-right:.5rem;content:":";display:inline-block}.yue .table-wrapper.autosummary{border-left:0;border-right:0;border-radius:0}.yue .table-wrapper table.autosummary td{border:none;padding-top:.25rem;padding-bottom:.25rem}.yue p.rubric+div.autosummary{margin-top:0}.sy-lside{--height:42px}.sy-lside-bottom{position:sticky;bottom:0;padding:0;border-top:1px solid var(--sy-c-divider);background-color:var(--sy-c-background);--tw-shadow:0 -12px 16px var(--sy-c-background);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.sy-lside .rst-versions{position:static;width:100%;background-color:var(--sy-c-surface);font-family:var(--sy-f-text)}.sy-lside .rst-versions a{color:var(--sy-c-link)}.sy-lside .rst-versions a:hover{color:var(--sy-c-link-hover)}.sy-lside .rst-versions .rst-current-version{background-color:var(--sy-c-background);color:var(--sy-c-text);padding:0 1rem;height:var(--height);line-height:var(--height)}.sy-lside .rst-versions.rst-badge .rst-current-version{text-align:left;font-size:.94rem;padding:0 1rem;height:var(--height);line-height:var(--height)}.sy-lside .rst-versions .rst-current-version .fa{color:var(--sy-c-text)}.sy-lside .rst-versions.rst-badge.shift-up .rst-current-version{text-align:left}.sy-lside .rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:none}.sy-lside .rst-other-versions{font-size:.86rem;border-top:1px solid var(--sy-c-divider)}.sy-lside .rst-other-versions dt{font-size:.68rem;font-weight:500;padding:4px 6px;color:var(--sy-c-light)}.sy-lside .rst-versions .rst-other-versions dd a{color:var(--sy-c-text)}.sy-lside .rst-versions .rst-other-versions dd a:hover{text-decoration:underline;color:var(--sy-c-link-hover)}.sy-lside .rst-versions input{width:100%;padding:6px 12px;font-size:.92rem;font-family:var(--sy-f-text);border-radius:6px;outline:0;background:var(--sy-c-background);border:1px solid var(--sy-c-border)}.sy-lside .rst-versions .rst-other-versions hr{border-color:var(--sy-c-divider)}@media (min-width:90rem){.sy-lside .rst-versions{background:var(--sy-c-background)}}.yue button.copybtn{align-items:center;justify-content:center;background-color:initial;border:none;color:var(--syntax-text)}.yue button.copybtn>svg{width:1.4rem;height:1.4rem}.yue button.copybtn:hover{color:var(--syntax-meta)}.yue .highlight button.copybtn:hover{background-color:initial}.yue button.copybtn:after{background-color:initial;color:var(--syntax-text)}.yue button.copybtn.success{border-color:var(--green-a10);color:var(--green-a10)}.yue button.copybtn.success:after{color:var(--green-a10)}.yue{--sd-color-primary:var(--accent-a11);--sd-color-secondary:var(--gold-a11);--sd-color-success:var(--green-a11);--sd-color-info:var(--blue-a11);--sd-color-warning:var(--orange-a11);--sd-color-danger:var(--red-a11);--sd-color-light:var(--sand-a2);--sd-color-muted:var(--gray-8);--sd-color-dark:#212122;--sd-color-black:#000;--sd-color-white:#fff;--sd-color-primary-highlight:var(--accent-a8);--sd-color-secondary-highlight:var(--gold-a8);--sd-color-success-highlight:var(--green-a8);--sd-color-info-highlight:var(--blue-a8);--sd-color-warning-highlight:var(--orange-a8);--sd-color-danger-highlight:var(--red-a8);--sd-color-light-highlight:var(--gray-4);--sd-color-muted-highlight:var(--gray-11);--sd-color-dark-highlight:#121211;--sd-color-black-highlight:#000;--sd-color-white-highlight:#d9d9d9;--sd-color-primary-text:var(--accent-9-contrast);--sd-color-secondary-text:var(--gold-9-contrast);--sd-color-success-text:var(--green-9-contrast);--sd-color-info-text:var(--blue-9-contrast);--sd-color-warning-text:var(--orange-9-contrast);--sd-color-danger-text:var(--red-9-contrast);--sd-color-light-text:var(--sy-c-text);--sd-color-muted-text:#fff;--sd-color-dark-text:#fff;--sd-color-black-text:#fff;--sd-color-white-text:#212529;--sd-color-shadow:var(--gray-1);--sd-color-card-border:var(--sy-c-border);--sd-color-card-border-hover:var(--accent-a9);--sd-color-tabs-label-inactive:var(--sy-c-bold);--sd-color-tabs-label-active:var(--sd-color-primary);--sd-color-tabs-underline-active:var(--sd-color-primary);--sd-color-tabs-label-hover:var(--accent-9);--sd-color-tabs-underline-hover:var(--accent-9)}.yue .surface{--sd-color-card-text:var(--sy-c-light);--sd-color-card-border:#0000;--sd-color-card-background:var(--sy-c-surface)}.yue a.sd-badge,.yue a.sd-badge:hover{border-bottom:0}.yue .sd-badge{font-weight:600;border-radius:3px}.yue .sd-btn{border-color:var(--sy-c-border)}.yue .sd-tab-set>label{padding:1rem .25rem .5rem;font-size:.84rem;font-weight:500}.yue .sd-tab-set>label~label{margin-left:1rem}.yue .sd-tab-content{padding:0;box-shadow:0 -.0625rem var(--sy-c-divider)}.yue .sd-tab-content .code-block-caption,.yue .sd-tab-content .highlight pre{border-radius:0}.yue .sd-card-title{color:var(--sy-c-text)}.yue .sd-card-title>svg{position:relative;top:-1px;margin-right:.25rem}.yue .sd-card-hover:hover{transform:scale(1)}.yue .sd-card-hover:hover .sd-card-title{color:var(--sy-c-link-hover)}.yue .sd-card a,.yue .sd-card a:hover{border-bottom:0}.yue .surface .sd-card-body,.yue .surface .sd-card-footer,.yue .surface .sd-card-header{padding-left:1.5rem;padding-right:1.5rem}.yue .surface .sd-card-footer,.yue .surface .sd-card-header{border-color:var(--sy-c-border)}@media (print){.yue .sd-card{page-break-inside:avoid}}.yue a.sd-text-wrap:hover{border-bottom-width:1px}.sphinx-tabs [role=tablist]{border-color:var(--sy-c-divider)}.yue .sphinx-tabs-tab{color:var(--sy-c-text);line-height:inherit;padding:1rem .25rem .5rem;font-size:.84rem;font-weight:500;border:none;border-bottom:.125rem solid #0000}.yue .sphinx-tabs-tab:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.yue .sphinx-tabs-tab[aria-selected=true]{border:none;border-bottom:.125rem solid var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active);background-color:initial}.yue .sphinx-tabs-tab+.sphinx-tabs-tab{margin-left:1rem}.yue .sphinx-tabs-panel{border:none;padding:0;margin:0;border-radius:0;background-color:initial}.yue .sphinx-tabs-panel.code-tab{padding:0}.yue .sphinx-tabs-panel.code-tab .code-block-caption,.yue .sphinx-tabs-panel.code-tab .highlight pre{border-radius:0}.yue{--jp-widgets-input-border-color:var(--gray-5);--jp-widgets-input-focus-border-color:var(--gray-8);--jp-widgets-slider-active-handle-color:var(--gray-4);--jp-widgets-slider-handle-border-color:var(--sy-c-border)}.yue .jupyter_container{background-color:var(--sy-c-background);border:3px solid var(--sy-c-border);border-radius:6px;overflow:hidden;box-shadow:none}.sy-main .yue .jupyter_container div[class^=highlight]{padding:0}.yue .jupyter_container div.cell_input{background-color:var(--syntax-pre-bg);border:0;border-radius:0}.yue .jupyter_container div.code_cell pre{padding:0}.jupyter_container div.cell_output .output,.jupyter_container div.cell_output .stderr,.jupyter_container div.cell_output .widget-subarea{padding:.5rem}.jupyter_container div.cell_output .stderr .stderr{padding:0}.jupyter-widget-hslider .slider-container,.widget-hslider .slider-container{display:flex;align-items:center}.jupyter-widget-slider .noUi-target,.widget-slider .noUi-target{width:100%}.jupyter_container div.code_cell .highlight>pre{padding:1rem}.jupyter_container div.code_cell .highlight .hll{margin-left:-1rem;margin-right:-1rem;padding:0 1rem}.jupyter_container div.code_cell .highlight .linenos{margin-right:.8rem}.yue .jupyter_container .stderr{color:var(--red-a11);background-color:var(--red-a3)}.yue .jupyter_container .stderr .stderr{background-color:initial}.nbinput .highlight{--radius:1px}.yue div.nblast.container{padding-top:5px}.yue div.nbinput.container div.input_area{border-color:var(--sy-c-border)}.yue div.nboutput.container div.output_area.stderr{color:var(--red-a11);background-color:var(--red-a3)}.yue div.nboutput.container div.output_area>.math-wrapper>div.math{padding-top:0}.yue .jp-RenderedHTMLCommon thead,.yue div.rendered_html thead{border-color:var(--sy-c-border)}.yue .jp-RenderedHTMLCommon tbody tr,.yue div.rendered_html tbody tr{color:var(--sy-c-text)}.yue .jp-RenderedHTMLCommon tbody tr:nth-child(odd),.yue div.rendered_html tbody tr:nth-child(odd){background-color:var(--sy-c-surface)}.yue .jp-RenderedHTMLCommon tbody tr:hover,.yue div.rendered_html tbody tr:hover{background-color:var(--color-surface-accent)}.yue{--sg-text-color:var(--sy-c-text);--sg-background-color:var(--sy-c-background);--sg-code-background-color:var(--syntax-pre-bg);--sg-tr-hover-color:var(--accent-a3);--sg-tr-odd-color:var(--sy-c-surface);--sg-tooltip-foreground:var(--sy-c-background-contrast);--sg-tooltip-background:var(--sy-c-background);--sg-tooltip-border:var(--gray-7) #0000;--sg-thumb-box-shadow-color:var(--gray-a4);--sg-thumb-hover-border:var(--accent-a9);--sg-script-out:var(--sy-c-light);--sg-script-pre:var(--syntax-pre-bg);--sg-pytb-foreground:var(--syntax-text);--sg-pytb-background:var(--red-a2);--sg-pytb-border-color:var(--red-a8);--sg-download-a-background-color:var(--accent-a3);--sg-download-a-background-image:none;--sg-download-a-border-color:1px solid var(--accent-a3);--sg-download-a-color:var(--accent-a11);--sg-download-a-hover-background-color:var(--accent-a4);--sg-download-a-hover-box-shadow-1:#0000;--sg-download-a-hover-box-shadow-2:#0000}.yue .sphx-glr-download a,.yue .sphx-glr-download a:hover,.yue .sphx-glr-thumbnails a{border-bottom:0}.yue p.sphx-glr-signature a{border-radius:0;border-bottom:0;text-decoration:underline}.yue p.sphx-glr-signature a:hover{color:var(--sy-c-link-hover)}.yue .sphx-glr-footer img{display:inline;margin:0}html.dark,html.light{--docsearch-primary-color:var(--accent-9);--docsearch-text-color:var(--sy-c-text);--docsearch-modal-background:var(--sy-c-background);--docsearch-footer-background:var(--sy-c-surface);--docsearch-searchbox-background:var(--sy-c-surface);--docsearch-searchbox-focus-background:var(--sy-c-background);--docsearch-muted-color:var(--sy-c-light);--docsearch-hit-color:var(--sy-c-text);--docsearch-hit-background:var(--sy-c-surface);--docsearch-hit-active-color:var(--accent-9-contrast);--docsearch-hit-shadow:inset 0 0 1px 0 var(--gray-a11);--docsearch-container-background:var(--sy-c-overlay)}html.light{--docsearch-key-gradient:linear-gradient(-225deg,#e6e6e6,#f8f8f8);--docsearch-key-shadow:inset 0 -2px #dbdbdb,inset 0 0 1px 1px #fff,0 1px 2px 1px #50505066}html.dark{--docsearch-key-gradient:linear-gradient(-225deg,#353434,#141414);--docsearch-key-shadow:inset 0 -2px #373737,inset 0 0 1px 1px #222,0 1px 2px 1px #000;--docsearch-footer-shadow:0 -1px 0 0 #373737,0 -3px 6px 0 #141414;--docsearch-modal-shadow:inset 1px 1px 0 0 #373737,0 3px 8px 0 #141414}#docsearch .DocSearch-Button{border-radius:6px}#docsearch .DocSearch-Button-Key,#docsearch .DocSearch-Button-Placeholder{font-size:.825rem}#docsearch .DocSearch-Button-Keys,#docsearch .DocSearch-Button-Placeholder{display:flex!important}#docsearch .DocSearch-Search-Icon{width:.875rem!important;height:.875rem!important}@media (max-width:767px){#docsearch{position:absolute;top:1rem;left:1.8rem;right:1.8rem}#docsearch .DocSearch-Button{margin-left:0;width:100%}}dl.sqla dt{color:var(--sig-name);margin-bottom:.5rem}dl.sqla dt>em{font-weight:400;font-style:normal;color:var(--sig-param)}dl.sqla dd>p.rubric{margin-top:1.5rem;text-transform:uppercase;font-size:.76rem}dl.sqla dd>p.rubric+.table-wrapper{margin-top:.75rem;border-left:0;border-right:0;border-radius:0}dl.sqla p.rubric+.table-wrapper td,dl.sqla p.rubric+.table-wrapper th{border-left:0;border-right:0;background-color:initial}dl.sqla p.rubric+.table-wrapper td>p{margin:0}dl.sqla p.rubric+.table-wrapper tr.row-odd{background-color:initial}dl.sqla p.rubric+.table-wrapper tr.row-even{background-color:var(--yue-c-row-background)}.yue details.toggle-details{background-color:var(--slate-a2);padding:0 1rem;border-radius:.2em}.yue details.toggle-details summary{border-left-color:var(--accent-a9);background-color:var(--gray-a2);margin-left:-1rem;margin-right:-1rem}.yue details.toggle-details[open] summary{border-radius:.2em .2em 0 0}.yue .toggle-details__container{margin-top:0;margin-bottom:0;padding-top:1rem;padding-bottom:1rem}.yue .toggle-details__container :first-child{margin-top:0}.yue .toggle-details__container :last-child{margin-bottom:0}.yue{--xr-font-color0:var(--sy-c-heading);--xr-font-color2:var(--sy-c-text);--xr-font-color3:var(--sy-c-light);--xr-border-color:var(--sy-c-border);--xr-disabled-color:var(--gray-a6);--xr-background-color:var(--sy-c-background);--xr-background-color-row-even:var(--sy-c-background);--xr-background-color-row-odd:var(--gray-2)}.yue .xr-array-data pre{margin:0}@media not all and (min-width:640px){.max-sm\:max-w-full{max-width:100%}}@media (min-width:768px){.md\:sticky{position:sticky}.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-72{width:18rem}.md\:shrink-0{flex-shrink:0}}@media (min-width:1280px){.xl\:sticky{position:sticky}.xl\:top-16{top:4rem}.xl\:hidden{display:none}.xl\:px-12{padding-left:3rem;padding-right:3rem}.xl\:pl-0{padding-left:0}}@media print{.print\:hidden{display:none}.print\:pt-6{padding-top:1.5rem}}
\ No newline at end of file
diff --git a/latest/_static/shibuya.js b/latest/_static/shibuya.js
deleted file mode 100644
index 94f927f7..00000000
--- a/latest/_static/shibuya.js
+++ /dev/null
@@ -1 +0,0 @@
-(()=>{function _(t){let e=t.getAttribute("aria-controls"),o=document.getElementById(e),c="data-expanded-"+e;t.addEventListener("click",function(){document.body.hasAttribute(c)?(document.body.removeAttribute(c),o.classList.remove("_expanded"),y(e,"false")):(document.body.setAttribute(c,"true"),o.classList.add("_expanded"),y(e,"true"))})}function y(t,e){let o=document.querySelectorAll('[aria-controls="'+t+'"]');for(el of o)el.setAttribute("aria-expanded",e)}var S=document.querySelectorAll(".js-menu");for(let t=0;t{a.parentNode.removeChild(a),document.head.removeChild(t)}),e(),window.addEventListener("resize",e)}var C;var l=["auto","light","dark"],d=document.querySelector(".js-theme");function k(){let t=h();t+=1,l[t]||(t=0);let e=l[t];setColorMode(e),localStorage._theme=e,L(e)}function h(){return l.indexOf(document.documentElement.getAttribute("data-color-mode")||"auto")}function L(t){let e=d.getAttribute("data-aria-"+t);d.setAttribute("aria-label",e)}d&&(d.addEventListener("click",k),L(l[h()]||"auto"));function I(){let t=document.querySelector(".globaltoc");if(!t)return;let e=parseInt(t.getAttribute("data-expand-depth"),10),o=n=>{if(!e)return!1;let s=0;for(;n.parentNode&&n.parentNode!==t;)n=n.parentNode,n.nodeName==="UL"&&(s+=1);return e>=s};t.querySelectorAll("li > ul").forEach(n=>{let s=n.parentNode;s.classList.contains("current")||o(s)?s.classList.add("_expand"):s.classList.add("_collapse");let i=N(n);s.appendChild(i)})}function N(t){let e=document.createElement("button");e.innerHTML=' ';let o=t.parentNode,c=t.previousSibling,n=c.textContent,s=()=>{o.classList.contains("_expand")?e.setAttribute("aria-label","Collapse "+n):e.setAttribute("aria-label","Expand "+n)};s();let i=E=>{E.preventDefault(),o.classList.contains("_expand")?(o.classList.remove("_expand"),o.classList.add("_collapse")):(o.classList.remove("_collapse"),o.classList.add("_expand")),s()};return c.getAttribute("href")==="#"&&c.addEventListener("click",i),e.addEventListener("click",i),e}var f=document.querySelector(".globaltoc a.current");f&&f.scrollIntoViewIfNeeded&&f.scrollIntoViewIfNeeded();I();var v=0,m=200,u=document.querySelectorAll(".yue > section section[id]"),r=document.querySelector(".back-to-top");function w(){let t=document.querySelector(".yue > section");t&&(m=t.computedStyleMap().get("scroll-margin-top").value)}function O(t){let e=t.getBoundingClientRect();return e.top<=m&&e.bottom>=m}function A(t){document.querySelectorAll(".localtoc li.active").forEach(e=>{e.classList.remove("active")}),document.querySelector(`.localtoc a[href="#${t}"]`).parentNode.classList.add("active")}function x(){let t;for(let e=0;e=document.body.offsetHeight){let t=u[u.length-1];t&&A(t.id)}else x();r&&(window.scrollY&&window.scrollY{window.scrollTo(0,0)});window.addEventListener("scroll",j);window.addEventListener("DOMContentLoaded",()=>{w(),x()});window.addEventListener("resize",w);var p=document.querySelector(".js-repo-stats");async function M(t,e){let o=`https://api.github.com/repos/${t}/${e}`,n=await(await fetch(o)).json(),s={stars:n.watchers,forks:n.forks};b(s),sessionStorage.setItem("_sy/repo/stats",JSON.stringify(s))}async function T(t,e){let o="https://gitlab.com/api/v4/projects/"+encodeURIComponent(t+"/"+e),n=await(await fetch(o)).json(),s={stars:n.star_count,forks:n.forks_count};b(s),sessionStorage.setItem("_sy/repo/stats",JSON.stringify(s))}function b({stars:t,forks:e}){t&&(document.querySelector(".js-repo-stars").textContent=t),e&&(document.querySelector(".js-repo-forks").textContent=e)}function B(){let t=sessionStorage.getItem("_sy/repo/stats");if(t)b(JSON.parse(t));else{let e=p.getAttribute("data-user"),o=p.getAttribute("data-repo"),c=p.getAttribute("data-type");c==="github"?M(e,o):c==="gitlab"&&T(e,o)}}p&&B();function R(t,e){let o=document.createElement("script");o.id="_carbonads_js",o.src=`//cdn.carbonads.com/carbon.js?serve=${t}&placement=${e}`;let c=document.querySelector(".yue > section"),n=document.querySelector(".yue > section > section");if(n)c.insertBefore(o,n);else{let s=document.querySelector(".yue > section > p");s?c.insertBefore(o,s.nextSibling):c.appendChild(o)}}var g=document.querySelector(".js-carbon");if(g){let t=g.getAttribute("data-carbon-code"),e=g.getAttribute("data-carbon-placement");t&&e&&R(t,e)}/windows/i.test(navigator.userAgent)&&document.body.classList.add("win");})();
diff --git a/latest/_static/sphinx_highlight.js b/latest/_static/sphinx_highlight.js
deleted file mode 100644
index aae669d7..00000000
--- a/latest/_static/sphinx_highlight.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Highlighting utilities for Sphinx HTML documentation. */
-"use strict";
-
-const SPHINX_HIGHLIGHT_ENABLED = true
-
-/**
- * highlight a given string on a node by wrapping it in
- * span elements with the given class name.
- */
-const _highlight = (node, addItems, text, className) => {
- if (node.nodeType === Node.TEXT_NODE) {
- const val = node.nodeValue;
- const parent = node.parentNode;
- const pos = val.toLowerCase().indexOf(text);
- if (
- pos >= 0 &&
- !parent.classList.contains(className) &&
- !parent.classList.contains("nohighlight")
- ) {
- let span;
-
- const closestNode = parent.closest("body, svg, foreignObject");
- const isInSVG = closestNode && closestNode.matches("svg");
- if (isInSVG) {
- span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
- } else {
- span = document.createElement("span");
- span.classList.add(className);
- }
-
- span.appendChild(document.createTextNode(val.substr(pos, text.length)));
- parent.insertBefore(
- span,
- parent.insertBefore(
- document.createTextNode(val.substr(pos + text.length)),
- node.nextSibling
- )
- );
- node.nodeValue = val.substr(0, pos);
-
- if (isInSVG) {
- const rect = document.createElementNS(
- "http://www.w3.org/2000/svg",
- "rect"
- );
- const bbox = parent.getBBox();
- rect.x.baseVal.value = bbox.x;
- rect.y.baseVal.value = bbox.y;
- rect.width.baseVal.value = bbox.width;
- rect.height.baseVal.value = bbox.height;
- rect.setAttribute("class", className);
- addItems.push({ parent: parent, target: rect });
- }
- }
- } else if (node.matches && !node.matches("button, select, textarea")) {
- node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
- }
-};
-const _highlightText = (thisNode, text, className) => {
- let addItems = [];
- _highlight(thisNode, addItems, text, className);
- addItems.forEach((obj) =>
- obj.parent.insertAdjacentElement("beforebegin", obj.target)
- );
-};
-
-/**
- * Small JavaScript module for the documentation.
- */
-const SphinxHighlight = {
-
- /**
- * highlight the search words provided in localstorage in the text
- */
- highlightSearchWords: () => {
- if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight
-
- // get and clear terms from localstorage
- const url = new URL(window.location);
- const highlight =
- localStorage.getItem("sphinx_highlight_terms")
- || url.searchParams.get("highlight")
- || "";
- localStorage.removeItem("sphinx_highlight_terms")
- url.searchParams.delete("highlight");
- window.history.replaceState({}, "", url);
-
- // get individual terms from highlight string
- const terms = highlight.toLowerCase().split(/\s+/).filter(x => x);
- if (terms.length === 0) return; // nothing to do
-
- // There should never be more than one element matching "div.body"
- const divBody = document.querySelectorAll("div.body");
- const body = divBody.length ? divBody[0] : document.querySelector("body");
- window.setTimeout(() => {
- terms.forEach((term) => _highlightText(body, term, "highlighted"));
- }, 10);
-
- const searchBox = document.getElementById("searchbox");
- if (searchBox === null) return;
- searchBox.appendChild(
- document
- .createRange()
- .createContextualFragment(
- '' +
- '' +
- _("Hide Search Matches") +
- "
"
- )
- );
- },
-
- /**
- * helper function to hide the search marks again
- */
- hideSearchWords: () => {
- document
- .querySelectorAll("#searchbox .highlight-link")
- .forEach((el) => el.remove());
- document
- .querySelectorAll("span.highlighted")
- .forEach((el) => el.classList.remove("highlighted"));
- localStorage.removeItem("sphinx_highlight_terms")
- },
-
- initEscapeListener: () => {
- // only install a listener if it is really needed
- if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return;
-
- document.addEventListener("keydown", (event) => {
- // bail for input elements
- if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
- // bail with special keys
- if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return;
- if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) {
- SphinxHighlight.hideSearchWords();
- event.preventDefault();
- }
- });
- },
-};
-
-_ready(SphinxHighlight.highlightSearchWords);
-_ready(SphinxHighlight.initEscapeListener);
diff --git a/latest/genindex.html b/latest/genindex.html
deleted file mode 100644
index b8b3f23f..00000000
--- a/latest/genindex.html
+++ /dev/null
@@ -1,314 +0,0 @@
-
-
-
-
- Index - ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-Index
-
-
-
A
- |
C
- |
D
- |
E
- |
F
- |
G
- |
I
- |
M
- |
N
- |
R
- |
T
- |
V
-
-
-A
-
-
-
-
- ape_vyper.exceptions
-
-
-
- ape_vyper.interface
-
-
-
-
-
-C
-
-
-D
-
-
-E
-
-
-F
-
-
-G
-
-
-I
-
-
-M
-
-
-N
-
-
-R
-
-
-T
-
-
-V
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/latest/index.html b/latest/index.html
deleted file mode 100644
index c310d654..00000000
--- a/latest/index.html
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
-
-
- ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ape-vyper
- /
-
-
- Vyper Docs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Back to top
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/latest/methoddocs/compiler.html b/latest/methoddocs/compiler.html
deleted file mode 100644
index 23ee5feb..00000000
--- a/latest/methoddocs/compiler.html
+++ /dev/null
@@ -1,480 +0,0 @@
-
-
-
-
- Compiler - ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ape-vyper
- /
-
-
- Compiler
-
-
-
-
-
-
-
-
-
-
-Compiler
-
-
-class ape_vyper.compiler. FileType ( value )
-An enumeration.
-
-
-
-
-class ape_vyper.compiler. Remapping ( _case_sensitive : bool | None = None , _env_prefix : str | None = None , _env_file : DotenvType | None = PosixPath('.') , _env_file_encoding : str | None = None , _env_ignore_empty : bool | None = None , _env_nested_delimiter : str | None = None , _env_parse_none_str : str | None = None , _env_parse_enums : bool | None = None , _cli_prog_name : str | None = None , _cli_parse_args : bool | list [ str ] | tuple [ str , ... ] | None = None , _cli_settings_source : CliSettingsSource [ Any ] | None = None , _cli_parse_none_str : str | None = None , _cli_hide_none_type : bool | None = None , _cli_avoid_json : bool | None = None , _cli_enforce_required : bool | None = None , _cli_use_class_docs_for_groups : bool | None = None , _cli_exit_on_error : bool | None = None , _cli_prefix : str | None = None , _secrets_dir : str | Path | None = None , * , key : str , dependency_name : str , dependency_version : None = None , ** values : Any )
-
-
-
-
-class ape_vyper.compiler. VyperCompiler ( * , compiler_settings : dict = {} )
-
-
-compile ( contract_filepaths : Iterable [ Path ] , project : ProjectManager | None = None , settings : dict | None = None ) → Iterator [ ContractType ]
-Compile the given source files. All compiler plugins must implement this function.
-
-Parameters:
-
-contract_filepaths (Iterable [ pathlib.Path ] ) – A list of source file paths to compile.
-project (Optional[ProjectManager
]) – Optionally provide
-the project containing the base paths and full source set. Defaults to the local
-project. Dependencies will change this value to their respective projects.
-settings (Optional [ dict ] ) – Adhoc compiler settings.
-
-
-Returns:
-list[ContractType
]
-
-
-
-
-
-
-compile_code ( code : str , project : ProjectManager | None = None , ** kwargs ) → ContractType
-Compile a program.
-
-Parameters:
-
-code (str ) – The code to compile.
-project (Optional[ProjectManager
]) – Optionally provide
-the project containing the base paths and full source set. Defaults to the local
-project. Dependencies will change this value to their respective projects.
-settings (Optional [ Dict ] ) – Adhoc compiler settings.
-**kwargs – Additional overrides for the ethpm_types.ContractType
model.
-
-
-Returns:
-A compiled contract artifact.
-
-Return type:
-ContractType
-
-
-
-
-
-
-enrich_error ( err : ContractLogicError ) → ContractLogicError
-Enrich a contract logic error using compiler information, such as
-known PC locations for compiler runtime errors.
-
-Parameters:
-err (ContractLogicError
) – The exception
-to enrich.
-
-Returns:
-The enriched exception.
-
-Return type:
-ContractLogicError
-
-
-
-
-
-
-flatten_contract ( path : Path , project : ProjectManager | None = None , ** kwargs ) → Content
-Returns the flattened contract suitable for compilation or verification as a single file
-
-
-
-
-get_compiler_settings ( contract_filepaths : Iterable [ Path ] , project : ProjectManager | None = None , ** kwargs ) → dict [ packaging.version.Version , dict ]
-Get a mapping of the settings that would be used to compile each of the sources
-by the compiler version number.
-
-Parameters:
-
-contract_filepaths (Iterable [ pathlib.Path ] ) – The list of paths.
-project (Optional[ProjectManager
]) – Optionally provide
-the project containing the base paths and full source set. Defaults to the local
-project. Dependencies will change this value to their respective projects.
-**overrides – Settings overrides.
-
-
-Returns:
-A dict of compiler settings by compiler version.
-
-Return type:
-dict[Version, dict]
-
-
-
-
-
-
-get_import_remapping ( project : ProjectManager | None = None ) → dict [ str , dict ]
-Configured interface imports from dependencies.
-
-
-
-
-get_imports ( contract_filepaths : Iterable [ Path ] , project : ProjectManager | None = None ) → dict [ str , list [ str ] ]
-Returns a list of imports as source_ids for each contract’s source_id in a given
-compiler.
-
-Parameters:
-
-contract_filepaths (Iterable [ pathlib.Path ] ) – A list of source file paths to compile.
-project (Optional[ProjectManager
]) – Optionally provide
-the project containing the base paths and full source set. Defaults to the local
-project. Dependencies will change this value to their respective projects.
-
-
-Returns:
-A dictionary like {source_id: [import_source_id, ...], ...}
-
-Return type:
-dict[str, list[str]]
-
-
-
-
-
-
-get_version_map ( contract_filepaths : Iterable [ Path ] , project : ProjectManager | None = None ) → dict [ packaging.version.Version , set [ pathlib.Path ] ]
-Get a map of versions to source paths.
-
-Parameters:
-
-contract_filepaths (Iterable [ Path ] ) – Input source paths. Defaults to all source paths
-per compiler.
-project (Optional[ProjectManager
]) – Optionally provide
-the project containing the base paths and full source set. Defaults to the local
-project. Dependencies will change this value to their respective projects.
-
-
-Returns:
-dict[Version, set[Path]]
-
-
-
-
-
-
-get_versions ( all_paths : Iterable [ Path ] ) → set [ str ]
-Retrieve the set of available compiler versions for this plugin to compile all_paths
.
-
-Parameters:
-all_paths (Iterable [ pathlib.Path ] ) – The list of paths.
-
-Returns:
-A set of available compiler versions.
-
-Return type:
-set[str]
-
-
-
-
-
-
-init_coverage_profile ( source_coverage : ContractSourceCoverage , contract_source : ContractSource )
-Initialize an empty report for the given source ID. Modifies the given source
-coverage in-place.
-
-Parameters:
-
-
-
-
-
-
-
-property name : str
-The name of the compiler.
-
-
-
-
-trace_source ( contract_source : ContractSource , trace : TraceAPI , calldata : HexBytes ) → SourceTraceback
-Get a source-traceback for the given contract type.
-The source traceback object contains all the control paths taken in the transaction.
-When available, source-code location information is accessible from the object.
-
-Parameters:
-
-contract_source (ContractSource
) – A contract type with a local-source that was
-compiled by this compiler.
-trace (TraceAPI
]) – The resulting trace from executing a
-function defined in the given contract type.
-calldata (HexBytes
) – Calldata passed to the top-level call.
-
-
-Returns:
-SourceTraceback
-
-
-
-
-
-
-
-
-class ape_vyper.compiler. VyperConfig ( _case_sensitive : bool | None = None , _env_prefix : str | None = None , _env_file : DotenvType | None = PosixPath('.') , _env_file_encoding : str | None = None , _env_ignore_empty : bool | None = None , _env_nested_delimiter : str | None = None , _env_parse_none_str : str | None = None , _env_parse_enums : bool | None = None , _cli_prog_name : str | None = None , _cli_parse_args : bool | list [ str ] | tuple [ str , ... ] | None = None , _cli_settings_source : CliSettingsSource [ Any ] | None = None , _cli_parse_none_str : str | None = None , _cli_hide_none_type : bool | None = None , _cli_avoid_json : bool | None = None , _cli_enforce_required : bool | None = None , _cli_use_class_docs_for_groups : bool | None = None , _cli_exit_on_error : bool | None = None , _cli_prefix : str | None = None , _secrets_dir : str | Path | None = None , * , version : SpecifierSet | None = None , evm_version : str | None = None , import_remapping : list [ ape_vyper.compiler.Remapping ] = [] , ** values : Any )
-
-
-evm_version : str | None
-The evm-version or hard-fork name.
-
-
-
-
-import_remapping : list [ ape_vyper.compiler.Remapping ]
-Configuration of an import name mapped to a dependency listing.
-To use a specific version of a dependency, specify using @
symbol.
-Usage example:
-vyper :
- import_remapping :
- - "dep_a=dependency_a@0.1.1"
- - "dep_b=dependency" # Uses only version. Will raise if more than 1.
-
-
-
-
-
-
-version : SpecifierSet | None
-Configure a version to use for all files,
-regardless of pragma.
-
-
-
-
-
-
-ape_vyper.compiler. get_evmversion_pragma ( source : str | Path ) → str | None
-Extracts evm version pragma information from Vyper source code.
-
-Parameters:
-source (Union [ str , Path ] ) – Vyper source code
-
-Returns:
-str
, or None if no valid pragma is found.
-
-
-
-
-
-
-ape_vyper.compiler. get_optimization_pragma ( source : str | Path ) → str | None
-Extracts optimization pragma information from Vyper source code.
-
-Parameters:
-source (Union [ str , Path ] ) – Vyper source code
-
-Returns:
-str
, or None if no valid pragma is found.
-
-
-
-
-
-
-ape_vyper.compiler. get_version_pragma_spec ( source : str | Path ) → SpecifierSet | None
-Extracts version pragma information from Vyper source code.
-
-Parameters:
-source (str ) – Vyper source code
-
-Returns:
-packaging.specifiers.SpecifierSet
, or None if no valid pragma is found.
-
-
-
-
-
-
-
-
-
-
- Back to top
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/latest/methoddocs/exceptions.html b/latest/methoddocs/exceptions.html
deleted file mode 100644
index 75db9da7..00000000
--- a/latest/methoddocs/exceptions.html
+++ /dev/null
@@ -1,261 +0,0 @@
-
-
-
-
- Exceptions - ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ape-vyper
- /
-
-
- Exceptions
-
-
-
-
-
-
-
-
-
-
-Exceptions
-
-
-exception ape_vyper.exceptions. DivisionByZeroError ( ** kwargs )
-Raised when dividing by zero.
-
-
-
-
-exception ape_vyper.exceptions. FallbackNotDefinedError ( ** kwargs )
-Raised when calling a contract directly (with missing method bytes) that has no fallback
-method defined in its ABI.
-
-
-
-
-exception ape_vyper.exceptions. IndexOutOfRangeError ( ** kwargs )
-Raised when accessing an array using an out-of-range index.
-
-
-
-
-exception ape_vyper.exceptions. IntegerBoundsCheck ( _type : str , ** kwargs )
-Raised when receiving any integer bounds check failure.
-
-
-
-
-exception ape_vyper.exceptions. IntegerOverflowError ( ** kwargs )
-Raised when addition results in an integer exceeding its max size.
-
-
-
-
-exception ape_vyper.exceptions. IntegerUnderflowError ( ** kwargs )
-Raised when addition results in an integer exceeding its max size.
-
-
-
-
-exception ape_vyper.exceptions. InvalidCalldataOrValueError ( ** kwargs )
-Raises on Vyper versions >= 0.3.10 in place of NonPayableError.
-
-
-
-
-exception ape_vyper.exceptions. ModuloByZeroError ( ** kwargs )
-Raised when modding by zero.
-
-
-
-
-exception ape_vyper.exceptions. NonPayableError ( ** kwargs )
-Raised when sending ether to a non-payable function.
-
-
-
-
-class ape_vyper.exceptions. RuntimeErrorType ( value )
-An enumeration.
-
-
-
-
-exception ape_vyper.exceptions. VyperCompileError ( err : VyperError | str )
-A compiler-specific error in Vyper.
-
-
-
-
-exception ape_vyper.exceptions. VyperCompilerPluginError
-An error raised in the Vyper compiler.
-
-
-
-
-exception ape_vyper.exceptions. VyperInstallError
-An error raised failing to install Vyper.
-
-
-
-
-exception ape_vyper.exceptions. VyperRuntimeError ( error_type : RuntimeErrorType | str , ** kwargs )
-An error raised when running EVM code, such as a index or math error.
-It is a type of ContractLogicError
where the code came from the
-compiler and not directly from the source.
-
-
-
-
-
-
-
-
- Back to top
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/latest/methoddocs/interface.html b/latest/methoddocs/interface.html
deleted file mode 100644
index 303a4514..00000000
--- a/latest/methoddocs/interface.html
+++ /dev/null
@@ -1,236 +0,0 @@
-
-
-
-
- Interface - ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ape-vyper
- /
-
-
- Interface
-
-
-
-
-
-
-
-
-
-
-Interface
-Tools for working with ABI specs and Vyper interface source code
-
-
-ape_vyper.interface. abi_to_type ( iface : dict [ str , Any ] ) → ConstructorABI | FallbackABI | ReceiveABI | MethodABI | EventABI | ErrorABI | StructABI | UnprocessedABI | None
-Convert a dict JSON-like interface to an ethpm-types ABI type
-
-
-
-
-Extract import aliases from import lines
-
-Returns:
-{import: alias}
-
-Return type:
-Dict[str, str]
-
-
-
-
-
-
-Extract import lines from the source, return them and the source without imports
-
-Returns:
-(stdlib_import_lines, interface_import_lines, cleaned_source)
-
-Return type:
-Tuple[str, str, str]
-
-
-
-
-
-
-Extract version pragma, and return cleaned source
-
-
-
-
-ape_vyper.interface. generate_inputs ( inputs : list [ ethpm_types.abi.ABIType ] ) → str
-Generate the source code input args from ABI inputs
-
-
-
-
-ape_vyper.interface. generate_interface ( abi : list [ dict [ str , Any ] ] | list [ Union [ ethpm_types.abi.ConstructorABI , ethpm_types.abi.FallbackABI , ethpm_types.abi.ReceiveABI , ethpm_types.abi.MethodABI , ethpm_types.abi.EventABI , ethpm_types.abi.ErrorABI , ethpm_types.abi.StructABI , ethpm_types.abi.UnprocessedABI ] ] , iface_name : str ) → str
-Generate a Vyper interface source code from an ABI spec
-
-Parameters:
-
-abi (List [ Union [ Dict [ str , Any ] , ABI ] ] ) – An ABI spec for a contract
-iface_name (str ) – The name of the interface
-
-
-Returns:
-str
Vyper source code for the interface
-
-
-
-
-
-
-ape_vyper.interface. generate_method ( abi : MethodABI ) → str
-Generate Vyper interface method definition
-
-
-
-
-ape_vyper.interface. indent_line ( line : str , level = 1 ) → str
-Indent a source line of code
-
-
-
-
-
-
-
-
- Back to top
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/latest/objects.inv b/latest/objects.inv
deleted file mode 100644
index 2fcdcb64..00000000
Binary files a/latest/objects.inv and /dev/null differ
diff --git a/latest/py-modindex.html b/latest/py-modindex.html
deleted file mode 100644
index 08c1b4fb..00000000
--- a/latest/py-modindex.html
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-
-
- Python Module Index - ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Python Module Index
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/latest/search.html b/latest/search.html
deleted file mode 100644
index c636fd31..00000000
--- a/latest/search.html
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
-
- Search - ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Search
-
-
-
-
- Please activate JavaScript to enable the search
- functionality.
-
-
-
-
-
-
- Searching for multiple words only shows matches that contain
- all words.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/latest/searchindex.js b/latest/searchindex.js
deleted file mode 100644
index 95c8f625..00000000
--- a/latest/searchindex.js
+++ /dev/null
@@ -1 +0,0 @@
-Search.setIndex({"docnames": ["index", "methoddocs/compiler", "methoddocs/exceptions", "methoddocs/interface", "userguides/quickstart"], "filenames": ["index.md", "methoddocs/compiler.md", "methoddocs/exceptions.md", "methoddocs/interface.md", "userguides/quickstart.md"], "titles": ["Vyper Docs", "Compiler", "Exceptions", "Interface", "Quick Start"], "terms": {"quick": 0, "start": 0, "compil": [0, 2], "except": [0, 1], "interfac": [0, 1], "class": [1, 2], "ape_vyp": [1, 2, 3], "filetyp": 1, "valu": [1, 2, 4], "an": [1, 2, 3, 4], "enumer": [1, 2], "remap": 1, "_case_sensit": 1, "bool": 1, "none": [1, 3], "_env_prefix": 1, "str": [1, 2, 3], "_env_fil": 1, "dotenvtyp": 1, "posixpath": 1, "_env_file_encod": 1, "_env_ignore_empti": 1, "_env_nested_delimit": 1, "_env_parse_none_str": 1, "_env_parse_enum": 1, "_cli_prog_nam": 1, "_cli_parse_arg": 1, "list": [1, 3, 4], "tupl": [1, 3], "_cli_settings_sourc": 1, "clisettingssourc": 1, "ani": [1, 2, 3, 4], "_cli_parse_none_str": 1, "_cli_hide_none_typ": 1, "_cli_avoid_json": 1, "_cli_enforce_requir": 1, "_cli_use_class_docs_for_group": 1, "_cli_exit_on_error": 1, "_cli_prefix": 1, "_secrets_dir": 1, "path": 1, "kei": [1, 4], "dependency_nam": 1, "dependency_vers": 1, "vypercompil": 1, "compiler_set": 1, "dict": [1, 3], "contract_filepath": 1, "iter": 1, "project": [1, 4], "projectmanag": 1, "set": [1, 4], "contracttyp": [1, 4], "given": 1, "sourc": [1, 2, 3, 4], "file": [1, 4], "all": 1, "plugin": [1, 4], "must": [1, 4], "implement": 1, "thi": [1, 4], "function": [1, 2], "paramet": [1, 3], "pathlib": 1, "A": [1, 2], "option": [1, 3], "provid": 1, "contain": 1, "base": [1, 4], "full": 1, "default": [1, 4], "local": 1, "depend": 1, "chang": 1, "respect": 1, "adhoc": 1, "return": [1, 3], "compile_cod": 1, "code": [1, 2, 3], "kwarg": [1, 2], "program": 1, "The": [1, 3, 4], "addit": [1, 2], "overrid": [1, 4], "ethpm_typ": [1, 3], "model": 1, "contract": [1, 2, 3], "artifact": 1, "type": [1, 2, 3, 4], "enrich_error": 1, "err": [1, 2], "contractlogicerror": [1, 2], "enrich": 1, "logic": 1, "error": [1, 2], "us": [1, 2, 4], "inform": 1, "known": 1, "pc": 1, "locat": 1, "runtim": 1, "flatten_contract": 1, "content": 1, "flatten": 1, "suitabl": 1, "verif": 1, "singl": [1, 4], "get_compiler_set": 1, "packag": 1, "version": [1, 2, 3], "get": [1, 4], "map": 1, "would": 1, "each": 1, "number": 1, "get_import_remap": 1, "configur": [1, 4], "import": [1, 3, 4], "from": [1, 2, 3, 4], "get_import": 1, "source_id": 1, "": [1, 4], "dictionari": 1, "like": [1, 3, 4], "import_source_id": 1, "get_version_map": 1, "input": [1, 3], "per": 1, "get_vers": 1, "all_path": 1, "retriev": 1, "avail": [1, 4], "init_coverage_profil": 1, "source_coverag": 1, "contractsourcecoverag": 1, "contract_sourc": 1, "contractsourc": 1, "initi": 1, "empti": 1, "report": [1, 4], "id": 1, "modifi": 1, "coverag": 1, "place": [1, 2, 4], "sourcecoverag": 1, "gener": [1, 3], "profil": 1, "properti": 1, "name": [1, 3, 4], "trace_sourc": 1, "trace": 1, "traceapi": 1, "calldata": 1, "hexbyt": 1, "sourcetraceback": 1, "traceback": 1, "object": 1, "control": 1, "taken": 1, "transact": 1, "when": [1, 2, 4], "i": [1, 2, 4], "access": [1, 2], "wa": 1, "result": [1, 2], "execut": 1, "defin": [1, 2], "pass": 1, "top": 1, "level": [1, 3], "call": [1, 2], "vyperconfig": 1, "specifierset": 1, "evm_vers": [1, 4], "import_remap": [1, 4], "evm": [1, 2], "hard": 1, "fork": 1, "To": 1, "specif": [1, 2, 4], "specifi": [1, 4], "symbol": 1, "usag": 1, "exampl": [1, 4], "vyper": [1, 2, 3, 4], "dep_a": 1, "dependency_a": 1, "0": [1, 2, 4], "1": [1, 3], "dep_b": 1, "onli": 1, "Will": 1, "rais": [1, 2], "more": 1, "than": 1, "regardless": 1, "pragma": [1, 3], "get_evmversion_pragma": 1, "extract": [1, 3], "union": [1, 3], "valid": [1, 4], "found": [1, 4], "get_optimization_pragma": 1, "optim": 1, "get_version_pragma_spec": 1, "divisionbyzeroerror": 2, "divid": 2, "zero": 2, "fallbacknotdefinederror": 2, "directli": [2, 4], "miss": 2, "method": [2, 3], "byte": 2, "ha": 2, "fallback": 2, "its": 2, "abi": [2, 3], "indexoutofrangeerror": 2, "arrai": 2, "out": [2, 4], "rang": 2, "index": 2, "integerboundscheck": 2, "_type": 2, "receiv": 2, "integ": 2, "bound": 2, "check": 2, "failur": 2, "integeroverflowerror": 2, "exceed": 2, "max": 2, "size": 2, "integerunderflowerror": 2, "invalidcalldataorvalueerror": 2, "3": [2, 4], "10": [2, 4], "nonpayableerror": 2, "modulobyzeroerror": 2, "mod": 2, "send": 2, "ether": 2, "non": 2, "payabl": 2, "runtimeerrortyp": 2, "vypercompileerror": 2, "vypererror": 2, "vypercompilerpluginerror": 2, "vyperinstallerror": 2, "fail": 2, "instal": 2, "vyperruntimeerror": 2, "error_typ": 2, "run": [2, 4], "math": 2, "It": 2, "where": [2, 4], "came": 2, "tool": 3, "work": 3, "spec": 3, "abi_to_typ": 3, "ifac": [3, 4], "constructorabi": 3, "fallbackabi": 3, "receiveabi": 3, "methodabi": 3, "eventabi": 3, "errorabi": 3, "structabi": 3, "unprocessedabi": 3, "convert": 3, "json": [3, 4], "ethpm": 3, "extract_import_alias": 3, "alias": 3, "line": 3, "alia": 3, "extract_import": 3, "them": [3, 4], "without": 3, "stdlib_import_lin": 3, "interface_import_lin": 3, "cleaned_sourc": 3, "extract_meta": 3, "source_cod": 3, "clean": 3, "generate_input": 3, "abityp": 3, "arg": 3, "generate_interfac": 3, "iface_nam": 3, "generate_method": 3, "definit": 3, "indent_lin": 3, "indent": 3, "ap": 4, "around": 4, "vvm": 4, "python3": 4, "up": 4, "12": 4, "you": 4, "can": 4, "latest": 4, "releas": 4, "clone": 4, "repositori": 4, "most": 4, "date": 4, "git": 4, "http": 4, "github": 4, "com": 4, "apeworx": 4, "cd": 4, "setup": 4, "py": 4, "first": 4, "extens": 4, "vy": 4, "your": 4, "folder": 4, "here": 4, "Then": 4, "root": 4, "command": 4, "deploi": 4, "interact": 4, "For": 4, "eas": 4, "publish": 4, "some": 4, "other": 4, "case": 4, "sometim": 4, "combin": 4, "togeth": 4, "wai": 4, "understand": 4, "do": 4, "so": 4, "mycontract": 4, "build": 4, "mycontractflatten": 4, "warn": 4, "featur": 4, "experiment": 4, "pleas": 4, "bug": 4, "find": 4, "try": 4, "By": 4, "howev": 4, "also": 4, "config": 4, "yaml": 4, "7": 4, "whatev": 4, "rule": 4, "ar": 4, "what": 4, "comment": 4, "post": 4, "v0": 4, "might": 4, "want": 4, "differ": 4, "arbitrum": 4, "new": 4, "opcod": 4, "support": 4, "yet": 4, "If": 4, "requir": 4, "pari": 4, "note": 4, "chosen": 4, "thu": 4, "directori": 4, "contracts_fold": 4, "e": 4, "g": 4, "altern": 4, "under": 4, "vote": 4, "vyperlang": 4, "repo": 4, "vypervot": 4, "8": 4, "automat": 4, "allow": 4, "ballot": 4, "format": 4, "codes": 4}, "objects": {"ape_vyper": [[1, 0, 0, "-", "compiler"], [2, 0, 0, "-", "exceptions"], [3, 0, 0, "-", "interface"]], "ape_vyper.compiler": [[1, 1, 1, "", "FileType"], [1, 1, 1, "", "Remapping"], [1, 1, 1, "", "VyperCompiler"], [1, 1, 1, "", "VyperConfig"], [1, 5, 1, "", "get_evmversion_pragma"], [1, 5, 1, "", "get_optimization_pragma"], [1, 5, 1, "", "get_version_pragma_spec"]], "ape_vyper.compiler.VyperCompiler": [[1, 2, 1, "", "compile"], [1, 2, 1, "", "compile_code"], [1, 2, 1, "", "enrich_error"], [1, 2, 1, "", "flatten_contract"], [1, 2, 1, "", "get_compiler_settings"], [1, 2, 1, "", "get_import_remapping"], [1, 2, 1, "", "get_imports"], [1, 2, 1, "", "get_version_map"], [1, 2, 1, "", "get_versions"], [1, 2, 1, "", "init_coverage_profile"], [1, 3, 1, "", "name"], [1, 2, 1, "", "trace_source"]], "ape_vyper.compiler.VyperConfig": [[1, 4, 1, "", "evm_version"], [1, 4, 1, "", "import_remapping"], [1, 4, 1, "", "version"]], "ape_vyper.exceptions": [[2, 6, 1, "", "DivisionByZeroError"], [2, 6, 1, "", "FallbackNotDefinedError"], [2, 6, 1, "", "IndexOutOfRangeError"], [2, 6, 1, "", "IntegerBoundsCheck"], [2, 6, 1, "", "IntegerOverflowError"], [2, 6, 1, "", "IntegerUnderflowError"], [2, 6, 1, "", "InvalidCalldataOrValueError"], [2, 6, 1, "", "ModuloByZeroError"], [2, 6, 1, "", "NonPayableError"], [2, 1, 1, "", "RuntimeErrorType"], [2, 6, 1, "", "VyperCompileError"], [2, 6, 1, "", "VyperCompilerPluginError"], [2, 6, 1, "", "VyperInstallError"], [2, 6, 1, "", "VyperRuntimeError"]], "ape_vyper.interface": [[3, 5, 1, "", "abi_to_type"], [3, 5, 1, "", "extract_import_aliases"], [3, 5, 1, "", "extract_imports"], [3, 5, 1, "", "extract_meta"], [3, 5, 1, "", "generate_inputs"], [3, 5, 1, "", "generate_interface"], [3, 5, 1, "", "generate_method"], [3, 5, 1, "", "indent_line"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:attribute", "5": "py:function", "6": "py:exception"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "function", "Python function"], "6": ["py", "exception", "Python exception"]}, "titleterms": {"vyper": 0, "doc": 0, "user": 0, "guid": 0, "python": 0, "refer": 0, "compil": [1, 4], "except": 2, "interfac": [3, 4], "quick": 4, "start": 4, "depend": 4, "instal": 4, "via": 4, "pip": 4, "setuptool": 4, "usag": 4, "contract": 4, "flatten": 4, "version": 4, "evm": 4, "pragma": 4, "optim": 4}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 57}, "alltitles": {"Vyper Docs": [[0, "vyper-docs"]], "User Guides": [[0, null]], "Python Reference": [[0, null]], "Compiler": [[1, "module-ape_vyper.compiler"]], "Exceptions": [[2, "module-ape_vyper.exceptions"]], "Interface": [[3, "module-ape_vyper.interface"]], "Quick Start": [[4, "quick-start"]], "Dependencies": [[4, "dependencies"]], "Installation": [[4, "installation"]], "via pip": [[4, "via-pip"]], "via setuptools": [[4, "via-setuptools"]], "Quick Usage": [[4, "quick-usage"]], "Contract Flattening": [[4, "contract-flattening"]], "Compiler Version": [[4, "compiler-version"]], "EVM Versioning": [[4, "evm-versioning"]], "Interfaces": [[4, "interfaces"]], "Pragmas": [[4, "pragmas"]], "Version Pragma": [[4, "version-pragma"]], "EVM Version Pragma": [[4, "evm-version-pragma"]], "Optimization Pragma": [[4, "optimization-pragma"]]}, "indexentries": {"filetype (class in ape_vyper.compiler)": [[1, "ape_vyper.compiler.FileType"]], "remapping (class in ape_vyper.compiler)": [[1, "ape_vyper.compiler.Remapping"]], "vypercompiler (class in ape_vyper.compiler)": [[1, "ape_vyper.compiler.VyperCompiler"]], "vyperconfig (class in ape_vyper.compiler)": [[1, "ape_vyper.compiler.VyperConfig"]], "ape_vyper.compiler": [[1, "module-ape_vyper.compiler"]], "compile() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.compile"]], "compile_code() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.compile_code"]], "enrich_error() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.enrich_error"]], "evm_version (ape_vyper.compiler.vyperconfig attribute)": [[1, "ape_vyper.compiler.VyperConfig.evm_version"]], "flatten_contract() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.flatten_contract"]], "get_compiler_settings() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.get_compiler_settings"]], "get_evmversion_pragma() (in module ape_vyper.compiler)": [[1, "ape_vyper.compiler.get_evmversion_pragma"]], "get_import_remapping() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.get_import_remapping"]], "get_imports() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.get_imports"]], "get_optimization_pragma() (in module ape_vyper.compiler)": [[1, "ape_vyper.compiler.get_optimization_pragma"]], "get_version_map() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.get_version_map"]], "get_version_pragma_spec() (in module ape_vyper.compiler)": [[1, "ape_vyper.compiler.get_version_pragma_spec"]], "get_versions() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.get_versions"]], "import_remapping (ape_vyper.compiler.vyperconfig attribute)": [[1, "ape_vyper.compiler.VyperConfig.import_remapping"]], "init_coverage_profile() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.init_coverage_profile"]], "module": [[1, "module-ape_vyper.compiler"], [2, "module-ape_vyper.exceptions"], [3, "module-ape_vyper.interface"]], "name (ape_vyper.compiler.vypercompiler property)": [[1, "ape_vyper.compiler.VyperCompiler.name"]], "trace_source() (ape_vyper.compiler.vypercompiler method)": [[1, "ape_vyper.compiler.VyperCompiler.trace_source"]], "version (ape_vyper.compiler.vyperconfig attribute)": [[1, "ape_vyper.compiler.VyperConfig.version"]], "divisionbyzeroerror": [[2, "ape_vyper.exceptions.DivisionByZeroError"]], "fallbacknotdefinederror": [[2, "ape_vyper.exceptions.FallbackNotDefinedError"]], "indexoutofrangeerror": [[2, "ape_vyper.exceptions.IndexOutOfRangeError"]], "integerboundscheck": [[2, "ape_vyper.exceptions.IntegerBoundsCheck"]], "integeroverflowerror": [[2, "ape_vyper.exceptions.IntegerOverflowError"]], "integerunderflowerror": [[2, "ape_vyper.exceptions.IntegerUnderflowError"]], "invalidcalldataorvalueerror": [[2, "ape_vyper.exceptions.InvalidCalldataOrValueError"]], "modulobyzeroerror": [[2, "ape_vyper.exceptions.ModuloByZeroError"]], "nonpayableerror": [[2, "ape_vyper.exceptions.NonPayableError"]], "runtimeerrortype (class in ape_vyper.exceptions)": [[2, "ape_vyper.exceptions.RuntimeErrorType"]], "vypercompileerror": [[2, "ape_vyper.exceptions.VyperCompileError"]], "vypercompilerpluginerror": [[2, "ape_vyper.exceptions.VyperCompilerPluginError"]], "vyperinstallerror": [[2, "ape_vyper.exceptions.VyperInstallError"]], "vyperruntimeerror": [[2, "ape_vyper.exceptions.VyperRuntimeError"]], "ape_vyper.exceptions": [[2, "module-ape_vyper.exceptions"]], "abi_to_type() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.abi_to_type"]], "ape_vyper.interface": [[3, "module-ape_vyper.interface"]], "extract_import_aliases() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.extract_import_aliases"]], "extract_imports() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.extract_imports"]], "extract_meta() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.extract_meta"]], "generate_inputs() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.generate_inputs"]], "generate_interface() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.generate_interface"]], "generate_method() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.generate_method"]], "indent_line() (in module ape_vyper.interface)": [[3, "ape_vyper.interface.indent_line"]]}})
\ No newline at end of file
diff --git a/latest/userguides/quickstart.html b/latest/userguides/quickstart.html
deleted file mode 100644
index 82e6f548..00000000
--- a/latest/userguides/quickstart.html
+++ /dev/null
@@ -1,300 +0,0 @@
-
-
-
-
- Quick Start - ape-vyper documentation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ape-vyper
- /
-
-
- Quick Start
-
-
-
-
-
-
-
-
-
-
-Quick Start
-Ape compiler plugin around VVM
-
-
-Installation
-
-via pip
-You can install the latest release via pip
:
-
-
-
-
-
-Quick Usage
-First, place Vyper contract source files (files with extension .vy
) in your Ape project’s contracts folder.
-An example Vyper contract can be found here .
-Then, from your root Ape project folder, run the command:
-
-The .vy
files in your project will compile into ContractTypes
that you can deploy and interact with in Ape.
-
-Contract Flattening
-For ease of publishing, validation, and some other cases it’s sometimes useful to “flatten” your contract into a single file.
-This combines your contract and any imported interfaces together in a way the compiler can understand.
-You can do so with a command like this:
-ape vyper flatten contracts/MyContract.vy build/MyContractFlattened.vy
-
-
-
-[!WARNING]
-This feature is experimental. Please report any bugs you find when trying it out.
-
-
-
-Compiler Version
-By default, the ape-vyper
plugin uses version pragma for version specification.
-However, you can also configure the version directly in your ape-config.yaml
file:
-vyper :
- version : 0.3.7
-
-
-
-
-EVM Versioning
-By default, ape-vyper
will use whatever version of EVM rules are set as default in the compiler version that gets used,
-or based on what the #pragma evm-version ...
pragma comment specifies (available post-v0.3.10
).
-Sometimes, you might want to use a different version, such as deploying on Arbitrum or Optimism where new opcodes are not supported yet.
-If you want to require a different version of EVM rules to use in the configuration of the compiler, set it in your ape-config.yaml
like this:
-vyper :
- evm_version : paris
-
-
-NOTE : The config value chosen will not override if a pragma is set in a contract.
-
-
-Interfaces
-You can not compile interface source files directly.
-Thus, you must place interface files in a directory named interfaces
in your contracts_folder
e.g. contracts/interfaces/IFace.vy
.
-Then, these files can be imported in other .vy
sources files via:
-import interfaces.IFace as IFace
-
-
-Alternatively, use JSON interfaces from dependency contract types by listing them under the import_remapping
key:
-# Use `voting` example contracts from Vyperlang repo.
-dependencies :
- - name : VyperVoting
- github : vyperlang/vyper
- contracts_folder : examples/voting/
- version : v0.3.8
-
- # Automatically allow importing voting contracts in your project.
-vyper :
- import_remapping :
- - "voting=VyperVoting@v0.3.8"
-
-
-Import the voting contract types like this:
-# @version 0.3.10
-
- import voting.ballot as ballot
-
-
-
-
-Pragmas
-Ape-Vyper supports Vyper 0.3.10’s new pragma formats
-
-
-EVM Version Pragma
-#pragma evm-version paris
-
-
-
-
-Optimization Pragma
-#pragma optimize codesize
-
-
-
-
-
-
-
-
-
-
-
- Back to top
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index 196f5504..00000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,38 +0,0 @@
-[build-system]
-requires = ["setuptools>=51.1.1", "wheel", "setuptools_scm[toml]>=5.0"]
-
-[tool.mypy]
-exclude = "build/"
-plugins = ["pydantic.mypy"]
-
-[tool.setuptools_scm]
-write_to = "ape_vyper/version.py"
-
-# NOTE: you have to use single-quoted strings in TOML for regular expressions.
-# It's the equivalent of r-strings in Python. Multiline strings are treated as
-# verbose regular expressions by Black. Use [ ] to denote a significant space
-# character.
-
-[tool.black]
-line-length = 100
-target-version = ['py310', 'py311', 'py312']
-include = '\.pyi?$'
-
-[tool.pytest.ini_options]
-norecursedirs = "projects"
-addopts = """
- -p no:ape_test
-"""
-python_files = "test_*.py"
-testpaths = "tests"
-markers = "fuzzing: Run Hypothesis fuzz test suite"
-
-[tool.isort]
-line_length = 100
-force_grid_wrap = 0
-include_trailing_comma = true
-multi_line_output = 3
-use_parentheses = true
-
-[tool.mdformat]
-number = true
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 1c2ef4d5..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-[flake8]
-max-line-length = 100
-exclude =
- venv*
- docs
- build
diff --git a/setup.py b/setup.py
deleted file mode 100644
index ca1bc907..00000000
--- a/setup.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-from setuptools import find_packages, setup
-
-extras_require = {
- "test": [ # `test` GitHub Action jobs uses this
- "pytest>=6.0", # Core testing package
- "pytest-mock",
- "pytest-xdist", # multi-process runner
- "pytest-cov", # Coverage analyzer plugin
- "hypothesis>=6.2.0,<7.0", # Strategy-based fuzzer
- "snekmate", # Python package-sources integration testing
- ],
- "lint": [
- "black>=24.4.2,<25", # Auto-formatter and linter
- "mypy>=1.10.1,<2", # Static type analyzer
- "types-setuptools", # Needed due to mypy typeshed
- "flake8>=7.1.0,<8", # Style linter
- "isort>=5.13.2", # Import sorting linter
- "mdformat>=0.7.17", # Auto-formatter for markdown
- "mdformat-gfm>=0.3.5", # Needed for formatting GitHub-flavored markdown
- "mdformat-frontmatter>=0.4.1", # Needed for frontmatters-style headers in issue templates
- "mdformat-pyproject>=0.0.1", # Allows configuring in pyproject.toml
- ],
- "release": [ # `release` GitHub Action job uses this
- "setuptools", # Installation tool
- "wheel", # Packaging tool
- "twine", # Package upload tool
- ],
- "dev": [
- "commitizen", # Manage commits and publishing releases
- "pre-commit", # Ensure that linters are run prior to committing
- "pytest-watch", # `ptw` test watcher/runner
- "IPython", # Console for interacting
- "ipdb", # Debugger (Must use `export PYTHONBREAKPOINT=ipdb.set_trace`)
- ],
-}
-
-# NOTE: `pip install -e .[dev]` to install package
-extras_require["dev"] = (
- extras_require["test"]
- + extras_require["lint"]
- + extras_require["release"]
- + extras_require["dev"]
-)
-
-with open("./README.md") as readme:
- long_description = readme.read()
-
-
-setup(
- name="ape-vyper",
- use_scm_version=True,
- setup_requires=["setuptools_scm"],
- description="Plugin for Ape Ethereum Framework for compiling Vyper contracts",
- long_description=long_description,
- long_description_content_type="text/markdown",
- author="ApeWorX Ltd.",
- author_email="admin@apeworx.io",
- url="https://github.com/ApeWorX/ape-vyper",
- include_package_data=True,
- install_requires=[
- "eth-ape>=0.8.7,<0.9",
- "ethpm-types", # Use same version as eth-ape
- "tqdm", # Use same version as eth-ape
- "vvm>=0.2.0,<0.3",
- "vyper>=0.3.7,<0.5",
- ],
- python_requires=">=3.10,<4",
- extras_require=extras_require,
- py_modules=["ape_vyper"],
- entry_points={
- "ape_cli_subcommands": [
- "ape_vyper=ape_vyper._cli:cli",
- ],
- },
- license="Apache-2.0",
- zip_safe=False,
- keywords="ethereum",
- packages=find_packages(exclude=["tests", "tests.*"]),
- package_data={"ape_vyper": ["py.typed"]},
- classifiers=[
- "Development Status :: 5 - Production/Stable",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: MIT License",
- "Natural Language :: English",
- "Operating System :: MacOS",
- "Operating System :: POSIX",
- "Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.10",
- "Programming Language :: Python :: 3.11",
- "Programming Language :: Python :: 3.12",
- ],
-)
diff --git a/tests/ExampleDependency/contracts/Dependency.vy b/tests/ExampleDependency/contracts/Dependency.vy
deleted file mode 100644
index 15e83484..00000000
--- a/tests/ExampleDependency/contracts/Dependency.vy
+++ /dev/null
@@ -1,4 +0,0 @@
-@view
-@external
-def read_stuff_2() -> uint256:
- return 123
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/ape-config.yaml b/tests/ape-config.yaml
deleted file mode 100644
index bd35d1e3..00000000
--- a/tests/ape-config.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-# Allows compiling to work from the project-level.
-contracts_folder: contracts/passing_contracts
-
-# Specify a dependency to use in Vyper imports.
-dependencies:
- - name: exampledependency
- local: ./ExampleDependency
diff --git a/tests/conftest.py b/tests/conftest.py
deleted file mode 100644
index e2ce1825..00000000
--- a/tests/conftest.py
+++ /dev/null
@@ -1,218 +0,0 @@
-import os
-import shutil
-from contextlib import contextmanager
-from pathlib import Path
-
-import ape
-import pytest
-import vvm # type: ignore
-from ape.contracts import ContractContainer
-from ape.utils import create_tempdir
-from click.testing import CliRunner
-
-BASE_CONTRACTS_PATH = Path(__file__).parent / "contracts"
-TEMPLATES_PATH = BASE_CONTRACTS_PATH / "templates"
-FAILING_BASE = BASE_CONTRACTS_PATH / "failing_contracts"
-PASSING_BASE = BASE_CONTRACTS_PATH / "passing_contracts"
-ALL_VERSIONS = (
- "0.2.1",
- "0.2.2",
- "0.2.3",
- "0.2.15",
- "0.2.16",
- "0.3.0",
- "0.3.1",
- "0.3.2",
- "0.3.3",
- "0.3.4",
- "0.3.7",
- "0.3.9",
- "0.3.10",
- "0.4.0",
-)
-
-CONTRACT_VERSION_GEN_MAP = {
- "": (
- "0.3.7",
- "0.3.9",
- "0.3.10",
- ),
- "sub_reverts": [v for v in ALL_VERSIONS if "0.4.0" not in v],
-}
-
-
-@pytest.fixture(scope="session", autouse=True)
-def from_tests_dir():
- # Makes default project correct.
- here = Path(__file__).parent
- orig = Path.cwd()
- if orig != here:
- os.chdir(f"{here}")
-
- yield
-
- if Path.cwd() != orig:
- os.chdir(f"{orig}")
-
-
-@pytest.fixture(scope="session", autouse=True)
-def config():
- with ape.config.isolate_data_folder():
- yield ape.config
-
-
-def contract_test_cases(passing: bool) -> list[str]:
- """
- Returns test-case names for outputting nicely with pytest.
- """
- suffix = "passing_contracts" if passing else "failing_contracts"
- return [p.name for p in (BASE_CONTRACTS_PATH / suffix).glob("*.vy") if p.is_file()]
-
-
-PASSING_CONTRACT_NAMES = contract_test_cases(True)
-FAILING_CONTRACT_NAMES = contract_test_cases(False)
-TEMPLATES = [p.stem for p in TEMPLATES_PATH.glob("*.template") if p.is_file()]
-
-
-# Needed for integration testing
-pytest_plugins = ["pytester"]
-
-
-@contextmanager
-def _tmp_vvm_path(monkeypatch):
- with create_tempdir() as path:
- monkeypatch.setenv(
- vvm.install.VVM_BINARY_PATH_VARIABLE,
- f"{path}",
- )
- yield path
-
-
-@pytest.fixture(
- scope="session",
- autouse=os.environ.get("APE_VYPER_USE_SYSTEM_VYPER") is None,
-)
-def setup_session_vvm_path(request):
- """
- Creates a new, temporary installation path for vvm when the test suite is
- run.
-
- This ensures the Vyper installations do not conflict with the user's
- installed versions and that the installations from the tests are cleaned up
- after the suite is finished.
- """
- from _pytest.monkeypatch import MonkeyPatch
-
- patch = MonkeyPatch()
- request.addfinalizer(patch.undo)
-
- with _tmp_vvm_path(patch) as path:
- yield path
-
-
-@pytest.fixture(scope="session", autouse=True)
-def generate_contracts():
- """
- Generate contracts from templates. This is used in
- multi-version testing.
- """
- for file in TEMPLATES_PATH.iterdir():
- if not file.is_file() or file.suffix != ".template":
- continue
-
- versions = CONTRACT_VERSION_GEN_MAP.get(file.stem, CONTRACT_VERSION_GEN_MAP[""])
- for version in versions:
- new_file = PASSING_BASE / f"{file.stem}_{version.replace('.', '')}.vy"
- new_file.unlink(missing_ok=True)
- new_file.write_text(
- file.read_text(encoding="utf8").replace("{{VYPER_VERSION}}", version)
- )
-
-
-@pytest.fixture
-def temp_vvm_path(monkeypatch):
- """
- Creates a new, temporary installation path for vvm for a given test.
- """
- with _tmp_vvm_path(monkeypatch) as path:
- yield path
-
-
-@pytest.fixture
-def compiler_manager():
- return ape.compilers
-
-
-@pytest.fixture
-def compiler(compiler_manager):
- return compiler_manager.vyper
-
-
-@pytest.fixture(scope="session", autouse=True)
-def project(config):
- project_source_dir = Path(__file__).parent
-
- # Delete build / .cache that may exist pre-copy
- cache = project_source_dir / ".build"
- shutil.rmtree(cache, ignore_errors=True)
-
- root_project = ape.Project(project_source_dir)
- with root_project.isolate_in_tempdir() as tmp_project:
- yield tmp_project
-
-
-@pytest.fixture
-def geth_provider():
- if not ape.networks.active_provider or ape.networks.provider.name != "node":
- with ape.networks.ethereum.local.use_provider(
- "node", provider_settings={"uri": "http://127.0.0.1:5550"}
- ) as provider:
- yield provider
- else:
- yield ape.networks.provider
-
-
-@pytest.fixture
-def projects_path():
- return Path(__file__).parent / "projects"
-
-
-@pytest.fixture
-def account():
- return ape.accounts.test_accounts[0]
-
-
-@pytest.fixture(params=("037", "039", "0310"))
-def traceback_contract(request, account, project, geth_provider):
- return _get_tb_contract(request.param, project, account)
-
-
-@pytest.fixture
-def traceback_contract_037(account, project, geth_provider):
- return _get_tb_contract("037", project, account)
-
-
-@pytest.fixture
-def traceback_contract_039(account, project, geth_provider):
- return _get_tb_contract("039", project, account)
-
-
-@pytest.fixture
-def all_versions():
- return ALL_VERSIONS
-
-
-@pytest.fixture
-def cli_runner():
- return CliRunner()
-
-
-def _get_tb_contract(version: str, project, account):
- project.load_contracts()
-
- registry_type = project.get_contract(f"registry_{version}")
- assert isinstance(registry_type, ContractContainer), "Setup failed - couldn't get container"
- registry = account.deploy(registry_type)
- contract = project.get_contract(f"traceback_contract_{version}")
- assert isinstance(contract, ContractContainer), "Setup failed - couldn't get container"
- return account.deploy(contract, registry)
diff --git a/tests/contracts/failing_contracts/contract_undeclared_variable.vy b/tests/contracts/failing_contracts/contract_undeclared_variable.vy
deleted file mode 100644
index 051f7ae0..00000000
--- a/tests/contracts/failing_contracts/contract_undeclared_variable.vy
+++ /dev/null
@@ -1,6 +0,0 @@
-# @version 0.2.16
-
-@external
-def foo1() -> bool:
- hello = world
- return True
diff --git a/tests/contracts/failing_contracts/contract_unknown_pragma.vy b/tests/contracts/failing_contracts/contract_unknown_pragma.vy
deleted file mode 100644
index 80c85cf5..00000000
--- a/tests/contracts/failing_contracts/contract_unknown_pragma.vy
+++ /dev/null
@@ -1,5 +0,0 @@
-# @version 14021.2222.8
-
-@external
-def foo1() -> bool:
- return True
diff --git a/tests/contracts/passing_contracts/DirectoryWithExtension.vy/README.md b/tests/contracts/passing_contracts/DirectoryWithExtension.vy/README.md
deleted file mode 100644
index 114f45ef..00000000
--- a/tests/contracts/passing_contracts/DirectoryWithExtension.vy/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Directory with Misleading Extension Test
-
-The existence of this directory is to test things still work when a directory with `.vy` in its name is present.
diff --git a/tests/contracts/passing_contracts/contract_no_pragma.vy b/tests/contracts/passing_contracts/contract_no_pragma.vy
deleted file mode 100644
index 1ed39dcb..00000000
--- a/tests/contracts/passing_contracts/contract_no_pragma.vy
+++ /dev/null
@@ -1,3 +0,0 @@
-@external
-def foo1() -> bool:
- return True
diff --git a/tests/contracts/passing_contracts/contract_with_dev_messages.vy b/tests/contracts/passing_contracts/contract_with_dev_messages.vy
deleted file mode 100644
index 9655de45..00000000
--- a/tests/contracts/passing_contracts/contract_with_dev_messages.vy
+++ /dev/null
@@ -1,23 +0,0 @@
-# @version 0.3.10
-
-# Test dev messages in various code placements
-@external
-def foo() -> bool:
- return True # dev: foo
-
-
-# dev: bar
-@external
-def bar() -> bool:
- return True
-
-
-@external
-def baz() -> bool: # dev: baz
- return True
-
-# Test non-ascii character matching
-# dev: 你好,猿
-
-# Test that empty dev comments are ignored
-# dev:
diff --git a/tests/contracts/passing_contracts/empty.vy b/tests/contracts/passing_contracts/empty.vy
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/contracts/passing_contracts/erc20.vy b/tests/contracts/passing_contracts/erc20.vy
deleted file mode 100644
index 3d9a208b..00000000
--- a/tests/contracts/passing_contracts/erc20.vy
+++ /dev/null
@@ -1,153 +0,0 @@
-# @version ^0.3.8
-# @dev Implementation of ERC-20 token standard.
-# @author Takayuki Jimba (@yudetamago)
-# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
-
-from vyper.interfaces import ERC20
-from vyper.interfaces import ERC20Detailed
-
-implements: ERC20
-implements: ERC20Detailed
-
-event Transfer:
- sender: indexed(address)
- receiver: indexed(address)
- value: uint256
-
-event Approval:
- owner: indexed(address)
- spender: indexed(address)
- value: uint256
-
-name: public(String[32])
-symbol: public(String[32])
-decimals: public(uint8)
-
-# NOTE: By declaring `balanceOf` as public, vyper automatically generates a 'balanceOf()' getter
-# method to allow access to account balances.
-# The _KeyType will become a required parameter for the getter and it will return _ValueType.
-# See: https://vyper.readthedocs.io/en/v0.1.0-beta.8/types.html?highlight=getter#mappings
-balanceOf: public(HashMap[address, uint256])
-# By declaring `allowance` as public, vyper automatically generates the `allowance()` getter
-allowance: public(HashMap[address, HashMap[address, uint256]])
-# By declaring `totalSupply` as public, we automatically create the `totalSupply()` getter
-totalSupply: public(uint256)
-minter: address
-
-
-@external
-def __init__(_name: String[32], _symbol: String[32], _decimals: uint8, _supply: uint256):
- init_supply: uint256 = _supply * 10 ** convert(_decimals, uint256)
- self.name = _name
- self.symbol = _symbol
- self.decimals = _decimals
- self.balanceOf[msg.sender] = init_supply
- self.totalSupply = init_supply
- self.minter = msg.sender
- log Transfer(ZERO_ADDRESS, msg.sender, init_supply)
-
-
-
-@external
-def transfer(_to : address, _value : uint256) -> bool:
- """
- @dev Transfer token for a specified address
- @param _to The address to transfer to.
- @param _value The amount to be transferred.
- """
- # NOTE: vyper does not allow underflows
- # so the following subtraction would revert on insufficient balance
- self.balanceOf[msg.sender] -= _value
- self.balanceOf[_to] += _value
- log Transfer(msg.sender, _to, _value)
- return True
-
-
-@external
-def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
- """
- @dev Transfer tokens from one address to another.
- @param _from address The address which you want to send tokens from
- @param _to address The address which you want to transfer to
- @param _value uint256 the amount of tokens to be transferred
- """
- # NOTE: vyper does not allow underflows
- # so the following subtraction would revert on insufficient balance
- self.balanceOf[_from] -= _value
- self.balanceOf[_to] += _value
- # NOTE: vyper does not allow underflows
- # so the following subtraction would revert on insufficient allowance
- self.allowance[_from][msg.sender] -= _value
- log Transfer(_from, _to, _value)
- return True
-
-
-@external
-def approve(_spender : address, _value : uint256) -> bool:
- """
- @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
- Beware that changing an allowance with this method brings the risk that someone may use both the old
- and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
- race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
- https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
- @param _spender The address which will spend the funds.
- @param _value The amount of tokens to be spent.
- """
- self.allowance[msg.sender][_spender] = _value
- log Approval(msg.sender, _spender, _value)
- return True
-
-
-@external
-def mint(_to: address, _value: uint256):
- """
- @dev Mint an amount of the token and assigns it to an account.
- This encapsulates the modification of balances such that the
- proper events are emitted.
- @param _to The account that will receive the created tokens.
- @param _value The amount that will be created.
- """
- assert msg.sender == self.minter
- assert _to != ZERO_ADDRESS
- self.totalSupply += _value
- self.balanceOf[_to] += _value
- log Transfer(ZERO_ADDRESS, _to, _value)
-
-
-@internal
-def _burn(_to: address, _value: uint256):
- """
- @dev Internal function that burns an amount of the token of a given
- account.
- @param _to The account whose tokens will be burned.
- @param _value The amount that will be burned.
- """
- assert _to != ZERO_ADDRESS
- self.totalSupply -= _value
- self.balanceOf[_to] -= _value
- log Transfer(_to, ZERO_ADDRESS, _value)
-
-
-@external
-def burn(_value: uint256):
- """
- @dev Burn an amount of the token of msg.sender.
- @param _value The amount that will be burned.
- """
- self._burn(msg.sender, _value)
-
-
-@external
-def burnFrom(_to: address, _value: uint256):
- """
- @dev Burn an amount of the token from a given account.
- @param _to The account whose tokens will be burned.
- @param _value The amount that will be burned.
- """
- self.allowance[_to][msg.sender] -= _value
- self._burn(_to, _value)
-
-
-# TODO:
-# TransferAndCall
-# And all ERC-677 functions
diff --git a/tests/contracts/passing_contracts/evm_pragma.vy b/tests/contracts/passing_contracts/evm_pragma.vy
deleted file mode 100644
index ae1bfd63..00000000
--- a/tests/contracts/passing_contracts/evm_pragma.vy
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma version 0.3.10
-#pragma evm-version paris
-
-x: uint256
-
-@external
-def __init__():
- self.x = 0
diff --git a/tests/contracts/passing_contracts/flatten_me.vy b/tests/contracts/passing_contracts/flatten_me.vy
deleted file mode 100644
index ccf0f377..00000000
--- a/tests/contracts/passing_contracts/flatten_me.vy
+++ /dev/null
@@ -1,34 +0,0 @@
-# pragma version 0.3.10
-
-from vyper.interfaces import ERC20
-
-from .interfaces import IFace2 as IFaceTwo
-from .interfaces import IFace as IFace
-import exampledependency.Dependency as Dep
-
-
-@external
-@view
-def read_contract(some_address: address) -> uint256:
- myContract: IFace = IFace(some_address)
- return myContract.read_stuff()
-
-
-@external
-@view
-def read_another_contract(some_address: address) -> uint256:
- two: IFaceTwo = IFaceTwo(some_address)
- return two.read_stuff_3()
-
-
-@external
-@view
-def read_from_dep(some_address: address) -> uint256:
- dep: Dep = Dep(some_address)
- return dep.read_stuff_2()
-
-
-@external
-def send_me(token_address: address, amount: uint256) -> bool:
- token: ERC20 = ERC20(token_address)
- return token.transferFrom(msg.sender, self, amount, default_return_value=True)
diff --git a/tests/contracts/passing_contracts/interfaces/IFace.vy b/tests/contracts/passing_contracts/interfaces/IFace.vy
deleted file mode 100644
index c5044b3a..00000000
--- a/tests/contracts/passing_contracts/interfaces/IFace.vy
+++ /dev/null
@@ -1,4 +0,0 @@
-@view
-@external
-def read_stuff() -> uint256:
- pass
diff --git a/tests/contracts/passing_contracts/interfaces/IFace2.vy b/tests/contracts/passing_contracts/interfaces/IFace2.vy
deleted file mode 100644
index 4912ff58..00000000
--- a/tests/contracts/passing_contracts/interfaces/IFace2.vy
+++ /dev/null
@@ -1,4 +0,0 @@
-@view
-@external
-def read_stuff_3() -> uint256:
- pass
diff --git a/tests/contracts/passing_contracts/interfaces/IFaceZeroFour.vyi b/tests/contracts/passing_contracts/interfaces/IFaceZeroFour.vyi
deleted file mode 100644
index cb314c87..00000000
--- a/tests/contracts/passing_contracts/interfaces/IFaceZeroFour.vyi
+++ /dev/null
@@ -1,6 +0,0 @@
-# pragma version ~=0.4.0
-
-@external
-@view
-def implementThisPlease(role: bytes32) -> bool:
- ...
diff --git a/tests/contracts/passing_contracts/interfaces/IRegistry.vy b/tests/contracts/passing_contracts/interfaces/IRegistry.vy
deleted file mode 100644
index 949d02ba..00000000
--- a/tests/contracts/passing_contracts/interfaces/IRegistry.vy
+++ /dev/null
@@ -1,7 +0,0 @@
-@external
-def register(addr: address):
- pass
-
-@external
-def register_f(addr: address):
- pass
diff --git a/tests/contracts/passing_contracts/interfaces/ISubReverts.vy b/tests/contracts/passing_contracts/interfaces/ISubReverts.vy
deleted file mode 100644
index 01f5a3e8..00000000
--- a/tests/contracts/passing_contracts/interfaces/ISubReverts.vy
+++ /dev/null
@@ -1,3 +0,0 @@
-@external
-def revertStrings(a: uint256) -> bool:
- pass
diff --git a/tests/contracts/passing_contracts/interfaces/nested/IFaceNested.vy b/tests/contracts/passing_contracts/interfaces/nested/IFaceNested.vy
deleted file mode 100644
index daea8ea9..00000000
--- a/tests/contracts/passing_contracts/interfaces/nested/IFaceNested.vy
+++ /dev/null
@@ -1,4 +0,0 @@
-@view
-@external
-def read_stuff_nested() -> uint256:
- pass
diff --git a/tests/contracts/passing_contracts/non_payable_default.vy b/tests/contracts/passing_contracts/non_payable_default.vy
deleted file mode 100644
index 988d0252..00000000
--- a/tests/contracts/passing_contracts/non_payable_default.vy
+++ /dev/null
@@ -1,8 +0,0 @@
-# @version 0.3.7
-
-event NotPayment:
- sender: indexed(address)
-
-@external
-def __default__():
- log NotPayment(msg.sender)
diff --git a/tests/contracts/passing_contracts/older_version.vy b/tests/contracts/passing_contracts/older_version.vy
deleted file mode 100644
index 9a9b108a..00000000
--- a/tests/contracts/passing_contracts/older_version.vy
+++ /dev/null
@@ -1,5 +0,0 @@
-# @version 0.2.16
-
-@external
-def foo1() -> bool:
- return True
diff --git a/tests/contracts/passing_contracts/optimize_codesize.vy b/tests/contracts/passing_contracts/optimize_codesize.vy
deleted file mode 100644
index 754f0ff0..00000000
--- a/tests/contracts/passing_contracts/optimize_codesize.vy
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma version 0.3.10
-#pragma optimize codesize
-
-x: uint256
-
-@external
-def __init__():
- self.x = 0
diff --git a/tests/contracts/passing_contracts/payable_default.vy b/tests/contracts/passing_contracts/payable_default.vy
deleted file mode 100644
index 93b4cd58..00000000
--- a/tests/contracts/passing_contracts/payable_default.vy
+++ /dev/null
@@ -1,10 +0,0 @@
-# @version 0.3.7
-
-event Payment:
- amount: uint256
- sender: indexed(address)
-
-@external
-@payable
-def __default__():
- log Payment(msg.value, msg.sender)
diff --git a/tests/contracts/passing_contracts/pragma_with_space.vy b/tests/contracts/passing_contracts/pragma_with_space.vy
deleted file mode 100644
index 7b69ecf8..00000000
--- a/tests/contracts/passing_contracts/pragma_with_space.vy
+++ /dev/null
@@ -1,7 +0,0 @@
-# pragma version 0.3.10
-
-x: uint256
-
-@external
-def __init__():
- self.x = 0
diff --git a/tests/contracts/passing_contracts/subdir/zero_four_in_subdir.vy b/tests/contracts/passing_contracts/subdir/zero_four_in_subdir.vy
deleted file mode 100644
index b3091c95..00000000
--- a/tests/contracts/passing_contracts/subdir/zero_four_in_subdir.vy
+++ /dev/null
@@ -1,6 +0,0 @@
-# Show we can import from the root of the project w/o needing relative imports
-from contracts.passing_contracts import zero_four_module as zero_four_module
-
-@external
-def callModuleFunctionFromSubdir(role: bytes32) -> bool:
- return zero_four_module.moduleMethod()
diff --git a/tests/contracts/passing_contracts/use_iface.vy b/tests/contracts/passing_contracts/use_iface.vy
deleted file mode 100644
index b29c6fff..00000000
--- a/tests/contracts/passing_contracts/use_iface.vy
+++ /dev/null
@@ -1,25 +0,0 @@
-# @version ^0.3.3
-
-# Import a local interface.
-implements: IFaceNested
-from .interfaces import IFace as IFace
-
-# Import from input JSON (ape-config.yaml).
-import exampledependency.Dependency as Dep
-
-from .interfaces import IFace2 as IFace2
-
-# Also use IFaceNested to show we can use nested interfaces.
-from contracts.passing_contracts.interfaces.nested import IFaceNested as IFaceNested
-
-
-@external
-@view
-def read_contract(some_address: address) -> uint256:
- myContract: IFace = IFace(some_address)
- return myContract.read_stuff()
-
-@view
-@external
-def read_stuff_nested() -> uint256:
- return 1
diff --git a/tests/contracts/passing_contracts/use_iface2.vy b/tests/contracts/passing_contracts/use_iface2.vy
deleted file mode 100644
index 4b888ace..00000000
--- a/tests/contracts/passing_contracts/use_iface2.vy
+++ /dev/null
@@ -1,10 +0,0 @@
-# @version ^0.3.3
-
-from .interfaces import IFace as IFace
-
-
-@external
-@view
-def read_contract(some_address: address) -> uint256:
- myContract: IFace = IFace(some_address)
- return myContract.read_stuff()
diff --git a/tests/contracts/passing_contracts/zero_four.vy b/tests/contracts/passing_contracts/zero_four.vy
deleted file mode 100644
index b8931bae..00000000
--- a/tests/contracts/passing_contracts/zero_four.vy
+++ /dev/null
@@ -1,31 +0,0 @@
-# pragma version ~=0.4.0
-
-from .interfaces import IFaceZeroFour as IFaceZeroFour
-implements: IFaceZeroFour
-
-from . import zero_four_module as zero_four_module
-
-from snekmate.auth import ownable
-
-# Also show we can import from ethereum namespace.
-# (new in Vyper 0.4).
-from ethereum.ercs import IERC20
-
-# `zero_four_module.vy` also imports this next line.
-# We are testing that the flattener can handle that.
-from . import zero_four_module_2 as zero_four_module_2
-
-@external
-@view
-def implementThisPlease(role: bytes32) -> bool:
- return True
-
-
-@external
-def callModuleFunction(role: bytes32) -> bool:
- return zero_four_module.moduleMethod()
-
-
-@external
-def callModule2Function(role: bytes32) -> bool:
- return zero_four_module_2.moduleMethod2()
diff --git a/tests/contracts/passing_contracts/zero_four_module.vy b/tests/contracts/passing_contracts/zero_four_module.vy
deleted file mode 100644
index 025a3d8b..00000000
--- a/tests/contracts/passing_contracts/zero_four_module.vy
+++ /dev/null
@@ -1,14 +0,0 @@
-# pragma version ~=0.4.0
-
-# This source is also imported from `zero_four.py` to test
-# multiple imports across sources during flattening.
-from . import zero_four_module_2 as zero_four_module_2
-
-@internal
-def moduleMethod() -> bool:
- return True
-
-
-@external
-def callModule2FunctionFromAnotherSource(role: bytes32) -> bool:
- return zero_four_module_2.moduleMethod2()
diff --git a/tests/contracts/passing_contracts/zero_four_module_2.vy b/tests/contracts/passing_contracts/zero_four_module_2.vy
deleted file mode 100644
index 44fb0fca..00000000
--- a/tests/contracts/passing_contracts/zero_four_module_2.vy
+++ /dev/null
@@ -1,9 +0,0 @@
-# pragma version ~=0.4.0
-
-# Showing importing interface from module.
-interface Ballot:
- def delegated(addr: address) -> bool: view
-
-@internal
-def moduleMethod2() -> bool:
- return True
diff --git a/tests/contracts/templates/contract.template b/tests/contracts/templates/contract.template
deleted file mode 100644
index 59ec9f05..00000000
--- a/tests/contracts/templates/contract.template
+++ /dev/null
@@ -1,120 +0,0 @@
-# @version {{VYPER_VERSION}}
-
-from vyper.interfaces import ERC20
-
-interface ERC20Ext:
- def decimals() -> uint8: view
-
-# Public storage (PCMap testing)
-dynArray: public(DynArray[uint256, 1024])
-token: public(address)
-start_token: public(immutable(address))
-
-# Constants (PCMap testing)
-MASK: constant(uint256) = 2**96 - 1
-FIVE: constant(uint256) = 5
-POS_FIVE: constant(int128) = 5
-FIVES: constant(uint256) = 555
-
-# Internal storage (PCMap testing)
-array_test: uint256[FIVE]
-
-
-# NOTE: Keep event as test for proving it doesn't fudge up PCMap.
-event Swap:
- account: indexed(address)
- receiver: indexed(address)
- asset_in: uint256
- asset_out: uint256
- amount_in: uint256
- amount_out: uint256
-
-
-# Testing empty events in how it affects PCMap generation.
-event Hollow: pass
-
-
-@external
-def __init__(_token: address):
- """
- @notice Constructor
- @param _token Include docs to prove it doesn't fudge with PCMap.
- """
- self.token = _token
- start_token = _token
-
- # Part of testing how internal arrays behave in PCMap locations.
- for asset in range(FIVE):
- self.array_test[asset] = asset * 7
-
-
-# NOTE: `@nonreentrant` just to test that it doesn't affect PCMap generation.
-@external
-@nonreentrant('lock')
-def setNumber(num: uint256) -> uint256:
- # NOTE: This `and` statement `assert` purposely tests something
- # we had an issue where this causes the PCMap calculation to get thrown off.
- assert num != FIVE and num != FIVES # dev: 7 8 9
-
- # Show that PCMap can handle log statements.
- log Swap(msg.sender, msg.sender, 1, 2, 3, 4)
-
- # Test that we can access state variables and PCMap still works.
- ERC20Ext(self.token).decimals()
-
- # WARN: This part is really important.
- # Specifically, the call to the immutable member start_token tests something.
- # This is because immutable variables are code offsets and not storage slots.
- ERC20Ext(start_token).decimals()
-
- res: uint256 = self.helper(num) * self.array_test[1]
- log Hollow()
- return res
-
-
-@external
-def num_add(i: int128) -> int128:
- return (2**127-1) + i
-
-
-@external
-def neg_num_add(i: int128) -> int128:
- return i - (2**127-1)
-
-
-@external
-def div_zero(i: int128) -> int128:
- return 4 / i
-
-
-@external
-def mod_zero(i: int128) -> int128:
- return 4 % i
-
-
-@external
-def gimme(idx: uint256) -> uint256:
- return self.dynArray[idx]
-
-
-@view
-@external
-def a_view_method(a: address) -> (uint256, uint256, uint256):
- assert a != msg.sender # dev: msg sender check
- assert a != start_token # dev: immut. token check
- assert a != self.token # dev: mut. token check
- return (FIVE, FIVES, MASK)
-
-
-@pure
-@internal
-def helper(a: uint256) -> uint256:
- assert a + 1 != FIVES or a - 1 != FIVES
- res: uint256 = unsafe_mul(a & MASK, FIVE) | FIVE | shift(a, POS_FIVE)
- if res * FIVE < FIVES:
- return res
-
- # NOTE: Empty raise statement in Vyper are different than Python.
- # This should be the same as an assert with no message.
- # This is intentionally here for testing PCMap generation.
- raise # dev: empty raise stmts
diff --git a/tests/contracts/templates/registry.template b/tests/contracts/templates/registry.template
deleted file mode 100644
index e95f920d..00000000
--- a/tests/contracts/templates/registry.template
+++ /dev/null
@@ -1,13 +0,0 @@
-# @version {{VYPER_VERSION}}
-
-addr: public(address)
-
-@external
-def register(addr: address):
- self.addr = addr
-
-
-@external
-def register_f(addr: address):
- assert self.addr != addr, "doubling."
- self.addr = addr
diff --git a/tests/contracts/templates/reverts.template b/tests/contracts/templates/reverts.template
deleted file mode 100644
index b40ff6f6..00000000
--- a/tests/contracts/templates/reverts.template
+++ /dev/null
@@ -1,64 +0,0 @@
-# @version {{VYPER_VERSION}}
-
-from .interfaces import ISubReverts as ISubReverts
-
-sub_reverts: public(ISubReverts)
-MAX_NUM: constant(uint256) = 32
-
-@external
-def __init__(sub_reverts: ISubReverts):
- self.sub_reverts = sub_reverts
-
-@external
-@nonreentrant('lock')
-def revertStrings(a: uint256) -> bool:
- assert a != 0, "zero"
- assert a != 1 # dev: one
- assert a != 2, "two" # dev: error
- assert a != 3 # error
-
- # Put random stuff in middle of function for testing purposes.
- i2: uint256 = 0
- for i in [1, 2, 3, 4, 5]:
- i2 = self.noop(i)
- if a != i2:
- continue
-
- assert a != 4 # dev: such modifiable, wow
- x: uint256 = 125348 / a
- assert x < 21 # dev: foobarbaz
- if a != 31337:
- return True
- raise "awesome show" # dev: great job
-
-@external
-def subRevertStrings(a: uint256) -> bool:
- return self.sub_reverts.revertStrings(a)
-
-@external
-def revertStrings2(a: uint256) -> bool:
- assert a != 0, "zero"
- assert a != 1 # dev: one
- assert a != 2, "two" # dev: error
- assert a != 3 # error
- assert a != 4 # dev: such modifiable, wow
-
- for i in range(MAX_NUM):
- assert i != a # dev: loop test
-
- if a != 31337:
- return True
- raise "awesome show" # dev: great job
-
-@pure
-@external
-def revertStringsCall(a: uint256) -> bool:
- assert a != 0
- assert a != 1, "TEST" # dev: one
- return True
-
-
-@pure
-@internal
-def noop(a: uint256) -> uint256:
- return a
diff --git a/tests/contracts/templates/sub_reverts.template b/tests/contracts/templates/sub_reverts.template
deleted file mode 100644
index 5d9c86a8..00000000
--- a/tests/contracts/templates/sub_reverts.template
+++ /dev/null
@@ -1,6 +0,0 @@
-# @version {{VYPER_VERSION}}
-
-@external
-def revertStrings(a: uint256) -> bool:
- assert a != 0 # dev: sub-zero
- return True
diff --git a/tests/contracts/templates/traceback_contract.template b/tests/contracts/templates/traceback_contract.template
deleted file mode 100644
index 807721ec..00000000
--- a/tests/contracts/templates/traceback_contract.template
+++ /dev/null
@@ -1,64 +0,0 @@
-# @version {{VYPER_VERSION}}
-
-from .interfaces import IRegistry as IRegistry
-
-_balance: public(uint256)
-registry: public(IRegistry)
-
-
-@external
-def __init__(registry: IRegistry):
- self.registry = registry
-
-
-@external
-def addBalance(
- num: uint256 = 123,
- num2: uint256 = 321,
-) -> uint256:
- assert num != self._balance
- assert num != num2
- self.registry.register(msg.sender)
- self._balance = self._balance + self.addInterest(num)
-
- # Run some loops.
- for i in [1, 2, 3, 4, 5]:
- if i == num:
- break
-
- # Comments in the middle (is a test)
-
- for i in [1, 2, 3, 4, 5]:
- if i != num:
- continue
-
- return self._balance
-
-
-@external
-def addBalance_f(
- num: uint256
-) -> uint256:
- assert num != self._balance
- self.registry.register(msg.sender)
- self._balance = self._balance + self.addInterest(num)
-
- # Run some loops.
- for i in [1, 2, 3, 4, 5]:
- if i == num:
- break
-
- # Fail in the middle (is test)
- # Fails because was already set above.
- self.registry.register_f(msg.sender)
-
- for i in [1, 2, 3, 4, 5]:
- if i != num:
- continue
-
- return self._balance
-
-
-@internal
-def addInterest(num: uint256) -> uint256:
- return 123 + num
diff --git a/tests/projects/coverage_project/README.md b/tests/projects/coverage_project/README.md
deleted file mode 100644
index df2b03e9..00000000
--- a/tests/projects/coverage_project/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# ape-vyper Coverage Project
-
-This test project exists to help test coverage related features in the Ape framework.
-The project is used in the `tests/test_coverage.py` test module.
diff --git a/tests/projects/coverage_project/ape-config.yaml b/tests/projects/coverage_project/ape-config.yaml
deleted file mode 100644
index 679a1df8..00000000
--- a/tests/projects/coverage_project/ape-config.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-ethereum:
- local:
- default_provider: node
-
-node:
- ethereum:
- local:
- # Connect to node running from other tests.
- uri: "http://127.0.0.1:5550"
-
-test:
- coverage:
- exclude:
- # Exclude any method starting with DEBUG_
- - method_name: "DEBUG_*"
- # Exclude the entire contract source `exclude_whole_contract.vy`.
- - contract_name: "exclude_whole_*"
- # Exclude a single method from `exclude_part_of_contract.vy`.
- - contract_name: "exclude_part_*"
- method_name: "exclude_*"
-
- reports:
- terminal:
- verbose: True
- html: True
- xml: True
diff --git a/tests/projects/coverage_project/contracts/coverage_test.vy b/tests/projects/coverage_project/contracts/coverage_test.vy
deleted file mode 100644
index 220c5211..00000000
--- a/tests/projects/coverage_project/contracts/coverage_test.vy
+++ /dev/null
@@ -1,24 +0,0 @@
-# @version 0.3.7
-
-_number: public(uint256)
-_immutable_number: public(immutable(uint256))
-
-@external
-def __init__(_number: uint256):
- _immutable_number = _number
-
-
-@external
-def foo_method(a: uint256 = 3, b: uint256 = 1) -> bool:
- assert a != 0 # dev: sub-zero
- self._number = a + b
- return True
-
-@view
-@external
-def view_method() -> bool:
- return True
-
-@external
-def DEBUG_ignore_me() -> bool:
- return True
diff --git a/tests/projects/coverage_project/contracts/exclude_part_of_contract.vy b/tests/projects/coverage_project/contracts/exclude_part_of_contract.vy
deleted file mode 100644
index 8e778a3d..00000000
--- a/tests/projects/coverage_project/contracts/exclude_part_of_contract.vy
+++ /dev/null
@@ -1,9 +0,0 @@
-# @version 0.3.7
-
-@external
-def exclude_me() -> bool:
- return True
-
-@external
-def include_me() -> bool:
- return True
diff --git a/tests/projects/coverage_project/contracts/exclude_whole_contract.vy b/tests/projects/coverage_project/contracts/exclude_whole_contract.vy
deleted file mode 100644
index cdce80c9..00000000
--- a/tests/projects/coverage_project/contracts/exclude_whole_contract.vy
+++ /dev/null
@@ -1,5 +0,0 @@
-# @version 0.3.7
-
-@external
-def exclude_me() -> bool:
- return True
diff --git a/tests/projects/coverage_project/tests/conftest.py b/tests/projects/coverage_project/tests/conftest.py
deleted file mode 100644
index 784072b4..00000000
--- a/tests/projects/coverage_project/tests/conftest.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import pytest
-
-
-@pytest.fixture
-def START_NUM():
- return 1234567
-
-
-@pytest.fixture
-def account(accounts):
- return accounts[0]
-
-
-@pytest.fixture
-def contract(account, project, START_NUM):
- return account.deploy(project.coverage_test, START_NUM)
diff --git a/tests/projects/coverage_project/tests/test_coverage.py b/tests/projects/coverage_project/tests/test_coverage.py
deleted file mode 100644
index 511eafb7..00000000
--- a/tests/projects/coverage_project/tests/test_coverage.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import ape
-
-from ape_vyper.exceptions import FallbackNotDefinedError, NonPayableError
-
-
-def test_immutable_number(contract, account, START_NUM):
- """
- Ensure that immutable members work in coverage.
- This is needed for full function coverage.
- """
- assert contract._immutable_number() == START_NUM
-
-
-def test_happy_path(contract, account, chain):
- """
- Covers some implicit statements as well two source statements.
- """
- num1 = 5
- num2 = 6
- receipt = contract.foo_method(num1, num2, sender=account)
-
- # In order for full coverage, we need to also call `_number()`.
- assert contract._number() == num1 + num2
-
- if chain.provider.supports_tracing:
- assert receipt.return_value is True
-
-
-def test_sad_path(contract, account, chain):
- """
- Covers some implicit statements as well as one source statement.
- """
- kwargs = {"dev_message": "dev: sub-zero"} if chain.provider.supports_tracing else {}
- with ape.reverts(**kwargs):
- contract.foo_method(0, 1, sender=account)
-
-
-def test_non_payable(contract, account):
- """
- Coverage (at least) the implicit statement for non-payable check.
- """
- with ape.reverts(NonPayableError):
- contract.foo_method(5, 1, sender=account, value=1)
-
-
-def test_no_default_method(contract, account):
- """
- Covers the implicit check for fallback not defined.
- """
- with ape.reverts(FallbackNotDefinedError):
- contract(sender=account)
-
-
-def test_foo_method_no_args(contract, account):
- """
- Covers the statement from the autogenerated method.
- """
- receipt = contract.foo_method(sender=account)
- assert not receipt.failed
-
-
-def test_foo_method_one_arg(contract, account):
- """
- Covers the statement from the autogenerated method.
- """
- receipt = contract.foo_method(1, sender=account)
- assert not receipt.failed
-
-
-def test_view_method(contract, account):
- """
- Prove that view methods work in coverage.
- Without this, it would not be 100%.
- """
- assert contract.view_method() is True
diff --git a/tests/projects/version_in_config/ape-config.yaml b/tests/projects/version_in_config/ape-config.yaml
deleted file mode 100644
index 5eb0b078..00000000
--- a/tests/projects/version_in_config/ape-config.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-vyper:
- version: 0.3.7
diff --git a/tests/projects/version_in_config/contracts/v_contract.vy b/tests/projects/version_in_config/contracts/v_contract.vy
deleted file mode 100644
index 38602d92..00000000
--- a/tests/projects/version_in_config/contracts/v_contract.vy
+++ /dev/null
@@ -1,5 +0,0 @@
-# @version 0.3.10
-
-@external
-def foo(a: uint256) -> bool:
- return True
diff --git a/tests/test_ape_reverts.py b/tests/test_ape_reverts.py
deleted file mode 100644
index 45fe1b21..00000000
--- a/tests/test_ape_reverts.py
+++ /dev/null
@@ -1,132 +0,0 @@
-import re
-import shutil
-
-import pytest
-from ape import chain
-from ape.pytest.contextmanagers import RevertsContextManager as reverts
-
-
-@pytest.fixture(autouse=True)
-def clear_db(geth_provider):
- yield
- # Helps prevent replacement tx errors.
- # TODO: Move this into Ape's isolation handling for geth.
- blobpool = chain.provider._process._data_dir / "geth" / "blobpool"
- shutil.rmtree(blobpool, ignore_errors=True)
-
-
-@pytest.fixture(params=("021", "022", "023", "0215", "0216", "034"))
-def older_reverts_contract(account, project, geth_provider, request):
- container = project.get_contract(f"sub_reverts_{request.param}")
- return container.deploy(sender=account)
-
-
-@pytest.fixture(params=("037", "039", "0310"))
-def reverts_contract_instance(account, project, geth_provider, request):
- sub_reverts_container = project.get_contract(f"sub_reverts_{request.param}")
- sub_reverts = sub_reverts_container.deploy(sender=account)
- contract = project.get_contract(f"reverts_{request.param}")
- return contract.deploy(sub_reverts, sender=account)
-
-
-def test_dev_revert(account, reverts_contract_instance, geth_provider):
- """
- Test matching a contract dev revert message with a supplied dev message.
- """
- with reverts(dev_message="dev: error"):
- reverts_contract_instance.revertStrings(2, sender=account)
-
- # Show a method further down in the contract also works.
- with reverts(dev_message="dev: error"):
- reverts_contract_instance.revertStrings2(2, sender=account)
-
-
-def test_dev_revert_pattern(account, reverts_contract_instance, geth_provider):
- """
- Test matching a contract dev revert message with a supplied dev message pattern.
- """
- with reverts(dev_message=re.compile(r"dev: err\w+")):
- reverts_contract_instance.revertStrings(2, sender=account)
-
- with reverts(dev_message=re.compile(r"dev: err\w+")):
- reverts_contract_instance.revertStrings2(2, sender=account)
-
-
-def test_dev_revert_from_sub_contract(account, reverts_contract_instance, geth_provider, project):
- """
- Test to ensure we can assert on dev messages from inner-contracts.
- """
- with reverts(dev_message="dev: sub-zero"):
- reverts_contract_instance.subRevertStrings(0, sender=account)
-
-
-def test_dev_revert_deep_in_method(account, reverts_contract_instance, geth_provider):
- """
- Test to ensure we can assert on a dev message that is in the middle of a
- complicated function implementation.
- """
- with reverts(dev_message="dev: foobarbaz"):
- reverts_contract_instance.revertStrings(13, sender=account)
-
- with reverts(dev_message="dev: such modifiable, wow"):
- reverts_contract_instance.revertStrings(4, sender=account)
-
- with reverts(dev_message="dev: great job"):
- reverts_contract_instance.revertStrings(31337, sender=account)
-
-
-def test_dev_revert_in_loop(account, reverts_contract_instance, geth_provider):
- with reverts(dev_message="dev: loop test"):
- reverts_contract_instance.revertStrings2(12, sender=account)
-
-
-def test_dev_revert_fails(account, reverts_contract_instance, geth_provider):
- """
- Test that ``AssertionError`` is raised if the supplied dev message and the contract dev message
- do not match.
- """
- with pytest.raises(AssertionError):
- with reverts(dev_message="dev: foo"):
- reverts_contract_instance.revertStrings(2, sender=account)
-
-
-def test_dev_revert_partial_fails(account, reverts_contract_instance, geth_provider):
- """
- Test that ``AssertionError`` is raised if the supplied dev message and the contract dev message
- do not match exactly.
- """
- with pytest.raises(AssertionError):
- with reverts(dev_message="dev: foo"):
- reverts_contract_instance.revertStrings(2, sender=account)
-
-
-def test_dev_revert_pattern_fails(account, reverts_contract_instance, geth_provider):
- """
- Test that ``AssertionError`` is raised if the contract dev message does not match the supplied
- dev revert pattern.
- """
- with pytest.raises(AssertionError):
- with reverts(dev_message=re.compile(r"dev: [^ero]+")):
- reverts_contract_instance.revertStrings(2, sender=account)
-
-
-def test_dev_revert_on_call(account, reverts_contract_instance, geth_provider):
- """
- Shows that dev strings are detectable even on pure / view methods.
- """
- with reverts(dev_message="dev: one"):
- reverts_contract_instance.revertStringsCall(1)
-
-
-def test_both_message_and_dev_str(account, reverts_contract_instance, geth_provider):
- """
- Test matching a revert message with a supplied message as well as a contract dev revert message
- with a supplied dev message.
- """
- with reverts(expected_message="two", dev_message="dev: error"):
- reverts_contract_instance.revertStrings(2, sender=account)
-
-
-def test_dev_message_older_versions(account, older_reverts_contract):
- with reverts(dev_message="dev: sub-zero"):
- older_reverts_contract.revertStrings(0, sender=account)
diff --git a/tests/test_cli.py b/tests/test_cli.py
deleted file mode 100644
index 12975b4b..00000000
--- a/tests/test_cli.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import subprocess
-
-import pytest
-from ape.utils import create_tempdir
-
-from ape_vyper._cli import cli
-
-
-@pytest.mark.parametrize(
- "contract_name,expected",
- [
- # This first one has most known edge cases
- (
- "flatten_me.vy",
- [
- "from vyper.interfaces import ERC20",
- "interface Dep:",
- "interface IFace:",
- "interface IFaceTwo:",
- ],
- ),
- ],
-)
-def test_flatten(project, contract_name, expected, cli_runner):
- path = project.contracts_folder / contract_name
- arguments = ["flatten", str(path)]
- end = ("--project", str(project.path))
- with create_tempdir() as tmpdir:
- file = tmpdir / "flatten.vy"
- arguments.extend([str(file), *end])
- result = cli_runner.invoke(cli, arguments, catch_exceptions=False)
- assert result.exit_code == 0, result.stderr_bytes
- output = file.read_text(encoding="utf8")
- for expect in expected:
- assert expect in output
-
-
-def test_compile():
- """
- Integration: Testing the CLI using an actual subprocess because
- it is the only way to test compiling the project such that it
- isn't treated as a tempdir project.
- """
- # Use a couple contracts
- cmd_ls = ("ape", "compile", "subdir", "--force")
- completed_process = subprocess.run(cmd_ls, capture_output=True)
- output = completed_process.stdout.decode(encoding="utf8")
- assert "SUCCESS" in output
- assert "zero_four_in_subdir.vy" in output
diff --git a/tests/test_compiler.py b/tests/test_compiler.py
deleted file mode 100644
index 177c3554..00000000
--- a/tests/test_compiler.py
+++ /dev/null
@@ -1,736 +0,0 @@
-import re
-from pathlib import Path
-
-import ape
-import pytest
-import vvm # type: ignore
-from ape.exceptions import CompilerError, ContractLogicError
-from ape.utils import get_full_extension
-from ethpm_types import ContractType
-from packaging.version import Version
-from vvm.exceptions import VyperError # type: ignore
-
-from ape_vyper.compiler import RuntimeErrorType
-from ape_vyper.exceptions import (
- FallbackNotDefinedError,
- IntegerOverflowError,
- InvalidCalldataOrValueError,
- NonPayableError,
- VyperCompileError,
- VyperInstallError,
-)
-
-# Currently, this is the only version specified from a pragma spec
-from .conftest import FAILING_BASE, FAILING_CONTRACT_NAMES, PASSING_CONTRACT_NAMES, TEMPLATES
-
-OLDER_VERSION_FROM_PRAGMA = Version("0.2.16")
-VERSION_37 = Version("0.3.7")
-VERSION_FROM_PRAGMA = Version("0.3.10")
-VERSION_04 = Version("0.4.0")
-
-
-@pytest.fixture
-def dev_revert_source(project):
- return project.contracts_folder / "contract_with_dev_messages.vy"
-
-
-EXPECTED_FAIL_PATTERNS = {
- "contract_undeclared_variable": re.compile(
- (
- r"\w*\.vy\s*UndeclaredDefinition:'\w*' "
- r'has not been declared\s*contract "\w*.vy"'
- # NOTE: Following bit proves we have line numbers (see all the \d's).
- r', function "\w*",.*\w*\d:\d\s*\d def.*\s*.*\d\s*\w* = \w*\s*-*\^\s*\d\s*.*'
- ),
- ),
- "contract_unknown_pragma": "",
-}
-ZERO_FOUR_CONTRACT_FLAT = """
-# pragma version ~=0.4.0
-
-
-interface IFaceZeroFour:
- def implementThisPlease(role: bytes32) -> bool: view
-
-
-# @dev Returns the address of the current owner.
-# @notice If you declare a variable as `public`,
-# Vyper automatically generates an `external`
-# getter function for the variable.
-owner: public(address)
-
-
-# @dev Emitted when the ownership is transferred
-# from `previous_owner` to `new_owner`.
-event OwnershipTransferred:
- previous_owner: indexed(address)
- new_owner: indexed(address)
-
-
-@deploy
-@payable
-def __init__():
- \"\"\"
- @dev To omit the opcodes for checking the `msg.value`
- in the creation-time EVM bytecode, the constructor
- is declared as `payable`.
- @notice The `owner` role will be assigned to
- the `msg.sender`.
- \"\"\"
- self._transfer_ownership(msg.sender)
-
-
-@external
-def transfer_ownership(new_owner: address):
- \"\"\"
- @dev Transfers the ownership of the contract
- to a new account `new_owner`.
- @notice Note that this function can only be
- called by the current `owner`. Also,
- the `new_owner` cannot be the zero address.
- @param new_owner The 20-byte address of the new owner.
- \"\"\"
- self._check_owner()
- assert new_owner != empty(address), "ownable: new owner is the zero address"
- self._transfer_ownership(new_owner)
-
-
-@external
-def renounce_ownership():
- \"\"\"
- @dev Leaves the contract without an owner.
- @notice Renouncing ownership will leave the
- contract without an owner, thereby
- removing any functionality that is
- only available to the owner.
- \"\"\"
- self._check_owner()
- self._transfer_ownership(empty(address))
-
-
-@internal
-def _check_owner():
- \"\"\"
- @dev Throws if the sender is not the owner.
- \"\"\"
- assert msg.sender == self.owner, "ownable: caller is not the owner"
-
-
-@internal
-def _transfer_ownership(new_owner: address):
- \"\"\"
- @dev Transfers the ownership of the contract
- to a new account `new_owner`.
- @notice This is an `internal` function without
- access restriction.
- @param new_owner The 20-byte address of the new owner.
- \"\"\"
- old_owner: address = self.owner
- self.owner = new_owner
- log OwnershipTransferred(old_owner, new_owner)
-
-
-# This source is also imported from `zero_four.py` to test
-# multiple imports across sources during flattening.
-
-@internal
-def moduleMethod() -> bool:
- return True
-
-
-@external
-def callModule2FunctionFromAnotherSource(role: bytes32) -> bool:
- return self.moduleMethod2()
-
-
-# Showing importing interface from module.
-interface Ballot:
- def delegated(addr: address) -> bool: view
-
-@internal
-def moduleMethod2() -> bool:
- return True
-
-
-implements: IFaceZeroFour
-
-
-# Also show we can import from ethereum namespace.
-# (new in Vyper 0.4).
-
-# `self.vy` also imports this next line.
-# We are testing that the flattener can handle that.
-
-@external
-@view
-def implementThisPlease(role: bytes32) -> bool:
- return True
-
-
-@external
-def callModuleFunction(role: bytes32) -> bool:
- return self.moduleMethod()
-
-
-@external
-def callModule2Function(role: bytes32) -> bool:
- return self.moduleMethod2()
-""".lstrip()
-
-
-def test_compile_project(project):
- actual = sorted(list(project.load_contracts().keys()))
-
- # NOTE: Ignore interfaces for this test.
- expected = sorted(
- [
- p.stem
- for p in project.contracts_folder.rglob("*.vy")
- if p.is_file() and not p.name.startswith("I")
- ]
- )
- if missing := [e for e in expected if e not in actual]:
- missing_str = ", ".join(missing)
- pytest.xfail(f"Missing the following expected sources: {missing_str}")
- if extra := [a for a in actual if a not in expected]:
- extra_str = ", ".join(extra)
- pytest.xfail(f"Received the following extra sources: {extra_str}")
-
- assert "contract_039" in actual
- assert "contract_no_pragma" in actual
- assert "older_version" in actual
-
-
-@pytest.mark.parametrize("contract_name", PASSING_CONTRACT_NAMES)
-def test_compile_individual_contracts(project, contract_name, compiler):
- path = project.contracts_folder / contract_name
- assert list(compiler.compile((path,), project=project))
-
-
-@pytest.mark.parametrize(
- "contract_name", [n for n in FAILING_CONTRACT_NAMES if n != "contract_unknown_pragma.vy"]
-)
-def test_compile_failures(contract_name, compiler):
- failing_project = ape.Project(FAILING_BASE)
- path = FAILING_BASE / contract_name
- with pytest.raises(VyperCompileError, match=EXPECTED_FAIL_PATTERNS[path.stem]) as err:
- list(compiler.compile((path,), project=failing_project))
-
- assert isinstance(err.value.base_err, VyperError)
-
-
-def test_compile_zero_four(compiler, project):
- """
- An easy way to test only Vyper 0.4 changes.
- """
- paths = (
- project.contracts_folder / "subdir" / "zero_four_in_subdir.vy",
- project.contracts_folder / "zero_four.vy",
- )
- result = [x.name for x in compiler.compile(paths, project=project)]
- assert "zero_four" in result
- assert "zero_four_in_subdir" in result
-
-
-def test_install_failure(compiler):
- failing_project = ape.Project(FAILING_BASE)
- path = FAILING_BASE / "contract_unknown_pragma.vy"
- with pytest.raises(VyperInstallError, match="No available version to install."):
- list(compiler.compile((path,), project=failing_project))
-
-
-def test_get_version_map(project, compiler, all_versions):
- vyper_files = [
- x
- for x in project.contracts_folder.iterdir()
- if x.is_file() and get_full_extension(x) == ".vy"
- ]
- actual = compiler.get_version_map(vyper_files, project=project)
- expected_versions = [Version(v) for v in all_versions]
-
- for version, sources in actual.items():
- if version in expected_versions:
- continue
-
- sources = ", ".join([p.name for p in actual[version]])
- fail_message = f"Unexpected version '{version}' with sources: {sources}"
- pytest.fail(fail_message)
-
- assert len(actual[OLDER_VERSION_FROM_PRAGMA]) >= 1
- assert len(actual[VERSION_FROM_PRAGMA]) >= 1
- assert project.contracts_folder / "older_version.vy" in actual[OLDER_VERSION_FROM_PRAGMA]
-
- expected = [
- "contract_with_dev_messages.vy",
- "erc20.vy",
- "use_iface.vy",
- "optimize_codesize.vy",
- "evm_pragma.vy",
- "use_iface2.vy",
- "pragma_with_space.vy",
- "flatten_me.vy",
- ]
-
- # Add the 0.3.10 contracts.
- for template in TEMPLATES:
- expected.append(f"{template}_0310.vy")
-
- names = [x.name for x in actual[VERSION_FROM_PRAGMA]]
- failures = []
- missing = []
- for ex in expected:
- if ex not in names:
- missing.append(ex)
-
- if missing:
- failures.append(f"Missing contracts: {','.join(missing)}")
-
- extra = []
- for ac in actual[VERSION_FROM_PRAGMA]:
- if ac.name not in expected:
- extra.append(ac.name)
-
- if extra:
- failures.append(f"Extra contracts: {', '.join(extra)}")
-
- assert not failures, "\n".join(failures)
-
- # Vyper 0.4.0 assertions.
- actual4 = {x.name for x in actual[VERSION_04]}
- expected4 = {
- "contract_no_pragma.vy",
- "empty.vy",
- "zero_four.vy",
- "zero_four_module.vy",
- "zero_four_module_2.vy",
- }
- assert actual4 == expected4
-
-
-def test_compiler_data_in_manifest(project):
- def run_test(manifest):
- assert len(manifest.compilers) >= 3, manifest.compilers
-
- all_latest_03 = [
- c for c in manifest.compilers if str(c.version) == str(VERSION_FROM_PRAGMA)
- ]
- evm_opt = [c for c in all_latest_03 if c.settings.get("evmVersion") == "paris"][0]
- gas_opt = [c for c in all_latest_03 if c.settings["optimize"] == "gas"][0]
- true_opt = [
- c
- for c in manifest.compilers
- if c.settings["optimize"] is True and "non_payable_default" in c.contractTypes
- ][0]
- codesize_opt = [
- c
- for c in all_latest_03
- if c.settings["optimize"] == "codesize" and c.settings.get("evmVersion") != "paris"
- ][0]
- vyper_028 = [
- c for c in manifest.compilers if str(c.version) == str(OLDER_VERSION_FROM_PRAGMA)
- ][0]
-
- for compiler in (vyper_028, codesize_opt):
- assert compiler.name == "vyper"
-
- assert vyper_028.settings["evmVersion"] == "berlin"
- assert codesize_opt.settings["evmVersion"] == "shanghai"
-
- # There is only one contract with evm-version pragma.
- assert evm_opt.contractTypes == ["evm_pragma"]
- assert evm_opt.settings.get("evmVersion") == "paris"
-
- assert "optimize_codesize" in codesize_opt.contractTypes
- assert "older_version" in vyper_028.contractTypes
- assert len(gas_opt.contractTypes) >= 1
- assert "non_payable_default" in true_opt.contractTypes
-
- project.update_manifest(compilers=[])
- project.load_contracts(use_cache=False)
- run_test(project.manifest)
- man = project.extract_manifest()
- run_test(man)
-
-
-def test_compile_parse_dev_messages(compiler, dev_revert_source, project):
- """
- Test parsing of dev messages in a contract. These follow the form of "#dev: ...".
-
- The compiler will output a map that maps dev messages to line numbers.
- See contract_with_dev_messages.vy for more information.
- """
- result = list(compiler.compile((dev_revert_source,), project=project))
-
- assert len(result) == 1
-
- contract = result[0]
-
- assert contract.dev_messages is not None
- assert len(contract.dev_messages) == 4
- assert contract.dev_messages[6] == "dev: foo"
- assert contract.dev_messages[9] == "dev: bar"
- assert contract.dev_messages[16] == "dev: baz"
- assert contract.dev_messages[20] == "dev: 你好,猿"
- assert 23 not in contract.dev_messages
-
-
-def test_get_imports(compiler, project):
- vyper_files = [
- x for x in project.contracts_folder.iterdir() if x.is_file() and x.suffix == ".vy"
- ]
- actual = compiler.get_imports(vyper_files, project=project)
- prefix = "contracts/passing_contracts"
- builtin_import = "vyper/interfaces/ERC20.json"
- local_import = "IFace.vy"
- local_from_import = "IFace2.vy"
- local_nested_import = "IFaceNested.vy"
- dependency_import = "Dependency.vy"
-
- # The source IDs end up as absolute paths because they are in tempdir
- # (not direct local project) and because of Vyper 0.4 reasons, we need
- # this to be the case. And we don't know the version map yet at this point.
- contract_37_key = [k for k in actual if f"{prefix}/contract_037.vy" in k][0]
- use_iface_key = [k for k in actual if f"{prefix}/use_iface.vy" in k][0]
- use_iface2_key = [k for k in actual if f"{prefix}/use_iface2.vy" in k][0]
-
- assert set(actual[contract_37_key]) == {builtin_import}
-
- actual_iface_use = actual[use_iface_key]
- for expected in (local_import, local_from_import, dependency_import, local_nested_import):
- assert any(k for k in actual_iface_use if expected in k)
-
- assert actual[use_iface2_key][0].endswith(local_import)
-
-
-@pytest.mark.parametrize("src,vers", [("contract_039", "0.3.9"), ("contract_037", "0.3.7")])
-def test_pc_map(compiler, project, src, vers):
- """
- Ensure we de-compress the source map correctly by comparing to the results
- from `compile_src()` which includes the uncompressed source map data.
- """
-
- path = project.sources.lookup(src)
- result = list(compiler.compile((path,), project=project))[0]
- actual = result.pcmap.root
- code = path.read_text(encoding="utf8")
- vvm.install_vyper(vers)
- cfg = compiler.get_config(project=project)
- evm_version = cfg.evm_version
- compile_result = vvm.compile_source(code, vyper_version=vers, evm_version=evm_version)
- std_result = compile_result[""]
- src_map = std_result["source_map"]
- lines = code.splitlines()
-
- # Use the old-fashioned way of gathering PCMap to ensure our creative way works
- expected = {pc: {"location": ln} for pc, ln in src_map["pc_pos_map"].items()}
- missing_pcs = []
- empty_locs = []
- wrong_locs = []
- for expected_pc, item_dict in expected.items():
- expected_loc = item_dict["location"]
-
- # Collect matching locations.
- matching_locs = []
- for mpc, loc in actual.items():
- if loc["location"] == expected_loc:
- matching_locs.append(mpc)
-
- if expected_pc not in actual:
- missing_pcs.append((expected_pc, expected_loc, matching_locs))
- continue
-
- if actual[expected_pc]["location"] is None:
- empty_locs.append((expected_pc, expected_loc, matching_locs))
- continue
-
- if actual[expected_pc]["location"] != expected_loc:
- wrong_locs.append((expected_pc, expected_loc, matching_locs))
-
- limit = 10 # Only show first ten failures of each category.
-
- def make_failure(title, ls):
- fail_format = "PC={pc}, Expected={ex} (actual matches={match})"
- suffix = ", ".join([fail_format.format(pc=m, ex=e, match=mat) for m, e, mat in ls[:limit]])
- return f"{title}: {suffix}"
-
- failures = []
- if len(missing_pcs) != 0:
- failures.append((missing_pcs[0][0], make_failure("Missing PCs", missing_pcs)))
- if len(empty_locs) != 0:
- failures.append((empty_locs[0][0], make_failure("Empty locations", empty_locs)))
- if len(wrong_locs) != 0:
- failures.append((wrong_locs[0][0], make_failure("Wrong locations", wrong_locs)))
-
- # Show first failures to occur first.
- failures.sort(key=lambda x: x[0])
-
- assert len(failures) == 0, "\n".join([x[1] for x in failures])
-
- # Test helper methods.
- def _all(check):
- return [x for x in actual.values() if x.get("dev") == f"dev: {check.value}"]
-
- def line(cont: str) -> int:
- # A helper for getting expected line numbers
- return [i + 1 for i, x in enumerate(lines) if cont in x][0]
-
- # Verify non-payable checks.
- nonpayable_checks = _all(RuntimeErrorType.NONPAYABLE_CHECK)
- if nonpayable_checks:
- assert len(nonpayable_checks) >= 1
- else:
- # NOTE: Vyper 0.3.10 doesn't have these anymore.
- # But they do have a new error type instead.
- checks = _all(RuntimeErrorType.INVALID_CALLDATA_OR_VALUE)
- assert len(checks) >= 1
-
- # Verify integer overflow checks
- overflows = _all(RuntimeErrorType.INTEGER_OVERFLOW)
- overflow_no = line("return (2**127-1) + i")
- expected_overflow_loc = [overflow_no, 12, overflow_no, 20]
- assert len(overflows) >= 2
-
- if vers == "0.3.7":
- assert expected_overflow_loc in [o["location"] for o in overflows if o["location"]]
- # else: 0.3.9 registers as IntegerBoundsCheck
-
- # Verify integer underflow checks
- underflows = _all(RuntimeErrorType.INTEGER_UNDERFLOW)
- underflow_no = line("return i - (2**127-1)")
- expected_underflow_loc = [underflow_no, 11, underflow_no, 25]
- assert len(underflows) >= 2
-
- if vers == "0.3.7":
- assert expected_underflow_loc in [u["location"] for u in underflows if u["location"]]
- # else: 0.3.9 registers as IntegerBoundsCheck
-
- # Verify division by zero checks
- div_zeros = _all(RuntimeErrorType.DIVISION_BY_ZERO)
- div_no = line("return 4 / i")
- expected_div_0 = [div_no, 11, div_no, 16]
-
- if vers == "0.3.7":
- assert len(div_zeros) >= 1
- assert expected_div_0 in [d["location"] for d in div_zeros if d["location"]]
- # TODO: figure out how to detect these on 0.3.9
-
- # Verify modulo by zero checks
- mod_zeros = _all(RuntimeErrorType.MODULO_BY_ZERO)
- mod_no = line("return 4 % i")
- expected_mod_0_loc = [mod_no, 11, mod_no, 16]
- assert len(mod_zeros) >= 1
- assert expected_mod_0_loc in [m["location"] for m in mod_zeros if m["location"]]
-
- # Verify index out of range checks
- range_checks = _all(RuntimeErrorType.INDEX_OUT_OF_RANGE)
- range_no = line("return self.dynArray[idx]")
- expected_range_check = [range_no, 11, range_no, 24]
- if vers == "0.3.7":
- assert len(range_checks) >= 1
- assert expected_range_check in [r["location"] for r in range_checks]
- # TODO: figure out how to detect these on 0.3.9
-
-
-def test_enrich_error_int_overflow(geth_provider, traceback_contract, account):
- int_max = 2**256 - 1
- with pytest.raises(IntegerOverflowError):
- traceback_contract.addBalance(int_max, sender=account)
-
-
-def test_enrich_error_non_payable_check(geth_provider, traceback_contract, account):
- if traceback_contract.contract_type.name.endswith("0310"):
- # NOTE: Nonpayable error is combined with calldata check now.
- with pytest.raises(InvalidCalldataOrValueError):
- traceback_contract.addBalance(123, sender=account, value=1)
-
- else:
- with pytest.raises(NonPayableError):
- traceback_contract.addBalance(123, sender=account, value=1)
-
-
-def test_enrich_error_fallback(geth_provider, traceback_contract, account):
- """
- Show that when attempting to call a contract's fallback method when there is
- no fallback defined results in a custom contract logic error.
- """
- with pytest.raises(FallbackNotDefinedError):
- traceback_contract(sender=account)
-
-
-def test_enrich_error_handle_when_name(compiler, geth_provider, mocker):
- """
- Sometimes, a provider may use the name of the enum instead of the value,
- which we are still able to enrich.
- """
-
- tb = mocker.MagicMock()
- tb.revert_type = "NONPAYABLE_CHECK"
- error = ContractLogicError("", source_traceback=tb)
- new_error = compiler.enrich_error(error)
- assert isinstance(new_error, NonPayableError)
-
-
-@pytest.mark.parametrize("arguments", [(), (123,), (123, 321)])
-def test_trace_source(account, geth_provider, project, traceback_contract, arguments):
- receipt = traceback_contract.addBalance(*arguments, sender=account)
- actual = receipt.source_traceback
- base_folder = Path(__file__).parent / "contracts" / "passing_contracts"
- contract_name = traceback_contract.contract_type.name
- expected = rf"""
-Traceback (most recent call last)
- File {base_folder}/{contract_name}.vy, in addBalance
- 32 if i != num:
- 33 continue
- 34
- --> 35 return self._balance
-""".strip()
- assert str(actual) == expected
-
-
-def test_trace_source_content_from_kwarg_default_parametrization(
- account, geth_provider, project, traceback_contract
-):
- """
- This test is for verifying stuff around Vyper auto-generated methods from kwarg defaults.
- Mostly, need to make sure the correct content is discoverable in the source traceback
- so that coverage works properly.
- """
- no_args_tx = traceback_contract.addBalance(sender=account)
- no_args_tb = no_args_tx.source_traceback
-
- def check(name: str, tb):
- items = [x.closure.full_name for x in tb if x.closure.full_name == name]
- assert len(items) >= 1
-
- check("addBalance()", no_args_tb)
-
- single_arg_tx = traceback_contract.addBalance(442, sender=account)
- single_arg_tb = single_arg_tx.source_traceback
- check("addBalance(uint256)", single_arg_tb)
-
- both_args_tx = traceback_contract.addBalance(4, 5, sender=account)
- both_args_tb = both_args_tx.source_traceback
- check("addBalance(uint256,uint256)", both_args_tb)
-
-
-def test_trace_err_source(account, geth_provider, project, traceback_contract):
- txn = traceback_contract.addBalance_f.as_transaction(123)
- try:
- account.call(txn)
- except ContractLogicError:
- pass
-
- receipt = geth_provider.get_receipt(txn.txn_hash.hex())
- actual = receipt.source_traceback
- base_folder = Path(__file__).parent / "contracts" / "passing_contracts"
- contract_name = traceback_contract.contract_type.name
- version_key = contract_name.split("traceback_contract_")[-1]
- expected = rf"""
-Traceback (most recent call last)
- File {base_folder}/{contract_name}.vy, in addBalance_f
- 48 if i == num:
- 49 break
- 50
- 51 # Fail in the middle (is test)
- 52 # Fails because was already set above.
- --> 53 self.registry.register_f(msg.sender)
- 54
- 55 for i in [1, 2, 3, 4, 5]:
- 56 if i != num:
- 57 continue
-
- File {base_folder}/registry_{version_key}.vy, in register_f
- 11 def register_f(addr: address):
- --> 12 assert self.addr != addr, "doubling."
- 13 self.addr = addr
- """.strip()
- assert str(actual) == expected
-
-
-def test_trace_source_default_method(geth_provider, account, project):
- """
- This test proves you get a working source-traceback from __default__ calls.
- """
- contract = project.non_payable_default.deploy(sender=account)
- receipt = contract(sender=account)
- src_tb = receipt.source_traceback
- actual = str(src_tb[-1][-1]).lstrip() # Last line in traceback (without indent).
- expected = "8 log NotPayment(msg.sender)"
- assert actual == expected
-
-
-def test_compile_with_version_set_in_config(config, projects_path, compiler, mocker):
- path = projects_path / "version_in_config"
- version_from_config = "0.3.7"
- spy = mocker.patch("ape_vyper.compiler.vvm_compile_standard")
- project = ape.Project(path)
-
- contract = project.contracts_folder / "v_contract.vy"
- settings = compiler.get_compiler_settings((contract,), project=project)
- assert str(list(settings.keys())[0]) == version_from_config
-
- # Show it uses this version in the compiler.
- project.load_contracts(use_cache=False)
- assert str(spy.call_args[1]["vyper_version"]) == version_from_config
-
-
-def test_compile_code(project, compiler, dev_revert_source):
- code = dev_revert_source.read_text(encoding="utf8")
- actual = compiler.compile_code(code, project=project, contractName="MyContract")
- assert isinstance(actual, ContractType)
- assert actual.name == "MyContract"
- assert len(actual.abi) > 1
- assert len(actual.deployment_bytecode.bytecode) > 1
- assert len(actual.runtime_bytecode.bytecode) > 1
-
-
-def test_compile_with_version_set_in_settings_dict(config, compiler_manager, projects_path):
- path = projects_path / "version_in_config"
- contract = path / "contracts" / "v_contract.vy"
- project = ape.Project(path)
- expected = '.*Version specification "0.3.10" is not compatible with compiler version "0.3.3"'
- iterator = compiler_manager.compile(
- (contract,), project=project, settings={"vyper": {"version": "0.3.3"}}
- )
- with pytest.raises(CompilerError, match=expected):
- _ = list(iterator)
-
-
-@pytest.mark.parametrize(
- "contract_name",
- [
- # This first one has most known edge cases
- "flatten_me.vy",
- # Test on the below for general compatibility.
- "contract_with_dev_messages.vy",
- "erc20.vy",
- "use_iface.vy",
- "optimize_codesize.vy",
- "evm_pragma.vy",
- "use_iface2.vy",
- "contract_no_pragma.vy", # no pragma should compile with latest version
- "empty.vy", # empty file still compiles with latest version
- "pragma_with_space.vy",
- ],
-)
-def test_flatten_contract(all_versions, project, contract_name, compiler):
- path = project.contracts_folder / contract_name
- source = compiler.flatten_contract(path, project=project)
-
- # Ensure it also compiles.
- source_code = str(source)
- version = compiler._source_vyper_version(source_code)
- vvm.install_vyper(str(version))
- vvm.compile_source(source_code, base_path=project.path, vyper_version=version)
-
-
-def test_flatten_contract_04(project, compiler):
- path = project.contracts_folder / "zero_four.vy"
- source = compiler.flatten_contract(path, project=project)
- source_code = str(source)
- assert source_code == ZERO_FOUR_CONTRACT_FLAT
-
- # Ensure it also compiles.
- version = compiler._source_vyper_version(source_code)
- vvm.install_vyper(str(version))
- vvm.compile_source(source_code, base_path=project.path, vyper_version=version)
diff --git a/tests/test_coverage.py b/tests/test_coverage.py
deleted file mode 100644
index 64229ed6..00000000
--- a/tests/test_coverage.py
+++ /dev/null
@@ -1,216 +0,0 @@
-import re
-import shutil
-import xml.etree.ElementTree as ET
-from pathlib import Path
-from typing import Optional
-
-import pytest
-
-LINES_VALID = 8
-MISSES = 0
-LINE_COV = "100.0".replace(".", r"\.")
-FUNC_COV = "100.0".replace(".", r"\.")
-
-EXPECTED_COVERAGE_REPORT = r"""
-\s*=+\s*Coverage Profile\s*=+\s*
-\s*\s*coverage_test Coverage\s*\s*
-\s*
-\s*Func\s+Stmts\s+Miss\s+Cover\s*
-\s*─+\s*
-\s*__cannot_send_ether_to_nonpayable_function__\s+1\s+0\s+100\.0%\s*
-\s*__fallback_not_defined__\s+1\s+0\s+100\.0%\s*
-\s*_immutable_number\s+0\s+0\s+100\.0%\s*
-\s*_number\s+0\s+0\s+100\.0%\s*
-\s*foo_method\(\)\s+1\s+0\s+100\.0%\s*
-\s*foo_method\(uint256\)\s+1\s+0\s+100\.0%\s*
-\s*foo_method\(uint256,uint256\)\s+3\s+0\s+100\.0%\s*
-\s*view_method\s+1\s+0\s+100\.0%\s*
-\s*
-\s*line=100\.0%, func=100\.0%\s*
-\s*
-\s*exclude_part_of_contract Coverage\s*
-\s*
-\s*Func\s+Stmts\s+Miss\s+Cover\s*
-\s*─+\s*
-\s*__fallback_not_defined__\s+1\s+1\s+0\.0%\s*
-\s*include_me\s+1\s+1\s+0\.0%\s*
-\s*
-\s*line=0\.0%, func=0\.0%\s*
-""".lstrip()
-COVERAGE_START_PATTERN = re.compile(r"=+ Coverage Profile =+")
-
-
-@pytest.fixture
-def coverage_project_path(projects_path):
- return projects_path / "coverage_project"
-
-
-@pytest.fixture
-def coverage_project(config, coverage_project_path):
- build_dir = coverage_project_path / ".build"
- shutil.rmtree(build_dir, ignore_errors=True)
-
- with config.Project.create_temporary_project() as tmp_project:
- shutil.copytree(coverage_project_path, tmp_project.path, dirs_exist_ok=True)
- yield tmp_project
-
- shutil.rmtree(build_dir, ignore_errors=True)
-
-
-@pytest.fixture
-def setup_pytester(pytester, coverage_project):
- tests_path = coverage_project.tests_folder
-
- # Make other files
- def _make_all_files(base: Path, prefix: Optional[Path] = None):
- if not base.is_dir():
- return
-
- for file in base.iterdir():
- if file.is_dir() and not file.name == "tests":
- _make_all_files(file, prefix=Path(file.name))
- elif file.is_file():
- name = (prefix / file.name).as_posix() if prefix else file.name
-
- if name == "ape-config.yaml":
- # Hack in in-memory overrides for testing purposes.
- text = str(coverage_project.config)
- else:
- text = file.read_text(encoding="utf8")
-
- src = {name: text.splitlines()}
- pytester.makefile(file.suffix, **src)
-
- # Assume all tests should pass
- num_passes = 0
- num_failed = 0
- test_files = {}
- for file_path in tests_path.iterdir():
- if file_path.name.startswith("test_") and file_path.suffix == ".py":
- content = file_path.read_text(encoding="utf8")
- test_files[file_path.name] = content
- num_passes += len(
- [
- x
- for x in content.split("\n")
- if x.startswith("def test_") and not x.startswith("def test_fail_")
- ]
- )
- num_failed += len([x for x in content.split("\n") if x.startswith("def test_fail_")])
-
- pytester.makepyfile(**test_files)
- _make_all_files(coverage_project.path)
-
- # Check for a conftest.py
- conftest = tests_path / "conftest.py"
- if conftest.is_file():
- pytester.makeconftest(conftest.read_text(encoding="utf8"))
-
- # Returns expected number of passing tests.
- return num_passes, num_failed
-
-
-def test_coverage(geth_provider, setup_pytester, coverage_project, pytester):
- passed, failed = setup_pytester
- result = pytester.runpytest_subprocess("--coverage")
- try:
- result.assert_outcomes(passed=passed, failed=failed)
- except ValueError:
- pytest.fail(str(result.stderr))
-
- actual = _get_coverage_report(result.outlines)
- expected = [x.strip() for x in EXPECTED_COVERAGE_REPORT.split("\n")]
- _assert_coverage(actual, expected)
-
- # Ensure XML was created.
- base_dir = pytester.path / ".build"
- xml_path = base_dir / "coverage.xml"
- _assert_xml(xml_path)
- html_path = base_dir / "htmlcov"
- assert html_path.is_dir()
- index = html_path / "index.html"
- assert index.is_file()
- _assert_html(index)
-
-
-def _get_coverage_report(lines: list[str]) -> list[str]:
- ret = []
- started = False
- for line in lines:
- if not started:
- if COVERAGE_START_PATTERN.match(line):
- # Started.
- started = True
- ret.append(line.strip())
- else:
- # Wait for start.
- continue
-
- elif started and re.match(r"=+ .* =+", line):
- # Ended.
- ret.append(line.strip())
- return ret
-
- else:
- # Line in between start and end.
- ret.append(line.strip())
-
- return ret
-
-
-def _assert_coverage(actual: list[str], expected: list[str]):
- for idx, (a_line, e_line) in enumerate(zip(actual, expected)):
- message = f"Failed at index {idx}. Expected={e_line}, Actual={a_line}"
- assert re.match(e_line, a_line), message
-
-
-def _assert_xml(xml_path: Path):
- assert xml_path.is_file()
- xml = xml_path.read_text(encoding="utf8")
- assert '' in xml
-
- # Show is valid XML.
- tree = ET.parse(str(xml_path))
-
- # Assert there are sources.
- sources = tree.find("sources")
- assert sources is not None
- source = sources.find("source")
- assert source is not None
- assert source.text is not None
- assert "contracts" in source.text
-
- # Assert there are statements.
- packages = tree.find("packages")
- assert packages is not None
- package = packages.find("package")
- assert package is not None
- classes = package.find("classes")
- assert classes is not None
- _class = classes.find("class")
- assert _class is not None
- lines = _class.find("lines")
- assert lines is not None
- line = lines.find("line")
- assert line is not None
- assert "hits" in line.keys()
- assert "number" in line.keys()
-
-
-def _assert_html(index_html: Path):
- html = index_html.read_text(encoding="utf8")
- assert html.startswith("")
- assert "Generated by Ape Framework" in html
- expected_columns = (
- "Source",
- "Statements",
- "Missing",
- "Statement Coverage",
- "Function Coverage",
- )
- for idx, column in enumerate(expected_columns):
- col_no = idx + 1
- expected_col_tag = f'{column} '
- assert expected_col_tag in html
-
- assert "100.0%" in html