{"sources":{"Neonkoi.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.24;\n\n// File: @openzeppelin/contracts/utils/introspection/IERC165.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/IERC721.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)\n\n\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n     *   {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)\n\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\n     * reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)\n\n\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n\n// File: @openzeppelin/contracts/utils/Context.sol\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n\n// File: @openzeppelin/contracts/utils/math/Math.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n\n// File: @openzeppelin/contracts/utils/math/SignedMath.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n\n// File: @openzeppelin/contracts/utils/Strings.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\n\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n\n// File: @openzeppelin/contracts/utils/introspection/ERC165.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\n\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n\n// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)\n\n/**\n * @dev Standard ERC20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n\n// File: @openzeppelin/contracts/token/ERC721/ERC721.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)\n\n\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\nabstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {\n    using Strings for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    mapping(uint256 tokenId => address) private _owners;\n\n    mapping(address owner => uint256) private _balances;\n\n    mapping(uint256 tokenId => address) private _tokenApprovals;\n\n    mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual returns (uint256) {\n        if (owner == address(0)) {\n            revert ERC721InvalidOwner(address(0));\n        }\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual returns (address) {\n        return _requireOwned(tokenId);\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {\n        _requireOwned(tokenId);\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual {\n        _approve(to, tokenId, _msgSender());\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual returns (address) {\n        _requireOwned(tokenId);\n\n        return _getApproved(tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) public virtual {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        // Setting an \"auth\" arguments enables the `_isAuthorized` check which verifies that the token exists\n        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.\n        address previousOwner = _update(to, tokenId, _msgSender());\n        if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) public {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {\n        transferFrom(from, to, tokenId);\n        _checkOnERC721Received(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n     *\n     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the\n     * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances\n     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by\n     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.\n     */\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        return _owners[tokenId];\n    }\n\n    /**\n     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.\n     */\n    function _getApproved(uint256 tokenId) internal view virtual returns (address) {\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in\n     * particular (ignoring whether it is owned by `owner`).\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {\n        return\n            spender != address(0) &&\n            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.\n     * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets\n     * the `spender` for the specific `tokenId`.\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {\n        if (!_isAuthorized(owner, spender, tokenId)) {\n            if (owner == address(0)) {\n                revert ERC721NonexistentToken(tokenId);\n            } else {\n                revert ERC721InsufficientApproval(spender, tokenId);\n            }\n        }\n    }\n\n    /**\n     * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n     *\n     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that\n     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.\n     *\n     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the\n     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership\n     * remain consistent with one another.\n     */\n    function _increaseBalance(address account, uint128 value) internal virtual {\n        unchecked {\n            _balances[account] += value;\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner\n     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that\n     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.\n     */\n    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {\n        address from = _ownerOf(tokenId);\n\n        // Perform (optional) operator check\n        if (auth != address(0)) {\n            _checkAuthorized(from, auth, tokenId);\n        }\n\n        // Execute the update\n        if (from != address(0)) {\n            // Clear approval. No need to re-authorize or emit the Approval event\n            _approve(address(0), tokenId, address(0), false);\n\n            unchecked {\n                _balances[from] -= 1;\n            }\n        }\n\n        if (to != address(0)) {\n            unchecked {\n                _balances[to] += 1;\n            }\n        }\n\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        return from;\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner != address(0)) {\n            revert ERC721InvalidSender(address(0));\n        }\n    }\n\n    /**\n     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n        _mint(to, tokenId);\n        _checkOnERC721Received(address(0), to, tokenId, data);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     * This is an internal function that does not check if the sender is authorized to operate on the token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal {\n        address previousOwner = _update(address(0), tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(address from, address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        } else if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients\n     * are aware of the ERC721 standard to prevent tokens from being forever locked.\n     *\n     * `data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is like {safeTransferFrom} in the sense that it invokes\n     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `tokenId` token must exist and be owned by `from`.\n     * - `to` cannot be the zero address.\n     * - `from` cannot be the zero address.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId) internal {\n        _safeTransfer(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\n        _transfer(from, to, tokenId);\n        _checkOnERC721Received(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is\n     * either the owner of the token, or approved to operate on all tokens held by this owner.\n     *\n     * Emits an {Approval} event.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address to, uint256 tokenId, address auth) internal {\n        _approve(to, tokenId, auth, true);\n    }\n\n    /**\n     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not\n     * emitted in the context of transfers.\n     */\n    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {\n        // Avoid reading the owner unless necessary\n        if (emitEvent || auth != address(0)) {\n            address owner = _requireOwned(tokenId);\n\n            // We do not use _isAuthorized because single-token approvals should not be able to call approve\n            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {\n                revert ERC721InvalidApprover(auth);\n            }\n\n            if (emitEvent) {\n                emit Approval(owner, to, tokenId);\n            }\n        }\n\n        _tokenApprovals[tokenId] = to;\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Requirements:\n     * - operator can't be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n        if (operator == address(0)) {\n            revert ERC721InvalidOperator(operator);\n        }\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).\n     * Returns the owner.\n     *\n     * Overrides to ownership logic should be done to {_ownerOf}.\n     */\n    function _requireOwned(uint256 tokenId) internal view returns (address) {\n        address owner = _ownerOf(tokenId);\n        if (owner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n        return owner;\n    }\n\n    /**\n     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the\n     * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param data bytes optional data to send along with the call\n     */\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {\n        if (to.code.length > 0) {\n            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n                if (retval != IERC721Receiver.onERC721Received.selector) {\n                    revert ERC721InvalidReceiver(to);\n                }\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert ERC721InvalidReceiver(to);\n                } else {\n                    /// @solidity memory-safe-assembly\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        }\n    }\n}\n\n// File: @openzeppelin/contracts/interfaces/IERC2981.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)\n\n\n\n/**\n * @dev Interface for the NFT Royalty Standard.\n *\n * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal\n * support for royalty payments across all NFT marketplaces and ecosystem participants.\n */\ninterface IERC2981 is IERC165 {\n    /**\n     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of\n     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.\n     */\n    function royaltyInfo(\n        uint256 tokenId,\n        uint256 salePrice\n    ) external view returns (address receiver, uint256 royaltyAmount);\n}\n\n// File: @openzeppelin/contracts/token/common/ERC2981.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (token/common/ERC2981.sol)\n\n\n\n/**\n * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.\n *\n * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for\n * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.\n *\n * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the\n * fee is specified in basis points by default.\n *\n * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See\n * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to\n * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.\n */\nabstract contract ERC2981 is IERC2981, ERC165 {\n    struct RoyaltyInfo {\n        address receiver;\n        uint96 royaltyFraction;\n    }\n\n    RoyaltyInfo private _defaultRoyaltyInfo;\n    mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;\n\n    /**\n     * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).\n     */\n    error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);\n\n    /**\n     * @dev The default royalty receiver is invalid.\n     */\n    error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);\n\n    /**\n     * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).\n     */\n    error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);\n\n    /**\n     * @dev The royalty receiver for `tokenId` is invalid.\n     */\n    error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @inheritdoc IERC2981\n     */\n    function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address, uint256) {\n        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];\n\n        if (royalty.receiver == address(0)) {\n            royalty = _defaultRoyaltyInfo;\n        }\n\n        uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();\n\n        return (royalty.receiver, royaltyAmount);\n    }\n\n    /**\n     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a\n     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an\n     * override.\n     */\n    function _feeDenominator() internal pure virtual returns (uint96) {\n        return 10000;\n    }\n\n    /**\n     * @dev Sets the royalty information that all ids in this contract will default to.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {\n        uint256 denominator = _feeDenominator();\n        if (feeNumerator > denominator) {\n            // Royalty fee will exceed the sale price\n            revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);\n        }\n        if (receiver == address(0)) {\n            revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));\n        }\n\n        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Removes default royalty information.\n     */\n    function _deleteDefaultRoyalty() internal virtual {\n        delete _defaultRoyaltyInfo;\n    }\n\n    /**\n     * @dev Sets the royalty information for a specific token id, overriding the global default.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {\n        uint256 denominator = _feeDenominator();\n        if (feeNumerator > denominator) {\n            // Royalty fee will exceed the sale price\n            revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);\n        }\n        if (receiver == address(0)) {\n            revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));\n        }\n\n        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Resets royalty information for the token id back to the global default.\n     */\n    function _resetTokenRoyalty(uint256 tokenId) internal virtual {\n        delete _tokenRoyaltyInfo[tokenId];\n    }\n}\n\n// File: @openzeppelin/contracts/access/Ownable.sol\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n\n// File: @openzeppelin/contracts/utils/Base64.sol\n// OpenZeppelin Contracts (last updated v5.0.2) (utils/Base64.sol)\n\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n */\nlibrary Base64 {\n    /**\n     * @dev Base64 Encoding/Decoding Table\n     */\n    string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n    /**\n     * @dev Converts a `bytes` to its Bytes64 `string` representation.\n     */\n    function encode(bytes memory data) internal pure returns (string memory) {\n        /**\n         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n         */\n        if (data.length == 0) return \"\";\n\n        // Loads the table into memory\n        string memory table = _TABLE;\n\n        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter\n        // and split into 4 numbers of 6 bits.\n        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up\n        // - `data.length + 2`  -> Round up\n        // - `/ 3`              -> Number of 3-bytes chunks\n        // - `4 *`              -> 4 characters for each chunk\n        string memory result = new string(4 * ((data.length + 2) / 3));\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Prepare the lookup table (skip the first \"length\" byte)\n            let tablePtr := add(table, 1)\n\n            // Prepare result pointer, jump over length\n            let resultPtr := add(result, 0x20)\n            let dataPtr := data\n            let endPtr := add(data, mload(data))\n\n            // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and\n            // set it to zero to make sure no dirty bytes are read in that section.\n            let afterPtr := add(endPtr, 0x20)\n            let afterCache := mload(afterPtr)\n            mstore(afterPtr, 0x00)\n\n            // Run over the input, 3 bytes at a time\n            for {\n\n            } lt(dataPtr, endPtr) {\n\n            } {\n                // Advance 3 bytes\n                dataPtr := add(dataPtr, 3)\n                let input := mload(dataPtr)\n\n                // To write each character, shift the 3 byte (24 bits) chunk\n                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n                // and apply logical AND with 0x3F to bitmask the least significant 6 bits.\n                // Use this as an index into the lookup table, mload an entire word\n                // so the desired character is in the least significant byte, and\n                // mstore8 this least significant byte into the result and continue.\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n            }\n\n            // Reset the value that was cached\n            mstore(afterPtr, afterCache)\n\n            // When data `bytes` is not exactly 3 bytes long\n            // it is padded with `=` characters at the end\n            switch mod(mload(data), 3)\n            case 1 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n                mstore8(sub(resultPtr, 2), 0x3d)\n            }\n            case 2 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n            }\n        }\n\n        return result;\n    }\n}\n\n// File: Neonkoi.sol\ninterface IAgentIdRegistry {\n    function handleOf(address wallet) external view returns (string memory);\n}\n\n/// @title Neonkoi - 1331 Cyber koi girl with glowing orange scales and cyan visor in a rainy neon city for .ai Agent ID holders on BNB Chain\n/// @notice Each wallet gets its first mint free while the 303 free pool lasts (gas only).\n/// Every other mint costs 0.00005 BNB. Max 50 per wallet, 1331 total. Collectible only, not an investment.\n/// @dev Art and metadata are generated fully on-chain from each token id. No IPFS, no reveal, nothing to set after deploy.\ncontract Neonkoi is ERC721, ERC2981, Ownable {\n    using Strings for uint256;\n\n    IAgentIdRegistry public constant AGENT_ID = IAgentIdRegistry(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n    uint256 public constant MAX_SUPPLY = 1331;\n    uint256 public constant FREE_SUPPLY = 303;\n    uint256 public constant FREE_PER_WALLET = 1;\n    uint256 public constant MAX_PER_WALLET = 50;\n    uint256 public constant PRICE = 0.00005 ether;\n\n    uint256 public totalSupply;\n    uint256 public freeClaimed;\n    bool public mintOpen = true;\n    mapping(address => uint256) public mintedBy;\n    mapping(address => uint256) public freeUsed;\n\n    error NoAgentId();\n    error OnlyWallets();\n    error MintClosed();\n    error BadQuantity();\n    error SoldOut();\n    error WalletLimit();\n    error WrongPayment();\n    error WithdrawFailed();\n\n    event Launched(address indexed to, uint256 indexed tokenId, string agent);\n\n    /// @notice Contract whose runtime code holds the artwork bytes (WebP), after a leading 0x00 STOP byte.\n    address public immutable IMAGE;\n\n    /// @dev The WebP artwork is embedded in this source and written, in this same deploy transaction,\n    /// into a small storage contract (runtime = 0x00 STOP byte + image bytes) owned by nobody.\n    constructor(address initialOwner) ERC721(\"Neonkoi\", \"NEONKOI\") Ownable(initialOwner) {\n        bytes memory image_ = hex\"524946467c440000574542505650382070440000b077019d012a900190013f016aaa4fab25a3a32ed78d596020096c6b26e6cb9d90aa8d7729817830528006bbb90e8fd8f7dcb9c7f567a5e3c905bb2c7a70feb9ea43fe0bd2f7a97f39be6bbea3bfb7fa34ff99ebb4f460e9aec64a96fb7971abd48b1572f9f59dde9febbc61f263f34eccea9dfe2bd123cf4b534f729fee66711f959ac970238f3eba2c5db8de3459e633d1a60ac90539474e8534116c0adaa6166b152888040c274ab8c7834ee1f9e5e6865a8832ab3b23488fd0a86686ca547423383f5a8f92a5d0ffe36800acf25d89c00cd9328424707518a91375eff58ef709f784b1b7b956c620a6ffc63d5d41fc77ead2a41ed61927dec45bbded7794669da904b028a3e81be738ecf24d4087776e465f253bc0092283f27b7960b6aedf6206251c26860c877c0c05517dd60795edfb4591f25a46b2192b9fdfdf407d429d6328dcd84dbcb3dea44d494a3aa2b3abdb1183efbb6aac8e860d11c3b6c44e9b49130eff73259cc3cc10adbecd415d1f22a8424554e7271096828e090eadb196cd35b082e71ac51350611c09548657af8ebe3a8be2379b0283b95b34b621bad89558417ad35c013cdc3a2998ec4af1eedcb2fac3b56d95cc0292744a6721eadc19633404fe97730e70cea18bd765acd4335def85c40daa928a7967bfb25a3f84e92700dfcf50c84deb62ceab3bb40b131c387d37f235abfdbcab7e6305453d8cdb75dad2f48a4e0cc6b3f1577e8437237b314edcc90bc5ac95e68ab7b66924391cd0e8ddf5eb048f2a4539828290df8ec603dd8906f2aacd8201bb82843a40e90b5cc04a857fb222e679981783e25470a9cf90b48f1a159c9e4ec70f1e2a476dcc13718378187561258401c532a15af95d123bec550efbabdb5fb548bb71737e1e6df5e281daec6d016bb87d4ffcc25af7ce16eb52712d3468cf1ed637bbb7ac531f7b29f7bcaf59b570aaab2bcec51d322bfc325a8144e55cd14eac8eab7d5dba1a5587ceb696a9fff1967a38f49b1d8441ba491d45d51fc54de7b2008e4105f4ae61c713931928b573faf09a31da9a246ed5afd9a9007c66cb0049407c797afe2daea6232de3982d9998a043c7478f649b5f0a42fad584e36ec11ea6a551f7c7fa3f04c215f694472935941bee980f9cd2ddbba4200e294d798bc11f63c28956e5e9680fa137e56441a6a371147aff598fdcf47e456ed0c966a96c655000b483e840857c537991ce048aaaf8ad01a27f89efdefe4cd678fcda04a35b9f9adb1f3f4ee869968084cc883924c8f4e2457bbc469fb06e8be079563917c02ac87102f7153841ac523549fc4dbd777b71531b43cea178c93f1464f5979bedac54763776f4a1977335f9ea36aacbaad26f2b32d9f519672e90d81d78b9c4e7c69366776113623aacd1d24c0b7802e05fabfc7aedcfe3978b1cc0a78a4e0c18669a50a3659c23fd5d7e6dd05bc1b444bc5333200fc3c4e726adf41ef772de9553bb46ae5be334eec0b9ad804c566afd69163116c2424e986385fd5b813f44d1404a6bdc684bb63cc2826b432302a29ea41b39e15b473b3801a59e4cffd01f46494880e5d67fdfbed7cd6f95913bd5141f39dd88d9d6d1227993e520cba46d75b226ffe13091599c68b78ef8301877c5d54daad5e3c4e6a6c3b90721051ca0ca234b2d8ed5b14428fb2499e9888543ff9ca1f89167335377a5c947669db896a8ad966ba16f0a9ad8b726fc4b60bb88953ec3d395e1c38f02b946aaa939dc04530a749c33d1e2764efe035aec3c2cc617d58474a7c22d13a70beed396571ddac9d37f3cefdfc355f04805f910f1c24edb0f5fe470bfd91450df1f0b2662244f2f5cadb24be0e6efac7efd71550b7e7c0c3e0ef79c7ef7b2543bc2de6bb86e288c9ad07984a75f73367e9e0fedf27c23923703016dbf87219cec28b45d6b7a604d4fa7c40204d1ec31351f4c72deba54fc56d55b663644e6ce05ac91daad0fb543389fb7bbfddfdc5bbc2e3f982f2928075590fbc9fe38501fe79fbd3e046b868374ff8e41e40ecf5b5b60ba88338c8056d69d8fc992e7e36a8dda39da55249be4096e72511f16166ba3c3718d85c0e15f69b0a8a79693431b243201833340e0d67adce9936a18ecd24d797ea76cba9122813c1f4e3caff48649b88c031e22dd2ccc705a54b904d2b1e6308b47530bed3f7f23ad395a11cf092a79590a9deb8efb214cb56a0d1e002a5fa3c72ffa1777cb7873b52e5175310dc1b278ad65f52982b536579da29ee87a3673aaeeb4d465af20a46db2b94e876c16d1ee66343e3c05c80f8257937d10b676af881f1c7ee321ca0df463ddb1a8e43cf5d285ed4229e0501dfda2e77ed2687ee36669441b1928f2a21bf802c6e3d9acaac762dc82ebcae66ada07aca91d62cea7faca34edcec6d9075b5852c781525dddfa738f95c29b6a283af94f1f31355e58383a3485b3b6e1c125c2ed9898e582164fc639dfcb6745415441fbdf067dffb2c0b0e516e92d71a3621f9b2a77f8a98ff1305b8b44f810336675440483554f980e6175dee06721c2123d59a18878fad2ce02753551825476bca7177c77877fa29b22461cbbccdb42b2e72851906674604ec76a1fb08d7641d0f5dae8ddb01ec916da13772eff7d457309fd29873043e94aba1de983b36c9861beb8d4bed5719244d4c888d79378f3dcecd36f8d0d1c775d3ded97d0413327d7f5c6a1628f0e6fc1ff6213db87331b84111b8c0afeceefe33e9c694a78eed53728d11cccde66d46b0e15a9a6b948becfa8926cfbf72584f1b7faa1df05c1d465a0f3f45dc8ca0b0a3097c2df26899818cee0422e8a2e0e5e74c31f0cf9a8af9ff897577d48397ef508b53e4c150dc27ac195dc001e30b858d024b220e75c3d9ca820b09cf4c8172d9a2ac9ee70c17ef32d7a87683887e6f9b0143f84428639dd2f53cc32578b0eb1139fae6aa3e8dd2c5d7ffc44176040741885838267ecebfb45cfabe577c12d95858377f79afcfd604914d94e37c1ec126844e72c95bbd272a29ffc0b9da2bea55ad1da61a55ff721ff7df459ae56c8830ca91319633990aa4090554375339c18ff514da38b790a3146ae7ee598df7468f30b17c7f788b12ca1817201e14cc8b548fa7149c372f39d2b69b2a4a73fe4cccaac0b65e7854a79788f434f72afd186550f8b520816c3df959eea656da8c01e8e41859061b41b71ee2eb46d7b94da2424dc0ef1c6ecd679124189791d9bd004d984687b11f4c225dfe81d8f75ae6ade3da05280104dd9b597dfd2ed9b3074d52f0d900f2792e77729f2cdbdab19f529d71360babbfb8a2aaf1659390eebd6294821e15b82be0b17659e6aebb894cdf15ff85def4bf5b95f0ea659e5a38fd62258d7b1d1021580102862c62db73adf6a9901368eb550b11e30cb15c9a0ed04f810dc2ae8a355c140c3dda974384e563eedb18817bc04b5c3e12b96330e618fe8822270de670ab455fff84779483195783cdf6c5781f9b7ad7cf2649f8420fc4907a30cda27d8affdc020c3d52a2e541f27cada3fb6b978407253dba15b7888e076bb90af1dec8dc64b84acd74530dea9711d3c2736cdb0039db66af1f966774f7f03ec24be82b8c1f8df1739251ed19d80f408df90bf41c2c8c8710400fd2fada487f8a1928dafb8590a146a703075602791737a6e46fe1d59ca23123792530aa36b7d95dd3ae1aae58d8e00f8f7f40398c7684a7954c000ca89c77349068b9ff57fa36a8f1e62ad2bd5e1677f1c4424edb156f2fb0583aaa3c5b74be6697c14eed845155aa944a63744faab092934658e97c59e694195d874ad9ae3dd032711e1cc5bffb94e3c3898219c4f2b6e85913be7ab7f977cdad5206863c9974409d6db3f8e8db18c2ebda59ddc4c47c88e07eeff75dd1e4d2282d81a532810f6679e8163e782810e8238b0f87379b0cae5bd25f893d1fedf03511aedb5ec1a348a43d668fae27e2de93bea9cccce765897ec62234497af919f0d2c9501f56748295befc398ef19a09d383518686ebeb1c32b0e032027973532c5ec160ebf4cdaf0c26725c781f61830f5fc11ae674564db01ca6fe71cf2d6e0e4992d23e0fc315163e1e6924c97f08de8ac0511eca5ea67877657345c17dc665f1e19ab9081c33c2e525f555805aef59de63daa2861a453db78dfbc23fd76b85321a92cdf3dd7b24418d1a91e2354cec12cdca4ead1debb31420cd5f8c9778fbcb2ba885f510e36d01c86423b8c1ebcf2256d3f8000feefa2005d6f4151c866ebe7c9696c11aa9bd12360544de73dc777585250a0b82bd4678d56427e1be88165d8352eae90345a58298589481b449d05a9d03c8e9ec4b865e381d05ab5dc0c8938841a14c9996ca64471fa803776b547555c2d81684ac8d4469eb8b76f39b995dba73dc48b7709e82fbe7701c527712ed5b8171ba564b3d4b9153830260f993f7093d103801517d1a3e5fe545c7c94f819e6d480dda423296ddbc632c82fde914008f93200394709135bc5326deb617252e21c8e431c8702e2106f1e5bbf4e665d6180c2e682123733731d1375e0b734c272c19c716c6e82e69ada58282d116a3324cace2bee8ad60ca99095f50e61960713e8c7d804bb35b99f209597be07554fa1a72c556ac144cfd67e5b079c30f658146ccc1ccea56c32cdf727cf401f6bb6f97feb4d1d3e3810c621406dba1875883ee8f36dc55d7b84523b39758990967ec7213236578c8cd38db1ffb6844915662b17950f3a13220b3d3854e4aedaca3a34ce649f0374c6f6ac3adf1e681615fad0806f1b118037ea0a833e0627c308d3e0aa4602634a86767a419d5223940050dd5033e91a2f0c075f38cfe064ea6832a46c4c4e5761253460133ec2b16811497c1d9efebeba6e0dd59c458f4f5ab57ca3ff81250a6891aafaf4676f97b7e10535222bca3fb717e8a58a12171c7b674a38aeb3a032f87c76bb04677fd8213c92034b6802d20cd97c76fe0002b68ba338e15c11a56cb1a42635b471310219da7c6be39a5ca23fafa458b807a898290971357ae8cbc3d6c190d749dbacc356fec5e574eb532da7b00d3ad9e19ef1f2975d1a809fe3919241362b458bcbf82ee34d4724b2f4a9a5dec25d6e029d609560084828b2238b0fd81b88ed8b6951d354261b46bb51ce6673d97344e969688163b6df2858fc6b7ca09f124404bc82e1fb69abff2e73d544302accf30438eb39945f4340e59a6f96abc8ff2b7afb5807ebec14c323a5e9e85d3a5e2cb93d96f7b4c430ef6f75c1481b53012fdc2c8ffacbfb2498e063129df4da26c379d1e5e6cf0ac3536f4237ed4cb0659606721549b2f4ad07ac27270c43eec8bb8d53be8a559886586340159b174c66377eda407f6d1e4439610f796ad6b162ca310af8bb2beaae83cc832dbc8711ed33a4350317ae0fbfe7ad016e429fe377bcc490d8ce5c079784e09b815d919b4c20b6b0d2188fddf547d85567b517b3b1deb82530b728cc049d81b255776e3e9a03d4556406bfc631c5a7480eb6ae7456d80fa5d0180816cd13b9694daf99a5443434ecd1ce3fbad1a9e477e5618863c1cde26e1ac33db9edb6c0d042b583d1bf988b025b2c100e65640b0c0f7e9141491a3e465ae8c2378c30ca4d4aec86190742cc9d61708eeda1dded0fad4c6edd4641c5936ad1128dde1186b921c350e4deb3468c2ce1255b3da16c8eed5dec90328ff92dc4b5c6effff6059908eea25c5d69202b4f04fb50da06ce1c9f0496fe9ce5761e8f7a4eea327f62d62bab9d87df1d8da14a8deab996b40dcf57cb8aceebb6b4f9630e3b4ccea4d11f8159987fa32a0e9bb84ae1d3347da8b3bdf262497462d0578a511934d59e7f1da80da291cef2015d8ca04a76eea75eb780493cd80f2a7e575e03f741bc06d35f97a16b1da03646b0bce6e27f8f3ac6799ba00021830747f5db56a8ae5c4de369fdf4456c4e079edb3373d17f7ea4ed0a2ec6f3896a74d41a395364ef7649e8ee8a8cf834359fda9b8e07835a413de2ea089053e7ec3631572aaf389c8d405624d89bc25331b1cb2a267577523fcf1d9843ea3feac1235f0edcfae17c569794c63f8976201655e5731a5291a8840f181f7189f13013d5e3c250bf8e2df41f4358a1b4f857be5866de4952edf54ea5dac368bb658351ff9e6e71c2d8ff1b423b2412cc143fc467af7dc0b1422a825383e7720621264606180895bf7fc2d3d234b220a2b0280e63995c5277526fe8d16983442e2d042097ed6cf59c35bf9f16e84dfee1f7ad71fb213765601f1718b3faad45672a8fc1c98584b27687a0632d41b1b0cb76ba17848f4280196306f5cfab9435c567a7abe5cec9456067e512c7b37445be97d21c54191c0f286a4e6b47085075eee5cf5f7face48de3095cd7f093748e7b19e0ae464fd4c3424508045f591fc32cd1778b587f120d1843ea223deb6b718e208c8f03558a2c56315271d240ad5abb2ebe3ba09f73d052fc3e63ef64cb80f69b3b5dafb3dc22e3991e980420c92f1b196eaa676db527530f1f595dbf497aedd72cb99ffd68837ef188030957002a5349885658f93929a7bc4b43756d190e4bdc07a4831cabd63ae9171c863714fc323e03df186a0aafcdc5aa309fcc33a032743e789d8922f3836e2cb72e411d97e40ca3427bbde68fb51c0e39b514856959ff7471eb7c4e55df25d1e9397bf9e888e721bb1fc03a9bed24e585138a6348e9820ffa9208de7ee4f129f67913826b7698ac1338e2e1193e33ef516fd348813517b7f94eda536f0ca7dcf007796740f3ca1e7da599c6dd9572dbf891d6fa15398738cd32abe8c9c205765be72388f427447c3e953812f7c6939a7bb3ed471d25f88bde434e390544e469efb171b6db29436889b90414859ba6105b17a5063d082e4f1ad2dcd3c1652c399290e4a3857ab8fe8440a27a25e4a2e10ee1b8a9776372ad86f857d9df1fbcc528e45e1a48ea2b2035909d4c442909c4ebb19a050a54ca5d1905293033395cc3b8925dc57d93461f518f1132ac257c4ed1ff06292c1e48e92b39ae9a3d6f41d3b7616b25081be521c164c04c99c3196b8b43d4bec3c275ea3ddf29ba92a9d5da88b84347dc30b56a13c235c6c2fe67ca801fa7bcd1dc41f62a71090bc9b082e2a3b04d62f1f04c88bfe53e5d29353138c8d9b96722ec6c0aa8b7ab4a7a3fa4b5e67c19b6372ca85c039c82dc70254d7d4f23de37c0803dd891cdc6eb520a108a10ed06aa07681438b52ea0bb4e360387ca9bddbc5a7237f5b418881cc8f005fc3918af984c4b05c14eeb2b83f764679696d3d60e541a7430c8ff404ed7b645a7f5ca6c1e69109e5e81f068711256748bb53fa7572ff506a59a215613382fea1b8f01ef489ca082ce983682d399884b71e63a67c9f763720b44840357cd46522fde231c2dff3a426d36fa2ecc5314352821c1aa604b3575f5fc826b72315923d76a94c2956ec7007bf0971c9cec3beab34ec1841e54c68eb92b274b20f4b4f95f94924dcc7ad01e75a1001769fefde63ca46506c0e4ce2c9fefdcc7e42c7c904a151b9785806ec93f62ca24c0845cb638f41029d77f45574d996a9e74a7feda0ae284f16e2b65f909633d65b1daba4e427c8f0bdf903ceb8de88037bb153ece8c5ba2b6650e938617d6029f5cb62215b9ab00ba690f6394c23a3c50a22eb57835a39aeb8a69e1787f43343a775272ff4d61a26514bd8421c5967b001a5ee78a5fd8f5778d744948072578fa7c7e2e2c3bd954916f12a9742d81934da435d29076d5d39966663940372d78e3272935c7f9d35589f2ddc79922aebe00e015ff4a6cb5a5fd21b5931e13da71975216cb3276ceb06722e2f6ca69ba8291508a1f3f55a9d3df5733fdf54a87d7953847317189858b36c3a96608cfef928558076193d0005f31072ab7c52e463be83de23ddfe450048aefa5a692ee2dcfddec31fd16168ac274a0b16f8a50a6cb22fa1bc0ed111eb0e698d523125e6fdc5c9ac2e5941814137f2f7856197254502fe5d80f96b06fc36cbcd8e82dedd222671e0015e5029087ca6c683adc4bc41bff0dfe66f71d8ff2743e47d0d7ba6c2297db3423cc0dbbc5d8cad029fd35a2503649a861b6cffea4a6581539c435fa600675c5a1a885766db1906ba8851c673408b86d699200579851aa3fd6e6f48590f6e88fb01906741c003b6c8c4d65e4995dc48bad94c0c104dec980533cbdfea7653afa6feffb4c1ffbc80b1e7bd4b83601fca49bbaffa6d4ce010cc508ef072b1cb8cfd9b290c7dc8c69cabfd3578a3db8e152d0ad44f383045bd95e65bde545666fe70d3b3a7ff91a261991bc5e3be07e039420030139ccb4cb258cb4b8f5c334d2c54d31e0087842758d44a31b09f406eb84a413af1254833c235d3c4045206b7dfed4e8fb8afd858b1c0d517b0b9c189bc38e854656123bf75c438bb0465fcc12d36781aff0f9985204de2eac9306762cce9c70a34a75ffb2d5e4bc351327034772526c08d8d0e1f96338b288e987365be01ff0bc8b7178fb1ea3d37f4179ba51a4d2b414f56bd314fce3acefd473a5e139728cc929fb8608a21642df4d6c8047f2b8c2225ad43284fd0d0d45bf83bd0a7528af8aa0dbc4fe9bf5ea384408f73972f824f0f64164e35c6895d315d6d3136d905d138fe2ae466255882032a086a47274d0ede9e1a8e190c8f02bbcb9319c593bbce8f15652ebaa5dca730001db48247f3617e220aa2523122f24a39a51dc1ada0aca2d381c753ac9a8deae8e0f6e080fb8e7263f8bfb499bba0cd438e5966eaf52d2de574b218e2f5832441d69522bf28588ac07ca55d9ddc82ea6420b2982c88cb86dc36a401af57c8f4d77a4959ef059654502224cf61faff0b8ee90ba935835df9bdfb2d5100c1521c5d9595568540639e86608ed438e23032138b8690c1708ad6c7e6fe25d1ea486e72f2807e44e219797ef58234ede09d45c66de1cfbf8e76191e64cec1c9dac0601669fea08e0b3cfa31e47e35e500222b568341e6c5403429125a162a5112c3c6b72518e0f4e740997bc65a9874d8a125705c872b1be37831512e75fcd4a5948b41c28cff93aa2f6f6d37b28caf9c60e5f9cb090dee7d0dfe9d84ae9af7c4b626d345af47eabcd475f8e45dccd83a033756627539bd27c104bf79e837a763db1dc3ff9cb02bd7fe31b802e2260d73ef614d37191aeec4a3b31d7c8b31111afff0e115d02fa8cf0b34406c2dfd3af3646bdd8ebbfb4c6c2f998ca5b85faf1f725c4eae6082ca4ba2f83286a96a7ac24ca2cc7bb89251ce27421110987b834fd8e072e248d22e870ac76d4dc7a6ccfad5e633bc6f857ff49e5c8989e90a669da4c4741b880ad858b30adc6905a794a6adb0e15e2c0bc0ec22259c084ab3a54b69e0b831f6250ac18e71e6d8634203bfed181e943bf9424556ba234082594594e98cce58500a3efaafba9b5c2b685d3aa98f723afcaf9d616edbb460ad51d0df5932ed88b18811d508a62071e09795b2241e10111b53c786471f95df4247f9bb7b9b2fc4f550372a971a347fa0c5d9046e59e00febc11823d2c0ca2fb2019af5ad7fb25d82f83c3f10218bad4c6d42e4e6b6a09d25c75486187a74cf1da785e18171bb38e37f4c3b595043f2fb30bdec16b5efbb51be182b1f35dfaa7f9ee1467b7dc75978c9d7632424bc3c2470e8e32d523031dcae1b1f8724bc28ca8053a32d4914a6d3709f43bd8bcd2bb1a3490ec105bbc0a1a1664364662cb04c488772e842fc9d0064c790b6c7c95d1879d64a6f625ba7b5b42dd0242090c0a2d8cbe4b3d2609b7ca24003d6adc849b4944329e161358709965939215b0fd21b0735c615c16f0ba890d64328753ad8c38a62416c8476b6c10d7087f0c801ba7c762418677afa2af61fedb8d9d6802208a2fd7e45b58af9c6272ef03d7998863082eeb0752fb9c24b4801ce5e1944697380e3202a44561b640dd7c87e0cfc4828e8a1454f16fc4daf38ccde4408e53240d7a1d1cab4ca2e8c667798f73fe796a80e3deeed125cda6ad6bab5ad59392eb0107e81af9878eba0dd259c22c5297eebf6059abc19bd9c42df82f0169ed22084314439a0f1b4bf05c517fa616b0b7de936981ca6cdc14573764dab00f00fa3e135064e156dea8e845a1950e72205f8c3630a65c7b7370d71dc4010f036c717e9fd9c69d4257e517fd2348ed77545919086a6cab6b7b269afd30ee1116b574e15a4392215830ed34b318f2d7e44ae82b25e17c5005630ba83fc1ce938c77061a5adb5302d0ce1086c95dec2b10ed3974f2f6f22e2b2b41bdae7bc76694803291fe610ad88d5ca201ec81cc40a29188b16581712295d2b1bda80d7d47523e87272e247cd30c407d31890271744c99318a415e1b725bfaca118fa1bfed0f987b5a99934dc6c06ccb9dba3b6e8c93eca4b4afa4d17f641243633d336d8e70e4f7b42a044ee3e63e82084f962339928d3be26ce1031805ef182cead6e17409baf14916252c3ecbc3d1f4782a71f4bb5d4624b34c8793bfe91259318e897a431d5e7d0a9b64ce77b4428d4d2bd4fc41c5b9928c46ed767571909ec91a6f29ad4c7e8ebb8f64fc0a16b78750fa0c16fbf7549a781abb1ba491f587744d98938d75b8e3d8b318de19cf2cf462c837fd614d9ded3159b566e6695d33f683390bc911f409288e50eb768fd11dfa35b92f6540f277fa2be7fbc934045dad32c25f073215ce41839440149b24958958dce381a08e6ecce469a71768eefce97b7370d7fd757c8f49582b42f4bffe83ca2ff3a8ab5506b2f72658ee2d48d8e4a0bba71bfeb3aadf81275d885283891801182f3f5645fc83ab61fb502dab3ada4a232bf749b2842d4dcfef3e8cfb8e0d926a4a31225dcc257acef3e0ef169a76db4ac0ece3f5b93d7b0236505f4df07aeaee5863b90d4f139bbf017b72b2b94a2c03aed0d123c8dd1de970fe47557a5f4448fd45c4543a67df10baca4d696bb18cb26b516bb31895de4090c479699c1d409c45389cfad80cc70e1408758e806e6ebc6336961873b6f8af16f9c9ea9001a3340397c00a741772caa2bcc63d81cb689bb48a8cce8f942e0d62f70d9b75c3e938ee0d2ccc6da1d1405b308668fc64d788b27b22dbad055bd1f52eacfb22018a482b90692a2520927a6098fc98cbf9faae1d7c0b42a5f9a9701b9aad79c1fa52e6f5e718cb3cca4c1978820938cf3256490ddc9195e88514f8874dc06070ca66e1a1a8f150b3f37e971333e550cd36a1a2776b6644ac106bc04384fa596ee9a3f06144071e438a9f8d2bfc5f22ecad6d919b10b39d261b4478568a422804d6f630d1152b8376aba6a4597c34ad6838d63019c43f6223f2723943c4dbb499a04640ba96130d20979cebda2a2725565e69b7a8f0e1c983566c1fd98fc8274b87cd1ef9a6ab6f942ab4ac842da5d827cab082e7fa804de0f9ffad960deb4c1719583aca5e4264863154574251763c2fb5fa179b78ab477d414b2a95cca06e57850115cdcf118e009e23eabbf8bcb9f6d891deade224542e287e9c4c0fe05f118728c3742c34cf3619c2891a79a74968c37c490fc57c93e2d0b4c2745f58a9e25cdab6a8c6af1574aad0eaaa2b4b0effcfc739fcadc740f64028aae608c70fc85399d7c9bfbe321ffad560af503fa023f13778d7dd9b4b8c7417b3ae752f9f3a953ffdce93d534a2e32dfbd0739a7b8320aeceb2504145a4c9b741f81dc22bfa214865445653e7ebc5fae1fd5dcb7de17b42fb3aa38dd947ea4eb3eb860011f5a16bf88852783332e07d6f70faee7084c8f95e7b68e86ea998d1f61b2c4e4dbbcbaeb308d0df80f7aca690054540e39d233b7218c9963d14f9ea625c3eaa26b45ab6936855119a0df047cde03d8f26847efc3e232a583f6cbc53475205b11c84795650539791ee3940aaa3bcd99b8563777719b5566975f2e0624fc96efb9e05561c3b14470615b7efbf0967dc38a169b6debf2c29cb413bb6f88f414027b298eec5f8591ff937ca28aa6cd79c0ad246bb414dddce0b7a3cf568c25df7c406760e5ba6e3e0bf6730d0c63164379aee6b45cafc9a0bf690b1ba95bf07b9b8f2d7f536a8cf7e11052b01f9edba80e519fe0b7eec6d82865ce8a151a0a173d6c71adf5254adf1e022e308dab9186a93c9f8b786600c285e501d26b461f43931c864596c5b02eaacc9a1764062e89117ec737569e1abca9e1a76df21b8e1a5f5e39bf56a747a8f5edea8d6444f2ab1002f17e07799823da28d0d9c0f386023a9df76da3cecfb0ad549e258de056409b9139df9775e75d7fb6370fafeafd74cc379cc8e4fcf63ebcbe3e92a7ca76b7d58e9ab924c4e3ec2e89fbd058b0266c073e4d3c66baf3c37dae822c5536fc639900f3ce84af5a7e742de01f99b57b19677db2af15d8b6061663bb9440cf4e01fb777b9fc45cd8294963dd87e365b8dd77093d1f3fc6ff08e098ac95c03f2578b4e4f47a56a84073b7484b307d8829605c56bb45f877c1317f0c26e53354d0925ef7cb97055eacf3435cf69a5c8a5fb6abc11b20919a2a3b6717ab3aa1cccf75eca697a1d03a3ef84c50962761a4d977fa44a587726a94860b85d054552ae3176b5360dd4b285086c53a500b9b13658714824ad7ab8b481c48a7348cdafdfe6280cbfa89944ea7b611abaf42aeef4a1056d64fb2fbd5abcecf14665c1cd0cec06cd752db24d4ef4f8b31d84ed5dfc62371affdec7457ec4a08191f1983dbb6347bd59acff1ff05116432eeaa65bb76ee08f24ebb155e45e27051fa01e245d5800da3c98fdcbc097884f239f234026faf31c8ba5416c5937addc954c4f2fb964e5f590ac4a7afa6f3f13988a6b873190f6f630296d887fd5278ac23964b968f13eae7156cdcdb31e4d4ccdd87b78033c1864238f2384bd987595f46c16b1565a70e522836d3b49c083be33e1d5459007c915f9acef6d18a68c3f33f35431a77428d48f8f94f49b2dd916fe3fd63f454d3775d9fe0f8483bd046b904f044fc46ad81a6e7c3082ee4952da96364b81849b526dc17d9546d61ab6b05ec6a76f65c6830c497d1331c98c988bf7444fc3999688d200787513e5036d9b23ac712b4dcc88d7f3dfd3c2db2d4be7ff232214c66cbca9f42d08365b008cf81961c3148b3e9816980101425f13e9bcadfadac4108d88f98d7a33d6da5864b6c4cb7c9027ed9f0569ac1f4eb59aa6f3663f438878ee97292d76b324ef103dd4c9ea0b693c318b67e9d2d3c09ffe6e506222293c962820255ff3ddc98c6294f62dbe882dbcee6b7ba2a9a0a372080a0707526eb3fcf6e471c1577580ca878d9072014022a67b820817b1fd67e6b8d6ec09ada2d6e4223e54182afc30ee2cc1374cdce00e9845f52924fbeb88b2f149238e5bfb3d0b4d3f82042977e7c447adc4c0450d2a378b268eb993251a1410cd32639f31563396eb74908a9d3a7ac0791150b50b10f1cd42bbf980f695fa380f2bd219d93763c19cfdee0a002260e54fca9b41f9f60612d202023b6d471854c84f5fa0252fd7e65a3ddf2790eb97827102a3130513634d35d41c7f68aba080ad945aa29f892d031880698a3e30a8342305054dfb6c201642bfda3321bd4fdcc0f27637c29fc36dc2ac0b64e302e97ac507a691b8580d855b41dfb2453afe99dafa457eba78f5615dc8e7cec91b4a81038b4e80624878e8e93c2dfc809295ac21285809ebd364e1f903bee790ec5578563726635dc0340f2567449fb4683c592b80fe973da0717139071cfc34e641712b2cb602325862ade40bb7f6cd8595c535174fd917d6cd25db005fc09008cf4a4af20e95753471deb5448e16392749618664e38b794ab7714788dbb46b7b65b146cec4b16df73d2b5198d201c970e8f985370a8d16853ffff95c43e82f8b45d2f715a493b1d2e580eab7003076af3aba9512723c1003add988177cf64bc2325995c6857a2569a188381b060ca8d9ad29d75e385add29d9f6af83651e2a5662277e1d90c5021a355e7fe58d551ddd46e1c32b7c559ef25439354ad346b4e11992b2576349b7a679d70f6c956e804bb30bf891546d4f1621e76607a0808127e41a4aadec06e8c3baad198d2cf0a53b4b20c52378d894a7898913ef9e326454d0c2c726ab2b08b418886b467f4ca8cd1830bcbca4f38880d5303c3a12432220731d57e7dd8a3b98758ec5b933eedd79746957c0fbf5045d709642aa277abf83eb30b93fdc6408d0a901decd79aa78d222b92035eec1ea9d68ac730567b2d8f59c5011f802c240b42d7890f18aca3d454e2caa95c161a325acf5e79520768f12975c57c59f94eb189ed4df7c6ebf95e38ad4a0957960c2290b37665b645e0ecba71f560941862fb33c0903bd8892250bc596373b933f617d27eec4a46fded99ce5a80d59a48ea787b676e38db3a473b9898719d834d2033f53cdab5db8259bf9a99c1f3ca49f1a514b6f43e90ec1f6379319b0503ab880a309e0f70ac76d7099acaaf49107bed2134af4e58554ed425cfc28739799e5c44ba69dea1916b8c320c3c7e5446da213c99a12447b4024301d0a374657a6d98a3a0056b959e146cb4a8cf30c1ec65b748d4f9d3cd89f3a229315c41d99645c8158d61eaf07983562a45f441c8a8332f127b17783f6553a2d7ca135f9d2fe970b7cd5b1e46b7680a474bf1919f9fda48409ea219d13ef1279669361c4b13c9d7f2a2fcce35d42db3221da9c4f97c70b76ce0d08670bf723d2b810c0e4b0c28a8a71d5a0fae473faaf53f0459b333b2d35c8e7b4663de19baeba687e805e3baf9addc2890a475570f9add6cdf28ed666de66bf0721bd5e34f7dc9024cd599899f26ef571505a1c2c2a8627f0ea51e38bb81080e3e580c3ea958aa3b3ebb93fcd5ddb984811edfd79f11d562f262521e5288c8f5211fae0921fb7b1c2b8622f2d04dfc3ffaef2b2e2f797f7e990a4b5c766f2578dbd3304f40430ec4e78899e8dfe16a9af32280b3ae1cdc0012ef44b4bec9b55d573cc91be7c9c733302d67b2849fd92c3b4d2a044dae9e5985e5707327412fcac71fc6e74f1badfe1c06c61e3d9d344a11a4b0e1ab601b48c2dde4dc3f6828a29e6473102dcb5b503be042fe55226a0a9e2da81a605b1228e2b1cbf4c29d8f7ae5e4b9fa4439d397603511b038a7f2f98bed44ddb654ea4ec6cbacd354fdd2ce504bdec2d18ebe809b9fa7a64fd16dc4963b5af0c7a0c8b1ac17426d2bf75fb94863477e76e8faf40a5b8f1297ee03705a1cef9f3d3a6229181fbce4e9409c23e745c8d62dc2cd6956e33ae9f859872ed9a4df013f9968a0e538351405d87ab2eba9f547d9a61cf4263fdf327ef342343f82d0b74ad80c71edd6d9923ea5f9e005530151c358c190286ecad6d8e7ba84e5d386c68a929f78bebb3f2c845b2e957c8e6064f52da80443660472140b3d81d4986d403dcb2b0e2b841f582f4157d5c8cae5a5f259ff003dda6ace43990279b8b11ce085dbfa7332b4a64e04820cc5d29dddcb8059256cc6647859555aa512cc4a0eaeb9c56b2fd7e53a15eda449f1678d029be95f407da965bc93bf431b05201dc8939be6841a649873f85f2c5318ecf9f9f5e98f169ff32fc9e492851ae585be663c268311e140a71136da6058f70b0b89c2c6a9fec95ebafc9d681ca3ded7d20448fec89c1df26bf449fdd266454f75f900e5ff27e2ce4cb6dd8e9bad1b11674f13d625d09536ae90024ce9a17b4ee4fa5a4cfec5c457e71205cd4a99a8866733c238332b5944a1a3ddd127168a47d61209c54b5494fd13e5a219c3c70c9d536358ba70ebf6580164981997e6294cdb897c4851fd63266558b511252a28a0b37067a6bdd0684571cd803f98ea9bc20ae09dbc96edb3b37d3a12e8a1ecc45f184012e636fe9a79c85842ad704dd0de652ce89b4d95be68ee8b3e90072a491a288c03900cf4e19f143631605ee0dae6e2fd7d4dc3657879d90434aa85fa23ec1ff0315688448eed22a712e270087beb5f91cd93917199ea04cd528d5b4951384f4a1fac666a268adad9c26c0971afdce521e8a39907fcaa4c779d0fedde0672a9a6bc3aba9b6e4ed45101c951f01774ee40ca5cb18be0f1248bc6a31bf4554f8d8d36096516a72d9f13141ff988768af3a4be50b02e5d295ac01037336aa09b47f8b222b946c326ee96e6559e71ca2833e3a851384532746f658ca8089ab45782f19aa86204df1d5e49e3062250564229eb6e42a8b3104c696f9e1297c83464daec37fb68cc1a6ac03a137b05e9a3fa2a8ae296f08b572f353be8556c2fdbe1fe60f63c4cf4abbbca6f65f57127c1d2f154b8671247041d3ddb6fbfa3ce7a26441edc72d4020037d25db360cd372dc71c3b42b932c076b3ccc6f431062df849543d3f2c47aa8c102f8cafa9d8a5c47b6061b718554cbf8a6aadc9ec638058d4e476301fe968111d1063a54c501466f7da1d7cb545adc6eba3b247332a66d195f29aedfd29d568d448035c20c59576972776f844af22769ffd5ed8ed08ce99df3163e5cf7675237579a7d23a065f71eb2984ae8ae3acd87ebd2190fbdbbd1166eed700969145279bdb708a3fa23ec84bb8eaf37ed57a612d5b88f98bb1a52454d9340021ef1b2cdf37a14f639f027a1a064ba340e6918233fa2cd4b43be2c649fb283515e6b63f87050ee3dbf3304d6b8621bcca602bebb06fcd6f7626fca50ac6f5d6c98105341cd93612ab0281a1fc4017f3aff664b5b796980b860bc8e1031770aadab41bb19a616bcf05de35139bb5dfc6235aa3b2abf9c0e5b8c932e161ac4bc29c0804e48ba1c5f73e0c93923b0be73464e3457ed9e9c3fa30ceebe402bc807588a770f1cd3a4ebeb58ee7beea77d9d5cf8c4d4626b745b047cbc168376728bce9258e352b15a6384abd7a2b9308766df75564d2b120158686a35437dec6c31dbc3f7ff6137eeda7c0b8d0ed118d167149624209b0d21a8883e840a003ad6522cf5b9d4fbe9ce121ee3fca90ac1929a261dd0e6ebf527e267178d0f8996257d5788a8e3eed6696c38be5ab45b403c61624b29124518a133a410dd97b2ba5d6224f6d2ccef6c115ca4d5f4264bb23facd700c4f67c8b852e95b68e2a89d3bdd5e95776d6015b367f1babe6bfb38113d641ad6f236a546c4adb446fdf4713c63d6482a3f391c5a67477929b3354e82b9d599713cfc5c7735613e622a5e6731a95b014e20f2055b00209709063e4721c267c3ab6eb0146a90dc07dd0c2d1ddcae7c684321ece3bc3c76ca5870defd708cb9e5218bf8147e84ebd16e2dc0285e26f84c8ad1ce882a5cd0012b151c895d2557b40ba2b972b937e9a3b380a9a424a2916b59df359d2027c457483fd1e84365fc1286fda4ec23b131e88ceec81156f26d60f3476ad8b09c3e0e33faf7e475d8d82ab4709627f179aae0b35752b24c22dc0f7e5ec3dd504cd0f93639328ac80560368d23614d02402fe7decf4904b4464f519fcb0a10984c6d9c29fd597849ffe6f1739d5d14ee47b43cd63d0a213ef99d87de2b3f183b517ce3d042f12f236fd0fccb121a310622ba03c8571e72de924d196483cf9b3a4f38c5c5dd5fe8233bb60af20f79ecfb25cbd2e0ef974c1445ed913ea8c53eb7aecd189acae0cddb32f417a81cba9f0d74e44c51b3cd130e6142b98d36d1e8ee27f44a4d09869afb379c55a0558f6bb5938b46e8900e5fbf373be14a8e84ad0b213b93fb617feef2769284cd494ac93dd4cc2f9b0812a76af746aa3553179f8d3c52a2779451fd99173e8b7a8b35464f0dead488ed941682dd7cd68661743aa6abdf7a7000c400aea5d07ba92e48712dae50339d648cce5802755cf6b0aaa94a98abd00f13a0551695a5b2d08618262861e8532bf43b73e97e6703bd7de444bf7a283cf87ccda10285677be3209774e9e937989321da88490dce94f000a93446c7501ad1203ab5b7c7e62fa2529e807be6e52a8dc40f3b212ad6cb744ed9456e79f4ddb4d7ef36c22c64d1a06b1585e461e88a9aa574c54be80950221492a3936af6254b028b3caeee2e4d68783e71de4b289492e1914a34b138041c8ada2dd3646219c7df4f8444b7c4a0cf0a39bba3cef157b0393ed33363f99d3b53ec0a00c4002308fd4af885dad42d3b5f4fa716c356e01dbff813b3f71c7a6db417c6f6b6139141826bd2e722b9659fed1ba45134e72ca37693bd927bda2838ad880d80feca6686eb0cd18b031d8f09a26d5ddd7d54e61922acffe5831cf8b06ea5a305bb536f1b88b79fe669c587fa0fc8fc8bdf1f5c06997175ebe3e9569d5a47f4bab4ce806bf204fca750d4ed89d1a65982b87c792f2265b3d87941496dfc07baa822ee7699e97140a70456bdf2d01e55d174d599d0c04cbf42d59396ac059786ab38db9c0aba3db70dcb4bbd02797501e1abe266bab2bcb2fc6989d2d50e918191c7741e69b772b252eca04f50488cc96e7f25b7e34182589bf38038748989519d8df8efa8e5e8ee2e56707a65aed6985dbacc5e1d0fd423c90c00d7ef1118de45f94903f6131066566785fbb86ef6ca9c4b712eb6f5a18cd87ef08396ffb0d440383199645eac5e0f59fbd742e391924265114e97ad24f4689049919f51f599798c94ca96cd970c764844370d9d9b2a89b3ac8a67855862b152e2d131b5124334ff29195caff14725ed06e61a9998b35faa4826fe43a162e9c3316e4dd5090b37cfe9966e937c3d33d31c44f9ac72ee27468016e5a4f587fd8ecf8ca7c1977d33730f579500418b554d015db37579b353fd3c1780d4f2b580d14cc591925f447f47899c30172bed4a17bc436967f8224ef3ac54aba0261387d3dcb3906d1fded9cb1eacf3d96dae59a581b1fcbdc16c6f242b61e8b976e9558a03829660f2b25341c04204d373b0b3aaf29c5e49b79703b7ae79bce6fc26c672f2b94c1817ebcb26726316f165629f4eda038501a8f71d38462dcc6572509c2ea53298801800ea0e1f3559a89a3a9f0c9485e11cbb0f1b866ec573892a078d6d7fb8668b4977751bfd34e93a6fba6634f4d4e45488e95a4666bdc277d5b7f9efc4e7f65c07802d300b6228cfa5635389107c620cf1e2d8ec4473374de50d70e178e02de981f3ca869513777b2fa9423dc6f3fcd6d95cf60318371d8b57d55275510b220be2dd4185fee13eb6c91da97daaa8333ca0dcd0f3ca5482f4e4f99b4320b714e41856d867b28bab5c5c4fe3c8d6a7359a81a9e74dd33a35d3169c06947ea8e6ed2926c75b150c0fdd94779fa343f931988054ee78edf719138472359a217be1067bbf6dd2df8d73f258ccb908088c60d157fe27f68dbc21d4701827da1eed17ecce6bd9de03c71547f23a8508609196653234381d83a01e9b09fb3b11ea01a6d2579a99ce023336603e4046e6d11a53f2750444e870a45f9e8e1e61c04f748e9c8aa1e1df718bfb3279cadaf8328ace49448076d1b1d61366273e6344e21df05ccae6d5b1dbd9c28b3d5510a4250f254806ae832139a76a7663cdf473abafc75f881ca570f4a457f95ef464e7acaf3d8f9eec871129bd4b1313d4a1584f360e2fbe07f17c50e5ab54e158e556cef835253ce7ec6f3cc6489315d34342ad7627ec1e1bd77e3a5c47a7208f13c7108808fddb1a7e7a234f175eae58925b452a324ff0c5897d6d9211bc86f48e6dc7fffc192918a7224cc3fb6f88af75e6e54ea1dd59dac0c74b78c9c87e05229b2407ba30f2277860d62aa7ed03c509e4ddf890a947548c7d4ba5885a05e157796e1ce5f565b9d1554ccc1559a49f3d731eed6a1959df1a7ae3960b7fcd2d5ee866e71668f87b0171c346c496ea4e0ad2effb785a5efebc119aadf1834c4c5dadbbaea86d832bf8a7c94a43230f477ef0c3cf2945fec844db9d8496c4ab3da3574f31be7b91dfd92d118fdffd237cc49b8e6f4d6b7bc4f3db750daffb7a909c42c6d0b8cc3d14354aec85ac0acb95121a00e344d8183ce85044b69818d505acb58406147b7b2141eb709c77edff7f014ad7408e9a9174cc0c9407e780c6e1f3760a123c38f1b2a84c8e65f36cc8caafa6fc084c53a65dff5fb2c2e1da85008d3207d36b44982d0e1571c06c04af6ce0cb4599a18460ca43516fa12a0dc04150e0327f211c167900054b651535c0e4affccfce8b831011d1395f410b845bbfa40111c454aff7e4795f0628e7f0fc8aa10d617474961447b6153357a4959becbdbf4971df4e0be400017cf81dc92522aaad06295b48564c56da8e8f6b4b2ec2ef0b9bbe66308656b6036f459da2645e0dc1b95967e3a31f343515a8becd92d4843fa5416658b737b7b91be15f1051556087fd24b8cca7c5634bec050e6cd67c675445317a8bbf14d3a59142389b5c26d7924ad394b5fc5e1a574ae9b607ea9052af89e5914aecbad81919e9034de7a874e1ffc67da69c3016e197ea8428f354303072132b883e1dfb01640920556618c79f962a9995b9d9397a00f1442123257411eac6fc4602911ddb8ff1c73f64aabf96db9a0b6bb777205063e4afdec6de796f5155b9b26b1e0c2556402c0410dc8812193d003ae735b9f94d8fa2c6bf29a5da4c4edf87556daa48b4ecadb83a1cdb95d0a10343ce88939975b0d36064dd4afa9be9c3f006bf30fb50f7d0af4bc13a76d81f311b4ed4312d8737160de0b55ede42542245c862225144b1819b4b250b3b81fc4c6da971927e45203e52a1a943ec3d1d4083ff43bcfd287c763f34fb1759c098bba7ea3979b7e54680f24dc8d46ab86aaba432cb2efe884aa243d873aa99aa027fe9343593517133c96925589fc0fd7e7ec64db80937941f971f2f4fda71f73a7ec2f3acec80fd45c57d32d9fcfc2d7d8f8d6a41db0a1156bef801d0f1698ad9d75982b3e4cbf4e44647c911941cec0907ea812f515989694d8b82a73884260f6ee6edfed659ae49da082bcbb5ac402d9c878a75fb6a47f1a09b224052692bd7ffa23ea9500e14e00ce12f5d64a994d1077387be18bf338ebd62b13819a507d98b269e9ff738c7c6687c8a9de7c072a2a83561e8489f1b1b38dd7bfaef92e01825f665bb5e3aa759c8545677d54b28419c81afed76af0c2a3df80073d5075a86c063f4e11ddf85fd8f1c4bae891b10ee753787edbf536a31c08bf318f2f539333fdf80818b14e0a819ef98e420280e69afb10a302a751cb4ce088239d167fb62bca8b0fc981eabf7dfb02ecc23b978ee5d5f3224eb75a7d910aac641a44f73afed80d5182ffc94dcd2f00379e13704f838dff5ddf185cf2e6e5a3bf9c6ef5aaf406ac2697b40e2f21a665eef5e3081f80f7bf15d6dff6a24481ea6c498d184fa38d0b8956a17ab7cabbbca8a7391389726f7764ced9d1a913922565eefcf8fabaea23b545aa2a50e1054e919383f0fbe16330ff94b0208ec677808c8ff96fa4b235b99a9324ceea0ee2e33a278a082ff204820e1badcc51d75e45fff795c71de8e2c4922f782c63941c194eebc3e767ac5feccdb5cefd3326f55093105ca2e36a1bc3a3ce0fdb239d7c1614abde3144ce5aa1ae820db8292cf8f15aa7b2230e93b3c3bdef3572040d5d16f6c1bc675030da4cce916eb240f2bc3382b1dd8199e9c696d5219d0780e73eedc24f947547b9cc40f6445118fca77bdca2c4f77e800568cbf79290db5251190e0e4b953e71e780747fe3827526375fe94acbdf1e026f3c76d460287b83ad9718bb95dac195eeb0f4826709e2c901fbcbb903f6b2a4ae0f9e5a9be32f6553b92a44fe078d37310c1bf1a0f65e0a1697434eb94785b7f1644038381c77b329f11261638545691c45fceabbbc8662037f503e789a24c55c20439238412d0f5575a9c6a2fc2611775afe782d0f17c42ee5c09c4275ce1cf2ee75a2ebb3e5444894e9fb671224ad2951d085dd36bf4bf40768aa3ecf1c0d13b1fe7f19390366cf8f03daaf49d2dba01851d3f199bb075e0e7ac3937534c1f0d0a859170f2587426cc612df228aaff805a314db24f2479aa442533ef31686ceb61dedd57f9edcec5cc13dd45b0383f059efd7848ef35340bbb043a4ae904e8150ca788c3c12c6bcca33fa24ba581b458e0f51799356f31e96a5368e6902d9f43ca9af4d2e539cdd9b5adb2e39ed9ddfe5f1b73809375282eaa4a3136610276ce2318eeeab266ff15e908e971dfb202406383e665fe7c6ed612e7cc87610bc45386f99c4846a62422ba863bed70072f41f23864791f2852e425a2f36edc99d0d382231f247635db084ff9039104161dafc9370dec0216ece1a8024c27ac18a6520e310dd80c2f7b572184b33565a48fb7c24e5ec4a9c9f05a6aa62498c17c6408dd1a80f3d0585fb5567edf280860525ef78bfa52f8e0cc27e03cbab6719fa4391a8ea05f99ec2d92558e22a28c06c2f81ccacaa8b5480455ec943a6ed7433d88e2f5c1cb1b1d1b2682575084c7081b6611579b36fb612bdec2af5ab696b501da53791064b3bbca6f17ae210fb73924991557c343f18dac4bd5e15bfdee856977fe12e6989bb16b6a936940321c0491e611339b40703811a6af24ddea41597c96b6126494f7375f28db63935280bd5eabdaf9fc39f3e813aa3bb77cefa78650c4969ee23abe589616b6cf719221c827dbf6e4006d19eaf840a37cb6080e15ab02b82e7bbb7dbf12b92c41f38878dcbe365c259014b6009a5c46ac7d407640fcfc8976f57d3985391138794fe777b6a335cde71a47b035d921af36547abad88bef679b7cf740085dc5f84b4f619833fb674c55a400315727f446453c2f1df9b8318d05e28a53a1f3b127793c39f09a804bcd513ea8f0e02885e17ad42dea12aafb6146bb3308d17094233311678a49436402115d247ab67ae8c2a9cb1f0d48fdd10cdba80f208792e56da101ad1da44242a6215d82a2c0389ce32de726d2f11c0a7d2059b66a74cfff2182a4e2c561f20a24d9f86873e0519373885c36be9995f00a9353e79a43777d205c93faa627a8470efba930bb3179f4fe92bc96969e5f8f543fa9b208eeb6fbbdb16cdb3bf94cc60ad53fb203010d964615816106238383b0e995675b2c6bb68dcb4d86b5f91483dfb96990d3429f4e7c8f30a94f067d46e2eee12de4a15ff7674c2e7575405fe86d5336b089b88d17587684b0d158a4fd773cbb2c3c9365da29886fe9ba240bbbb910cbe9b1e84dd9ccc42e31d0da06d583c4de724cf380982bb053e8ad035fcbe6ea00247d5c0ac829a12c02413ea4f6a84ea6166f7ea5394d38f126fd675e563fd437cacbcc35a0887535e518dd813d84b87f5b70598abe6f61c15a0c462e7a00e19d248bac5eb7b3582a59d19ae1ac8264b59f01e85aa4b7089e4548d84aa46f82b0aa05d7712ef870ee461b3728305511db11a2ff6359915b2af92b9a9b963547180d3b20c5191ba8221b1e8042250e032318405492a2d6f32e1f86f452957b7c2db57eea2fc4ebecd9b07f4a71ee172004946674dfc5e2630bfafdba3d9d8bcc284a9be24816071006bc31a23a5a56a746bc0414da85325caaf9b799d7a5b05ebf220078d689cf22b728b70c392ab8eb0fcb7994807d84d16003ed693538f467096ee71702747d77c078cd191e0abdf89cfc8a22f8f8cbde194b119a3f5345e0da81d23cb15dfc213d2ec6656e82c7b130491f87cd66fea4e4d20824dc077544eec441bdedc73f7893a0888beba05e57d035ff90cfae1dee01d6677d5ecedb4348582ae8c34549491c0700f63d0916a3b2c40ac9ecd52e2298d596f252e41edeb31ee9fda2fd644c2a955b1e8e5519bff07c2de59d735c83250c6cdef18aa63b6955807b61b7ab13d6524c41f83889f30cc9f649c5e282a73a37cd5364326159b355551518c0f012c50673b958a64462ae6efee6294c3ea171ed5880e13b39d50f23e979fe56c310c9989db18224cf55816fce6e95f4e235b4b72afd678a00f0cbe061022e2589c12e6f80379dd5634f4b81924b161953c75416504ccd6d2472d9f22cf04c768bc1966fa6891ee68cedef517c48a4deee22f793d2e0259678e860914d90cfe4e40bf918b3a2f0a368f88a2b4fb352298fed9425e61640b1a6bf2fce1b27ee30d6dd9ca971126711a6d615c0db959aac59bad487236dfa74ad946b8dde2a88b11693274226974bf30562ae6b9a78ab9d622facdc128f51281d7e172d883111d38bf3adb281a84d974fbd1e26ffdf6fbe864e00d260f84d178f7ad1ecc02d4b89916518b78beac3f08867850780552caf28651f949ed067d4a430a53c094a785b6e35951801c896551d6be6c5305d6a0024490ea5bba0a28d62ab40c659f466359a757006f05f4b59729056390593818f127952e409353eeb7357c3835a2494883edaaf054ea500254985b4bd9b79cc0e63d80848c4720c175fa678912c342d480e027f140517a8bb16d69ce2fced9ecd473565657aa48b4163f2300a6ecffb14ff5eaf226b0f80cfeafb63f0fb01d56b9df87efe595d2a44cfe3160c9c932e63ddf98a1457afcbfd453f6deea589f2027d45c3a59320ad7788396c2bf572b68c2fe0dee0e6d736113b7d1240d8c74fd20d8fd432db190c6a8584db0bfa403f614550ad1eb11353ea544cbcb262e0b2552e8fa0d4693151a9f07a110045145676887e7b1806a67729a0b6d32e3da7999bd8fbdbc479470d885c9fded643532f9b9553ae9aa94a454cbfe257ac17a57da6e28d0b38013f700dd396f077969308393aaea1b9b36fa2567696a2209eb74e98d16f533a5515a79f4f292b0f73ede82b327679f1f5a000000\";\n        uint256 len = image_.length + 1;\n        require(len <= 24576, \"image too big\");\n        bytes memory code = abi.encodePacked(hex\"61\", uint16(len), hex\"80600c6000396000f300\", image_);\n        address a;\n        assembly {\n            a := create(0, add(code, 32), mload(code))\n        }\n        require(a != address(0), \"image store failed\");\n        IMAGE = a;\n        _setDefaultRoyalty(initialOwner, 500); // 5%\n    }\n\n    /// @notice How many of `qty` mints would be free for this wallet right now.\n    function freeFor(address wallet, uint256 qty) public view returns (uint256 n) {\n        uint256 w = FREE_PER_WALLET - freeUsed[wallet];\n        uint256 p = FREE_SUPPLY - freeClaimed;\n        n = w < p ? w : p;\n        if (qty < n) n = qty;\n    }\n\n    /// @notice Free mints this wallet still has (limited by the remaining free pool).\n    function freeLeft(address wallet) external view returns (uint256) {\n        return freeFor(wallet, FREE_PER_WALLET);\n    }\n\n    /// @notice Exact BNB (wei) a wallet must send to mint qty.\n    function quote(address wallet, uint256 qty) public view returns (uint256) {\n        return (qty - freeFor(wallet, qty)) * PRICE;\n    }\n\n    function mint(uint256 qty) external payable {\n        if (msg.sender != tx.origin) revert OnlyWallets();\n        if (!mintOpen) revert MintClosed();\n        if (qty == 0) revert BadQuantity();\n        if (totalSupply + qty > MAX_SUPPLY) revert SoldOut();\n        if (mintedBy[msg.sender] + qty > MAX_PER_WALLET) revert WalletLimit();\n        string memory handle;\n        try AGENT_ID.handleOf(msg.sender) returns (string memory h) {\n            handle = h;\n        } catch {\n            revert NoAgentId();\n        }\n        if (bytes(handle).length == 0) revert NoAgentId();\n        uint256 free = freeFor(msg.sender, qty);\n        if (msg.value != (qty - free) * PRICE) revert WrongPayment();\n\n        if (free > 0) {\n            freeUsed[msg.sender] += free;\n            freeClaimed += free;\n        }\n        mintedBy[msg.sender] += qty;\n        for (uint256 i; i < qty; ++i) {\n            uint256 id = ++totalSupply;\n            _mint(msg.sender, id);\n            emit Launched(msg.sender, id, handle);\n        }\n    }\n\n    // ---------------- on-chain art ----------------\n\n    function _seed(uint256 id) internal pure returns (uint256) {\n        return uint256(keccak256(abi.encodePacked(\"Neonkoi\", id)));\n    }\n\n    function _r(uint256 s, uint256 i) internal pure returns (uint256) {\n        return uint256(keccak256(abi.encodePacked(s, i)));\n    }\n\n    /// @dev HSL (h 0-359, s and l 0-100) to an rgb() string, which every SVG renderer reads.\n    function _hsl(uint256 h, uint256 s, uint256 l) internal pure returns (string memory) {\n        h %= 360;\n        int256 c = (100 - _abs(int256(2 * l) - 100)) * int256(s) * 255 / 10000;\n        int256 x = c * (60 - _abs(int256(h % 120) - 60)) / 60;\n        int256 m = int256(l) * 255 / 100 - c / 2;\n        int256 r; int256 g; int256 b;\n        if (h < 60) (r, g, b) = (c, x, 0);\n        else if (h < 120) (r, g, b) = (x, c, 0);\n        else if (h < 180) (r, g, b) = (0, c, x);\n        else if (h < 240) (r, g, b) = (0, x, c);\n        else if (h < 300) (r, g, b) = (x, 0, c);\n        else (r, g, b) = (c, 0, x);\n        return string.concat(\"rgb(\", _u(r + m), \",\", _u(g + m), \",\", _u(b + m), \")\");\n    }\n\n    function _abs(int256 v) internal pure returns (int256) {\n        return v < 0 ? -v : v;\n    }\n\n    function _u(int256 v) internal pure returns (string memory) {\n        if (v < 0) v = 0;\n        if (v > 255) v = 255;\n        return uint256(v).toString();\n    }\n\n    function _pick(string[4] memory names, uint256 r) internal pure returns (string memory) {\n        return names[r % 4];\n    }\n\n    function _T1() internal pure returns (string[4] memory) {\n        return [\"Cyber koi girl\", \"Cyber koi girl\", \"Cyber koi girl\", \"Cyber koi girl\"];\n    }\n    function _T2() internal pure returns (string[4] memory) {\n        return [\"Techwear jacket\", \"Techwear jacket\", \"Techwear jacket\", \"Techwear jacket\"];\n    }\n    function _T3() internal pure returns (string[4] memory) {\n        return [\"Magenta cyan rim light\", \"Magenta cyan rim light\", \"Magenta cyan rim light\", \"Magenta cyan rim light\"];\n    }\n    function _T4() internal pure returns (string[4] memory) {\n        return [\"Rainy neon city\", \"Rainy neon city\", \"Rainy neon city\", \"Rainy neon city\"];\n    }\n\n\n    /// @notice Raw artwork bytes read from the IMAGE data contract.\n    function _img() internal view returns (bytes memory b) {\n        address a = IMAGE;\n        uint256 n = a.code.length - 1;\n        b = new bytes(n);\n        assembly {\n            extcodecopy(a, add(b, 32), 1, n)\n        }\n    }\n\n    function _svg(uint256) internal view returns (string memory) {\n        return string.concat('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 400 400\"><image width=\"400\" height=\"400\" href=\"data:image/webp;base64,', Base64.encode(_img()), '\"/></svg>');\n    }\n\n    function _attributes(uint256 s) internal pure returns (string memory) {\n        return string.concat(\n            '[{\"trait_type\":\"Character\",\"value\":\"', _pick(_T1(), s), '\"},',\n            '{\"trait_type\":\"Outfit\",\"value\":\"', _pick(_T2(), s >> 8), '\"},',\n            '{\"trait_type\":\"Light\",\"value\":\"', _pick(_T3(), s >> 16), '\"},',\n            '{\"trait_type\":\"Background\",\"value\":\"', _pick(_T4(), s >> 80), '\"}]'\n        );\n    }\n\n    /// @notice The token's SVG image.\n    function image(uint256 id) public view returns (string memory) {\n        _requireOwned(id);\n        return _svg(_seed(id));\n    }\n\n    function tokenURI(uint256 id) public view override returns (string memory) {\n        _requireOwned(id);\n        uint256 s = _seed(id);\n        string memory json = string.concat(\n            '{\"name\":\"Neonkoi #', id.toString(),\n            '\",\"description\":\"Neonkoi is 1331 Cyber koi girl with glowing orange scales and cyan visor in a rainy neon city. Art generated fully on-chain on BNB Chain. Minted by .ai Agent ID holders.\",',\n            '\"image\":\"data:image/svg+xml;base64,', Base64.encode(bytes(_svg(s))),\n            '\",\"attributes\":', _attributes(s), '}'\n        );\n        return string.concat(\"data:application/json;base64,\", Base64.encode(bytes(json)));\n    }\n\n    /// @notice Collection-level metadata for marketplaces.\n    function contractURI() external pure returns (string memory) {\n        string memory json = string.concat(\n            '{\"name\":\"Neonkoi\",\"description\":\"Neonkoi is 1331 Cyber koi girl with glowing orange scales and cyan visor in a rainy neon city. Art generated fully on-chain on BNB Chain. Mint is gated to .ai Agent ID holders.\",',\n            '\"seller_fee_basis_points\":500}'\n        );\n        return string.concat(\"data:application/json;base64,\", Base64.encode(bytes(json)));\n    }\n\n    // ---------------- owner ----------------\n\n    function setMintOpen(bool open) external onlyOwner {\n        mintOpen = open;\n    }\n\n    function setRoyalty(address receiver, uint96 feeBps) external onlyOwner {\n        _setDefaultRoyalty(receiver, feeBps);\n    }\n\n    function withdraw() external onlyOwner {\n        (bool ok,) = owner().call{value: address(this).balance}(\"\");\n        if (!ok) revert WithdrawFailed();\n    }\n\n    function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC2981) returns (bool) {\n        return super.supportsInterface(interfaceId);\n    }\n}"}},"abi":[{"type":"constructor","inputs":[{"name":"initialOwner","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"BadQuantity","type":"error","inputs":[]},{"name":"ERC2981InvalidDefaultRoyalty","type":"error","inputs":[{"name":"numerator","type":"uint256","internalType":"uint256"},{"name":"denominator","type":"uint256","internalType":"uint256"}]},{"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"name":"ERC2981InvalidTokenRoyalty","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"numerator","type":"uint256","internalType":"uint256"},{"name":"denominator","type":"uint256","internalType":"uint256"}]},{"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"receiver","type":"address","internalType":"address"}]},{"name":"ERC721IncorrectOwner","type":"error","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"owner","type":"address","internalType":"address"}]},{"name":"ERC721InsufficientApproval","type":"error","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"ERC721InvalidApprover","type":"error","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"name":"ERC721InvalidOperator","type":"error","inputs":[{"name":"operator","type":"address","internalType":"address"}]},{"name":"ERC721InvalidOwner","type":"error","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"name":"ERC721InvalidReceiver","type":"error","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"name":"ERC721InvalidSender","type":"error","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"name":"ERC721NonexistentToken","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"MintClosed","type":"error","inputs":[]},{"name":"NoAgentId","type":"error","inputs":[]},{"name":"OnlyWallets","type":"error","inputs":[]},{"name":"OwnableInvalidOwner","type":"error","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"name":"OwnableUnauthorizedAccount","type":"error","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"name":"SoldOut","type":"error","inputs":[]},{"name":"WalletLimit","type":"error","inputs":[]},{"name":"WithdrawFailed","type":"error","inputs":[]},{"name":"WrongPayment","type":"error","inputs":[]},{"name":"Approval","type":"event","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"ApprovalForAll","type":"event","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"Launched","type":"event","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"agent","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"name":"OwnershipTransferred","type":"event","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"Transfer","type":"event","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"AGENT_ID","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentIdRegistry"}],"stateMutability":"view"},{"name":"FREE_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"FREE_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"IMAGE","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"MAX_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PRICE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"approve","type":"function","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"balanceOf","type":"function","inputs":[{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"contractURI","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"name":"freeClaimed","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeFor","type":"function","inputs":[{"name":"wallet","type":"address","internalType":"address"},{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"n","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeLeft","type":"function","inputs":[{"name":"wallet","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeUsed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"getApproved","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"image","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"isApprovedForAll","type":"function","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"name":"mintOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mintedBy","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"owner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"ownerOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"quote","type":"function","inputs":[{"name":"wallet","type":"address","internalType":"address"},{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"renounceOwnership","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"royaltyInfo","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"salePrice","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setApprovalForAll","type":"function","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMintOpen","type":"function","inputs":[{"name":"open","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setRoyalty","type":"function","inputs":[{"name":"receiver","type":"address","internalType":"address"},{"name":"feeBps","type":"uint96","internalType":"uint96"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"symbol","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"tokenURI","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"totalSupply","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"transferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"transferOwnership","type":"function","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"withdraw","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"matchId":"58035365","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-02T03:54:12Z","match":"exact_match","chainId":"56","address":"0x3ADfBBa26d3674477aA21B0CF2E4C2BC643ff85b"}