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( - '" - ) - ); - }, - - /** - * 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 - - - - - - - - -
-
-
- - - - ape-vyper - -
- -
-
-
-
-
-
-
-
- - -

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 - -
- -
-
-
-
-
-
-
- - - - -
-
-
-
-
-
- - - - - - - - - \ 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

-
-
-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:
-
    -
  • source_coverage (SourceCoverage) – The source -to generate an empty coverage profile for.

  • -
  • contract_source (ethpm_types.source.ContractSource) – The contract with -source content.

  • -
-
-
-
- -
-
-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.

-
-
-
- -
- -
-
-
-
- - - - - - - - - \ 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

-
-
-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.

-
- -
- -
-
-
-
- - - - - - - - - \ 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

-

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

-
- -
-
-ape_vyper.interface.extract_import_aliases(source: str) dict[str, str]
-

Extract import aliases from import lines

-
-
Returns:
-

{import: alias}

-
-
Return type:
-

Dict[str, str]

-
-
-
- -
-
-ape_vyper.interface.extract_imports(source: str) tuple[str, 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]

-
-
-
- -
-
-ape_vyper.interface.extract_meta(source_code: str) tuple[Optional[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

-
- -
- -
-
-
-
- - - - - - - - - \ 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 - - - - - - - - - - - -
-
-
- - - - ape-vyper - -
- -
-
-
-
-
-
-
- - -
-
- - - - - - - - \ 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 - - - - - - - - - - - -
-
-
- - - - ape-vyper - -
- -
-
-
-
-
-
-
-
- -

Search

- - - - -

- 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

-

Ape compiler plugin around VVM

-
-

Dependencies

-
    -
  • python3 version 3.10 up to 3.12.

  • -
-
-
-

Installation

-
-

via pip

-

You can install the latest release via pip:

-
pip install ape-vyper
-
-
-
-
-

via setuptools

-

You can clone the repository and use setuptools for the most up-to-date version:

-
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. -Then, from your root Ape project folder, run the command:

-
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:

-
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

-
-

Version Pragma

-
#pragma version 0.3.10
-
-
-
-
-

EVM Version Pragma

-
#pragma evm-version paris
-
-
-
-
-

Optimization Pragma

-
#pragma optimize codesize
-
-
-
-
-
-
- -
-
-
-
- - - - - - - - - \ 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