{"sources":{"Cyberlynx.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: Cyberlynx.sol\ninterface IAgentIdRegistry {\n    function handleOf(address wallet) external view returns (string memory);\n}\n\n/// @title Cyberlynx - 3223 Cyber lynx girl with glowing pink ears and teal 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 310 free pool lasts (gas only).\n/// Every other mint costs 0.00005 BNB. Max 50 per wallet, 3223 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 Cyberlynx is ERC721, ERC2981, Ownable {\n    using Strings for uint256;\n\n    IAgentIdRegistry public constant AGENT_ID = IAgentIdRegistry(0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F);\n    uint256 public constant MAX_SUPPLY = 3223;\n    uint256 public constant FREE_SUPPLY = 310;\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(\"Cyberlynx\", \"CYBERLYNX\") Ownable(initialOwner) {\n        bytes memory image_ = hex\"52494646084a00005745425056503820fc490000907b019d012a900190013eed62a84ea9a523a32dd6cd79301d89686b49841741f1cbfa9a43a2f39df296d019d6fedc87f30cebfaefd93268825d977d3e7f61f51ffee3d207cd5f9ad7a88fee9e955e98beb61fe0bd5efa67ffb2e3b6cb05b5d8cfc74a2adcf7f5abddefecbc6651dd78b4ad3a6cfddfa21bff2f39005153315bd146c3b2e49ef7253fc080581dd77eb39e6118c317af1fe0a52f1467dd4daf32bc0bfa09451969da12a218f94f768f94455d8805cf14673d7cd2bb30066bd2c3c14159f8ecd713bd3d2e578baa290000506a47d53d9860126826031a88c642580b75e4eef467edaeed2a1dde3bf14f4978aaf98927411dd738d5f8f23b56b865198b438469e8fbeb48fd58d2fc1fc0906fcabace1587b9336f579284aed258944e3a2adfac9ae5681b0563af16211660f80cee7ca344f4eb9e124bae8e6a3a2ee15d126eca0163c9bc7d002a2171833e0835a42231abe9971a43a39883bfe4bfd6d046fa88580dc3607f4ccef6f703866de02b222a6c510a2c017c7fb4de19f293046f09ec6b24dae2cbec8eddb45e818a1860edeea5eb2f0f0a4f2f36405d533de0b70e12cd8bcba54afc407263ab29f06cc250e0f188418e2df003b6aa93be15f72011851ecfb8b7113376b4118a30ad8b0fc8d17f9d76f38a5afbbde5be05f42b598bd7710ec1e22b9f22f0e8af1583e86d592b937cf788e171924ec97e720f48d60361e966e446a6b335232c76e02efcc0767509b85df35c8faf5f9c6002ecaa4806541e7bb9bb1f0db8c261615ffd40ce2cafdc500bf81324511eb58e1439d7a95644a06d84c7ea1902e6a94f63a4df1780f76c91f8cda84b694a4bdc1d1480fe031c600072f3562892629990960c048f5d9d3501879e77e6541b275288f577f6a556b0487bd8baf7e5199e4fbe585dde8e88c3f13588f0c46a5f8c1faa6cf6411d663c5685bfee254c42e4773ed7d6578727c5bcc31d8ed1146f375249824b3679a796613ce054692a63e5a43af1ccc1a170fe581b1d513d3d5b0d9e3c18eb8bbaf69c0762fac3f4ef0163e8a06d3bd99577a588dd92190ed2db3f9cd6f94eac1f82f100549f464067709ff44e1ff4cad829792e8e0e23c020265c797b69f61acd4fe9511f82df07866300c3d8a74611147b80b880d96253c00a9cb1fd3619fd61b0ea4d9b3414df9c805d44754642c1d94940e6a91f766d348e08c2494c8745f1810504d7666c0295a86b125687df2bd917dded830a1fb75d8272d73a20196b0eedcde74340c2d88bc0b787e0a18a3101cbb5bc7bbbe296ffb60cbb904c90471db1b8550aa296b253afabd20a59b135717e691f7fc95903f6cf28413bb34e6fd7c4e391ee434bb6bcd2f780f6bc2072be30df4211b507d065aec20f21b514fa54faac67565a090415e0aa546e2d5bd55fc66eafdf19fc0d26e2f420a2f001ba068362d45a00921e1175448057355afdefab2c00245f6597724f6cfed9c32be12557b8480154c96a5c2f5f9811034ebc4839ec8d2382aef63f0828c28b956d6be2d957eeac16a89f04b81e7c5f342c7ab2fa81e3e720776ed0aa711781ff08e35212b03c2210ab9ece3b11d76f8f88a20b07869995a161c4b6299f7ee1cc685a4e3ffb5e4177c44b4c386b9d57680e4acf3384b790df6466e6f1934c5e3c70f5b04daac37c6b2c88798511deb81532d356370a9563e73325541342ddd698e06ca16fbb87843dc2b05c9c92b8ff7bf4458e58960a90b2e2a68528dfa26e7987fbfa69128719284618d186c27f6c3ac3b51497cd13896fdb74eed1c9b9d5f27cb5f72266ebfd2c4067be5a4eb5c1488c1e4e69d21e345715ef56a9d26e124c125bb474e33641521e4119a0e3cfe46d76b61124a9e6bdb72d36fda79d40e21deb04d6f5fc1c5148ab675c293557af471f670938326c7129b2cdc506421fe8d5d1aecbd0c763c6fd322ef2c16fd0521940ad25a88c713927e2bd61799ed8b51406c506bb3f95c539de431302046a78ec2d800fb6e6db6fb63a238bab3d2116e7b0aaf8f9a167be85687ebb56b318cf25c8e0490b2b270d394179ca65efac024ac78d0558704a87ba340866eee22a26dfde872ba4518da69ef8d0c749de15a3bdcc9294d629b0adead46ccefa699b468a7aee41021a637fc7d649dec55945d2a7a5f301454fc5edcde514e27c7660926e74c4b05b591f0704b7facf14d43a277ebbbee489fdd7cf03bceca08bc6f5c17b607434d70d83297c2dd0c4ff8f201cf02063c8c0678f4eb0db8fbb6d42d8ca5ec97b0c298d9fe6213d47cff99f850224daddd7426bf18801261bf31a3c5bd3797ba241e2e913670e9eee1736f3683b9740072b02975c3c7cb4e09dbd2b0013398ae83f265c2356e75bc4ffad846e8c45a2ae7ed922194694ba593df6271ec4cbef05121ab4a21db0a1a057c8142bec340bd747667536eaf2688fc950949d27575367932ad7edc1183b28f99f41f19086e6467824ce7cc40d31445bdebf474f23ab377d24a1a876dd2b6f0a99fc8030ec82da6ad1730c47ed6c10f09924ac5d372cab7bc6eabbe75c988a5bade33a798f59a35e6fd1e0e918ce5b35384aa591ac71c65712e5daa8da533380ef9cfd0ecdaf282269e4f2c1bce90376ef4e82166861d016c08c197fddd70bac41837e16369c993584b970519d2ac11788168058173c162884ff937934cc5b01669d22005680ff8492323501e8f36cb7575a94739cb3100d31f36932d6cf45b7798055ce47133022e125daef209e3c3037f14027667a42b9cffb400deec4eb7a0b1a41d02e6d89c885c08a3f3222c764d44e518597bd98ec8af7a40736f10d515d8b94d468b2f89816a5fb5ace85bdc62d717c8727487a911a226130e71f1125ab66096600858f12964fed1cf06f5145d8b0ef0aa2d33cb2aac6ad9bca1d2fa07725a1f92080b1cce609f11850684b917e7532b8d5cbe19bc2c573beec26bbe34b6e8b4adcb70cd4e3c84d5e741ae49cca3fb380bc6eb5454ccb139c3a4fbdc0be50b27aadb1fcf35065a47aa1c72c543f345e89d593bab34a8f5bfaedc5650f06f8373f5715211063e37567ef76781313e118c6271f91de15d8af50e677142dbf158a4351fe8da87bf89115558c2278103581ce3938651c59a57bb7bf8e2d586f253a9557eb1f7aaffbabd6bfbde90c4b6f4065a1cee672bd19564a9963464f9b158835ff56819eee2371b93a5eda92b05f2bf136df6d6ac570a3fb2eef93091aec4f9e03df626255d89354ef7b1a9a3d56c2ed938cbb9f6c0f3ab0e112a5942ffacd8f0f77d69c02513117def1b8fd51c079dbf47454b3467eefb96198b7a4a8705933864af78ad866fccbcb6faa5c780a25a0fce5c2619c045de854bfaa13846a360a72b41f30a7e9aa2ec721c0df09a9079b29104d522028e06f2e72832537a6650e79aba6faa8cabd82c944a645479a526251c4c8b3a3e168da969e355ce95e25292f159a382e60d815d0d721890eb921927e0be2243bff0f3605251effbbe496ab4df959cad5dd3529bab21f07105f363bee52d64461a512d30e95edd4d21543891a84de357e62c32d3a3908924d8a44d2c77f5c2dc8e06b25512c7fa00f2f1757e77a98db7eeca6cc04950fb94108716e28f7c03831f76e3f08830e4c9fd64474c8e82264ec5c46c35c383438296b1e6a8b3b9a73a239e884ca74b5afd54de0db0e67a6d841c14f6f667171a441c0d0f28837c365c2adeb45a313d67cd0709f23ef86d9aa4f02ce111855c3e9f6cc4c340eb4dede3c976e8b10bcbc1594ac4fa2175c8e470c48c094d22c56fad417a0e77781051a9279719149db5feddb667ac0ea40c9fb06386952b113202a294a6f67f275b449289f891ec13b03303c6386dd68d424d5451391a2dfbeceb97f87ebff913f8cc730a2e8df5881a3f7b798c7e30d6c383a076d38f799e00ebc74fc276e4ce0ca4903696b354b31b71053574d6564f3df4d5987ab2ddfdb1bae1ffcb01e3d8b364537f0c254b55c295c4e15c5e8d4db59632588fc2059af19ee357084a451fe08039b1f0d7c872a1e43f94e59b7d68259d3b8d2ed3596bf4d8fb888067703d6b401d4d7b3db66cc3e1529aec8ba542ea732f03ff2bea0f4d6b31796ee17d7e78990b437bafec151888f39cc9511450cc74f52566fd333f4c587ef089b608785757bdcf111122ef04054c558cf5511e852d104d1a7cfb876763ecd2cda0164afc9afef0d824937dbff54cb2113637fba9f9c2ac95c28a719937e2a5953904b8954bfe6fbad6280961ca7cafd91c529f305ccc000fefadb647202871cbb991b0baacef2bf4ed6c40168ab88fee430edf4a19299dd0f99ac03fb1851d6b17643d11f9c38d0b7ace717827484bbcb50c90731f836f26b57dcf6f204f54437e33ecf225d1169f7e61076b708e96ced452695d32cc9989dfe3179b6b3997c8561cb6fad3144a11792809e60f4c58362bcb690f7db4cb7e3cd3ebd48d479df4473e128dc2993dfe2925d683ecdd665631c05fcd6025af47b5e596a6ffec29d254e9a73af7a788e641173b00556fc953e743a9cbf1b6bbafade97ef5fc5ca32011b7609717c0e8a9c2a400ce4fa48b9e3971b92dd8f3136980fdee0533570d151ba121ee9c205fba7a445d802a6a98948975dd49a152cd97a7ce5d29a6b25c93dcaf12211b5adfa67fd8d29d2d52b5c48646699e858b1546831ecee9514501d91286fce1f1d88a54f84e63ac244d5fd082042be1629ead373cbfe40e0f82c35ab0b0b6c070b94871957412a3475de824a36b45acf0c4674161794205a7ced14b8243e53c95cffc54744e0a63e35fcf71225c1372de1da20bee06d961ee6cdc1a640cce96e159ee2c4e948dceb5046dc19dfc56791593a558f99686c264bd2cb702a17ed9d798ae19f89e53b725f4f7c53e384bc91ab7ed0843d6fbf5b973b5dcf937fc552e68ccad31408731b71b8ab86e550790360fdea04603e248500d591a0edc3db441d02c9ddc229b1429103fe075e63e51ce065dd8788b8214514ee828aebbaf1ec4fead86b8674763477666e87a47c29c7d09ab31f15de6ee1959a36bb51e2460877b3f81735b71dba0a9f7826d82835095a8c278844193c2a2c8f174cda1053f130687b8ad3a794f865a4a6af683a3a837ca80cdbc74143d451e135de0cede4f2bf77bf7d5174cd44b12e25ac478103d7c8996b3124f6c64a177bffb159c688d5e6e2faa6a493c2b2d192e55e7dc22f31839bdd8da2c735060cbdb7e254aff84a2dc02299b3d7af7899ddb479a2cd004f509982158be28365bbd0c7762694a06971726378db49b202a0c0add8e78d2eb86e030a5083e7082b95e58356024bd0b3e26afa4afa1dbcea18bf10bcdab34b8cc085e87a96ba7a69eccaa25309914275030b1f96287c07e5f76833ec053093ade04d36d565cc647a66cd5444a978921c94bd0c7fee83f19418f715aa3098b31e15cd5d177957c9452e64b2b860f6b9b6047e81f94277027ee0f0b0a73af60ff9a16216f7084c8f5676d9c14d9ab0c06603df15b9730a80df940af245c01fa22866cc98ffd9aed58a8bd751c55286591a4ba343d26167df9d09f25c41cd7d7274e8b2f3f1d5d9110c7ce028b354ddde3e9f4e868baf879b99587b8e936739a34ad86b9d50ee138005d14d6ad2b4ceb31f24fc34e7cfbeb3c3cd258bfe6be5f425e55a1a3564987961f3b1ab33ff8e23fb9631ad74c9b7357681b900bd50d6b1c4999e578d1c4b966eb392ce4fe58a7a699576c39308fb7f306bd9f604b27491442a0a726316cb0f333892b83fc272e55e443add1a947ea76036cbb88469f01992fca4d99cde1d21983301a04574afcfcafc0860103adad9ecd5440b683e49bd49d66ba3935df676b731310d273cfcf6bb53679f8555d263b32303d93af6dc866f2ffc1d60ddcbc82c625c635ebf6b1776b02fe9c6a7e7257e70159d2592f3e9dbfccc8d97c36cf72b0ecf2402e31484ae54d67d01710a3bb5cd5f20138b038f540529f5ed16607169f0d9905083794a2c578d0c9feeb9f0e1bd99f355b041a2aa9929f1ad9cf14a66f4abad66907091b04a480217928e86bf81bb1db677ad084b677c064a51e43ec74e400fc5304f70f2ec41430873387c8ab210be7b3fac1f4a13e0058b05dd1018e90ed5753b07f6db783fc0413ece7b125bbb69f64e6eb7157f5d070bc8924c5c8377c486b643663981533db9bc45c6a88f641c1d547e9262343b035ca5b7cb4535ad7580f148de9b7a6497996b54aeacd3d27d2d266626e8addfba71f37f8b19c973a0d72902b104765ccda11145b1be68ed2b15da8bc9a085bee20120cbf27d65ccff618cd1be424cb02e6457f672c5563ff5e21822237817ed9641214f7542cd61da4f4cebfae8b840173826f7c471488b7c2968cd73b822a6efed65295301e2ac5115fe94615fdcb57769f76deff5673be00278e023bc8840e28e269a19ff5f7ece188735eb4ed4658e12592b99391c575fd040a1af0061c5d14159f94b2e6ef1a9d0f68791c0899509c6d2a5112a41da97a8422bafa27ad73ae62b5de0bbc6106ebc42a073b922fadcc49f6477f09d8bccdfa80b6cfac5b1d6e869e769e9c59576bfefb052529a516284d225b49a9cc05e8cd616c184d73782cffcc9d1870aecb75ccf63027fdb3a5da9f8afd9ffead374ee7bf142e2f71fc061a507733cdac5deb6d373b0a68b913213f205a345595b1f29cc387a209f7ae932853b760cb35b11a08283b5c73e2148618fc84ffd80c5a613b02a42cbc32b56128d99049a4abc28d3be3756be6147cb5e8f6c48dd2e4b9935bd5b8ea7964f8a56a15c43c02b41a2e6842c6669f90e9e5b261e3f9949f70bc05fa0cf5575160436f03dce07802cf83dafc86b11b57ab0c8026b4cb4e013808b30bfb648d85ba3de244262897d803ef7b1ea5259851e90a9074bcfa2cc34cfcb17e241002b89bb985cda395cae9060b8cb617fecf59758c1e4bd5f4f4632a3899d9171ba0a17e70b6b5995c755e956554057a443c481cd6c335b4b7c0d0a711d1555699d4cfc2da75d6bed4e3b7d4ceda76256bd7f9435c0ff3b04320ff6828de938394f8c1e7602fa874d6dc4da820f5e013e3fd1ae702bf39d68c0015e820220ed9d15a0127a9e91f60937221411496dfadbd29a84b00f2f4cdb1b14c0ac8fd97e3340bd3849f6a50dce097fd79cb8dbce73b08b963a3e59480c2b4829b96fdc99361dc3241c1b05ef97bb70ace12f4b402b0dc69ee6d9a30d9e7cd8621b5584979c4d5ea66619fa4aa64d43b2fb4f04b857acd9981a21eba212a72228c2b4e38200c1c4a59542a7206709c9381737e940ee9cf437864ea463f3cc769264063a23407933f01ee79d721e0105e9d4110d0e1e9e18e6e98e65f468a7481c42429eca3470ae670b182f46c7e813a49982421fe64c2042f9ad202210b6013c629b708c38aa76590382f7949473c1d195ed082da97fee8307122886a96bd67e19b6bd03ffd75fab724f1ec5bd9cf361a5486a8dc6872e19ef5f598976d8492b2e5a1e09254820fd58dfa2f7fe5bf0d9b10c6fb56a95bb3e62881e1a102844de0cfc2d5a8f235c48185d7d3d0be2ef960b148d04aa0232e5feefbc23e72b24fe0f0f0d632bab874419279ad119e748cbb93481c305a9e6a5854f2c5e150cec2115443cd0020f29b44de02f79ee40094ccf31a4aa0631bfcb22a3e41a3f4cacdc2d1cd831fc661e6bfbdd8bd91be36e2acdbe305b6f50683180941ed7490ea9dd6375ec44a03dbea0ab39939e5769df78dfa60dc87f73cefb71db63c0b4f9086d6f93459a92e54fd9d5df3054bd7b3ea8844362616de894933cd4826d42e8196251599546937ded2bddbdb889ae398dba2e203971e911dbc12cc670df6d206307558820e9a7eecaaddc895e12d963795630394c9fcafc655bdde9b4fbea3ac784c8cd77ef1d0f4ddfda3c9d4f19665dfc63bb5c9d588447833be69111894f5633e072930660cd0c7eee8611857e39a6abfd0096257bad3274ea6e5cad643848c4c0664783f0579e8efe2497066e87da31c013f29b79359934def74befaa62670b2262cb3b5cfb3572304fa9211955d34d2ee571dbeae647094c9581aa1d05029365a5151a5fef2f5dac007216d585b6eca39a13d162cb716545c9f22229b112f32e382171c73063f43fc60076d7338cb76465cc3b468662e268a58214f74b769d432d88738d570ceff2df32238895aad4a7b0d22f53c5f9fcc37f42f764717a36eea2296260bc6cc8cb246fe5dd15d8ac73853aa8b1ce2b5b24ac9392320f1e9ebf265b3421f27037ea7b774d150143c1d93b9bcdde14e2b2ad10fb40822fe37ca755118ed7f7590b955c4c1793b6d708ac039c49424be68f6aa4376dbed56d953b1dd75da4a34d43c0e084dd978fcb61c9d96dc2539a183290ec91636ea3f3bbe0e512f7742453ce8447123e595eb71463342f295f375be18eae4a2da20e5f0b10b3f3e0f3c0fe417d682605595fa80eb3562f80988dd85feac412d848bbce1d8efae9b53207329456c8d7cfeafa45299f3756f3d84c3fc379d3a8ec73409e1ab8a9dc0019cc9644d4c8c200b697a6097dd11423cc23fcc1a5cd2572e76ac78802655787b806a01435807b1aee753e23057cf56ca2ac476d00bd6d25c61f0f30a4ba675c7ddcec5085c587c5d4263af426ad511ce98b0aa2c84ccc4a842c76c65384c96af30bef220130b3639c7438b932305eb0813883d55885fbacf124ae6946c3cfb4a997580bb63fde86d4d66a954b52c53f9bad70571b5b7e7ba8c28df9d80112b9ce73c100907ddbb834500343cb1c89b800236b5daf4d016b01f14b7ec9d23ab4f59c134f2747ba27a08c6106553d67655c3328eb3632b0d71486ca336667122ed1acdc050a7c7899f8df73230f574402f2850095913d4b9beb51bffc5f95c8a67f049601659b482c0b28cf191ace9211f9a71d9740d602e2372fcb0ef68affb58029a0c732dc829dd2c9937e516e4dcb77ea539c536befc7206a9a1df2f1cd1d1de2ae15397b723e83d7c1882811d06e1b6dfba388f18bda189a89a49c9c96398fd64ef4d458340f58f4ac79bbb7ea38ce150008e1090f75cc185672524967444c65e16202040af6fed0422c2cd9fc3a7d35f3c37a66311f73d889bbc2d64b05fc3f3786697a67229a57146626c71b69d5f8a1a35819ca2605af91fe3c57d651827f3bd199a6377c0a93dbd6b14f2234846b2111e80cae9eaa77054204213279bfea111654ad589a4cbd531b9c3312339276d8831a83d3d910f9f7947868df57b44ddd2f9e0c4f7c49ef053ef9bb60f0026b8e08f9800ae60e41216115c798fd91a679d62076328d0c87b88701eb587593094b8b50036ffd13d2068396dd9380da8b1f6d3f0f241bdeb899bf8feaf841ac8ca88e75d90534b5cd8e8a5ae79adbb40078da76ae5779b4edda2f104d837558bde04c92ef5c5edf1e52f67435408b6bcadaa234b710669949e9db860ca2821eee81bd3061a495359edd98ac6369d92efe1ec1e88fb709cab62381bba7b8c8aab4387a6f5288017eb8804a35a6869dfe808004889059ec10caa8a44ff117b5223091d5f58650c1723c8eeee54aace4772445b0cd1ef6bbe40e716cfa0d782027a5012f8af18437fe1f39c72ceb9206329c8e5f803ab19ef7fa64f5034d58b5244ce4b00726e85554aec351cf510d3a2e6c025797814ecfc7c702d71290323d4f959f670b8f7916ff1eda8a8f53ef8ed65dfe210916e6470688a32ca934aa468ce3b39ae3e4e755f8ffa6feb2c093a5df27d0ec6bec1b8e94d9462be6e2c5024df6e91881371038d1147e65ebffedb20a62d9c64c6f0ccfb40134631a8f5ec922230398ca59b549471d26e44d3c9d21cc3c9476de3f356bd31e891e0833b35a46c35985d5a812dfa4fef0f9699da3e632180ff1f57975e72061ecd1cdd95421c1f06978e6fbcf8a8738235b7770fbe890a6e180294995553b7c5ae1447dceec2829a3c813e7d39a10b097deaf8aaddf4bb6c4d6cdca3edba5d70d5602746b2ee59e6f619844a00eb2e4a62b48dfbe3e4765f3b224a71acb26d1876e681ea9ae7c0b7190ad1be05a4392fe43d2a5aea60db87b42b19c52bbdeabae72841dc547da11e6e6bb0b59e40fa704ef0269d9f4e60d88a08e5a7eeedb2095d5847d9d065997b9148b74e15dd8ba3b9d25ba1cf11794650465dab25411f8a7e3a16e1f67cb5386d2965d7c326f35c5e24af8cb7e1f939fbfd18a9edfd2f877e1400d7c776f00a52cd94a0cd2fca12709c0bed8e5d48b5c3c25bb4c71560e1b6922eeb0da8bde96cc94180859104b208f764c7c271d861ae5406769ebfcf2e939c2d718f017dadc1c8cd1d7685382761c47197f60d43bfc954389e2d31152e75530608b919b2186ba83487ca978cdeb521b0b01bdca25931ffdaea1d6907de9ba168c2a1612bbb426e3f250d2826bee9ccc49569cee2ef90a0b8ef76f16f85a765f82f2a6e1f8127422c908153b4593e53da1a5629ad7d75e8d493447f8a86727149117f94d505f6a0e75b370adf8d58307979cd1e4d9b6f50f54ed8e1d95105612872a1abc05f4081fba9e6cfe5ccd224c7b09f43d4af3cc0d8d42302facfaf43b30b0c325b5f0e1ac58f9a1b4508299b6513ecf884692053e5b710cdfd362cfe5f9e0ee8bd9d1892e051b463494867de0f41b987e6e25101770637b7ca2b6f6a510685c4960b53f077d19a8daf31ee56ea08feb5d449c1e1a90f8aac892d36b5d3b83c02a247c95f4d860fa65d5f3c4e8b4ee812583d1c582fc8743c328af2594ea8e86da5af8903cd8ec83ba69b14e42f03090957aa473536052a894ff1ccd4d1685a6778de8d27110e8fead0699ed2a6206feab83e4ee8f4155b498a2bc68fd08e29a8f6cb3c529157a40ba5817ad176e348525261a2bc5678a3ef85196ff208534f635f2e6f1b9e56a52488c3c4276bc0280d105e3e66f66eb8675984acf51c389d25fa13f50ce2fe5ac8b1d27ece8706b33579afe14bbb5ab606442a4b9a485d5dcbd6709957a86d8bef26512cdd26206a6e6ad288ac4228095769973489f9310b9917074ef74f6900815d55838aa52d6aacc74fa9e2788077a8c954de386ac675caff690a5f52ad432bf52842e18a8f9997fe246d2a3a2d45455afad7b82449e074f47d4d692e0a8889e5f6ab470f019e363df1bf15f88bf7a4db43711e81bb370bac568a998bfe22f2146c4acaebeb3e5ce8f47accd2a86835260d4f3800cc15d75cdb99d83d821e3a68e6d268f026a8e1a428ec83e8f33d93090f85475f8b799d06d0cb8547a14731c7d3801f56bd29a6f0ce6befea3fe41b578ceec7108d4156186e16f49d4ddcf158d1edbe609072b05065f94e401ea001c84d3426670ce49c7b81ed3bc6b13d46a29e4ef2249237cc709749fd5a543f177f55e5fa606774b3168070e12fe67f601a15b1542ed25e20b8290daf0dbdec71552db1a7fe681403633cbc236c66c63d06460371f1cd0c827b7f5a6772f4152d633d26beb2d0a5c2f15cf7252e538ab32faa9b896735f511a836d850259148e8ae983cf9e984b57fa13a6b9fa4aeffc40ab6e9a1e00ec390ec6f9071e49b18bf25b7c38b445b6125352a8fc9a11e2359dcd3a3405c29b98e33df9a2491ad4abe3f360b1dd20e4c162eddd28b806927cc09ce769d782023b066ea9dcd5fa60de30c6e480d59354cd91da85dd82cc9ac99fd26baf8005072394e1ef192ca43a8cee2ecff9321e48fc6c08974d8a5a699cdda46288d8bb398d7be54828bc11f3ea4070f0fcd4111797a228877b9d31bd46b0ab6d45174e4492e2796cc70919a8e1a73489804f5ce2d1fcb891e6ea3eaa16f02627908ea2a79ead389eb9afa1cd6907277117cb9a9d5f0aa558c561aca3934a7e4b23646a2a0f19c24971c1cd0a98291d243927d8e1e0eeb46459c12b58a5a790fe05788744e4cee99f29b63bdba6809f637e09ae9efed88851e65d4a92d2873132e22fe3ec84021ad28523e9af745703e6af7dc5314172661c1194d8cde137a0a613f7f081c00dd701014afcfc50e90a38e59b1fc5170ce885c01fdaa14041d1a8a87d071204eabf75c43c71d70ebd4283cc466ec803df8301f9c8d2f4c5075d164937b15a8d1297282a6d126ee10b0987e8962f50fbf3a85091e8654adca4317672bbead57c561943fb8fac3123b0701653381ec981849a9327dd355392b84e951d0ec10f03ff7b411ded04693c243ef8502a16c29d2b9d6d5bf76753ae25e4ab49507cb835e5397f53c12cbc8204119c67c8dc6589d5614123b9ecf6e28fe9c0232f587bc1639e858dae61bbc0d80dd2f158bb9b4fb137cb1d0f537713504e391fd8cd05b18205f1f6394b081af3c5a248e4a5501cc0223eb8fe252ad32854404f7f975109780afc4c9b9a1828b95fbcdc960f91826a795a4a2f7f1a0b89998f840a5fe60522aa2abfca4e55c9d511e2c0c88635a25acbbecd55492f6f6c74071b5daf9e72f36430af02b1bf8d1f5651491bb14e6fd05573ce8a02d88e45a414ca1c6232376e9b1d9ae84d00427345354a3f3fc120671b750a7f6d2ce58b40f4f291ac25103c6ffe566ff9c7f145770a749f740984d97b10a516b5b4434a793c2c15d386239cee97338a269faeb80fd99cf7ec706c3793db7cb466fda89d1478c5e1a4ee5d39705ba57bd49a7329846525a7f9c2834923a46be814bfa8cc168376353654dbb0577be371dbef90c1ac8f5b7eeb0b8fe488f8bb54c98f4cde0748b15b5ff220402df5bd738d8b52503b664c0be9e61eabcf23c05a9864c902a478cf8f8abba9f10b0ff8fef9b595d780bf335153241fa521bc0e5c83ccb752f484c05baed513b0303cbafc68f54082c8d53ded37e3d67d222cd8f8ed1b2cf689b5856435652d0948349a3bd2982b737293873704176f213fc5ef99a4ecf74a1a6194c531047cab8bdc7f06ceab7e03d6bdec5b02ba57d653f4e183e36cbebe1b5f92fdda5aba69280dc628314a12efb2bb55477490e5a80cc0aa511765185175ba89a8aac588ffe94dfa7e44a969b3e67c46eb8cdfe074f0fd5eb6edd4c5a136aa13bcaf9cbcd95440f680b34865fd4703e7184b990ecafc2b90930cbe4f1cda741f29a572f34ea8bdd45a5ad5fbcdcb25c9ec0c23b8e28ed9f9a18f58d12986f3496f2594316ed7d01879921bc13a61abece17067319693e1a01bb6ffd9290004d59d1115530d3b11dfaf1702f23d5abb13371a87c415f97b345de53a265cf9868581e3a8b455db54c628a7f0474a59418c85e00d5629ee03d0fe7a950c23f0af4716826af5aa1bd4d6425551c1e7114243f1877ddf14980f626901e2129e7fe9c26785a12c76e58b65ef17a58398c4b60b2942dba7d6c896a7c5558047021a437e26680cb8ff7a47c2eb8c35d07e6b7d02690d4384d045a989bb61f831dcec9741bd6d51264f0fd84220eaa51c143f4e1cd9dd0f94d6cf485328eb2d5b198745d17bc607d96f922d53a77f51d61b32be2baf82727c0fed1dac8ee004a8d49be0d2146e7b9bcb23305929b34ea0fe00d6907227ca4fa04c61943f647b446e3cf2e84fb7092b9633850dbdbf05aa583a77908da4956c1dbf463ff1f9569818ea3217f8b0f996f8b13107a74584d68af1bfe112e0db179d492d6d7ca5dae700477855dc879b5fd3115627d72ff9a19c5bd23c645bd34efe97392fa1b7869d3098874eb24193771c1f91e8db0174424dc55417121ab96addc59b35fab467bb0b8430f66507885e3ee1a7a21db443a5ac5bd5d31544d926f04a26cd6c8fa6a81255a6bb1d6c760abb76866ff0bbbf3a3a3e80f90c1a2d657a54766870c21ee506fea83ce655de2326373940304811c387fd60e6fb5a393208c2c045425f5d9d84a2e0085431295c6438eaf94360070266166aa0d0618fe21536c2eda9a9eafa9172fb4030243db942df152910904d3d53fed171307cbf890d8b3c6d26cc3aad43d4003567b2b5952d68194b868ffa027df979fa450b8f517b80cec22558a5e19744ccd5c5f6cf2f0a40e509b0c9129c5b7d7015bdcc33d55e1f45d840b12c79d64d95488808c481ce7f44aef8ccb1a5195a5579cbe5a8fcf4654db993273a98a6f7dc90623a06dcd0a6c324769abece2e31dbfb511adbd55ae7697eb8d6f1c7ad68b108f68f9633dee8893c2bfd8704e0093d6a18bb0cbb442a4895d8899956da24ce200f629cebec2a9f0a84014944cdcca08777c5e1ece0f8a3a9997a22096253329a1fc4794e065574380006b00d907b63179536ab75af3f15f244960d8872f587f85f1e35442d48cd15db48a613672c057049cf18072a609b87659e3c151e6c353be5a6224c5e0409ae74eefd9fe5419e1c7591c25d06d12ea6078891e95ea4a67c8c786b2e75db2a22808339954f2954baaa7f1ed8df3ae2cceee14fa5fbc2154732fed694556127575ca973af5fef56781803e9e7e193ae5c5b769e7ea426a8652a6fde1cd903f80fd41f8a00bba736db57e2e347ea3ca8bb2a4a5454e328ceb4c2e3d043a62cb40362ad1c38cfc6173155259109a0f432ed4975502768dda67bdab35d1d06c6f6758ce9c85a49a5b451f9bf65a0377b4c43862c69ce63ab15c6b680cad7f9bb7d1fb939ec147cb8c3f28236f8be97637939a65033db56eaa5ceab24fd6dfbc36af445bf806ed618cff4854da0813d5db1bd55245fe2fc15d9d62cc63829b43230525562bf8d77629f7ecf0dfdee10350be93579f62695925dd234965f253e262d90d1fc760a349416084b54258e3e0ef56d0f259b2cf79f975b2a6f229d12a80d01cc32360bcba5d8719127eb574dc92b17e0c871d42181e3e23ab171843e211e9c08da3b1d62840c7de034072a4fb3287c6c56197324adeff4d680b8ceeed450d4a63db0b59cb19513dfc398bf5d47e899545c8b5a3afac772bef45422b08f4def8774a1a84409784b38eae930282df4ac12d9906746c8e56585ac6afcb6d383c018a9f54026ca5fe61cb824cd8c657730ffef5a45068b2e9e8aec8b922b70f92604efd82a4b62ab9f2d350ebf06031cb02f5db8a47d33a7ad2bb43379c437989895c3a4eac31f72457cbdf93b9579bedd602b166460fa1c0e1c939174dd2ebc2ef1f100b3993aff60235508df08708a587f2060b76b987cd274b32fe9aa14533eb00226c798721719419fb61de733d69cea7f2fecbc6c9f34338da059e84a60a518d86fc5a5befab3eb6c863a3712b915344e1515dc0d75ae78a2205b1d78ef1ad2e7923ca543886385cf8094da000677d150bca0cac415a9a8d73b3dc031977c5274f8f94cb0417d26e5c8545148af38ec6faa48658529f4a34297f105de8ad763830aa0da9cdc815890d8d35f886b517d5ca690198fba5d68ac1fadcab223b21fc51bc1f832b139cad59052da952f065e7eaa3ebafd78317ac3c737e6e8594aeb696f73c35e4632cd423b7c0ff31bda1fffc02449e12e80a0672b105ca652ba4124eaa34b92fe526656664937c81162d2f4c1393b089548264a49e53b6013758df59d18b476b3cd5523eb247535aeafdf5d6955d6eb4c0e0b1c33f56253fb682c777dc6a3a3076d5d6d19143b8f7a6798aae7aa727bf0684db1f96d9205db4eaea1538789c05f50364f7ee5ddcd5b4cf172b325fa542a73ab57ebb9ba6c25d4d4c9cc86b67a23627980ca2fcda4767b8df8b92862d398be3d98197fd904d80e8dfb3c80c8a44c6aa9751d0217aabcb7f44f5996ecddedb91e7b3d68acfbeb8f943d0980137d54dbc391404c440d31e92377b5d1d10f7e895e234f0663a985fc2f8b051fd2ed1c1a40eed035ef146cb118da581a27806af28f6ecd27de1a3de9e16a08dc512d6387428b1d933f3fab3b85a064aedbc8699117d2b795b4d0a957828d8f3f641d6bf6857c97f79eeddb6efd35a3950a9b461db5cc2024690d7bf67cb286122561f10ee4bedb8639bbaec203d8a725f4e504a424647b1dbf99f572d4c1b4b825f38a6779084e8917387fd57ce39106ed73418dcf40358167b35b366cdfb73c584cbb1542cb16088b58189eca1e40f47df244342033afbc9c42b99cf478a213dcbfb2740e6677ff885a4e14ed8a38b2add584978e6845f0d77cc5e6cc1f76d144c540b15d1e399141971fb6e94e0b08b465e3751174f4349ebccc95d5a7355573728b29077aeb3c0d35e4c714b637a0ef60d63956678302f669027e10e56122fd4d03cfe79eb015e46838cacff128404a114f50f25d2c7caaf09c8dbd95f13c8db33baabc511caa204dd23377c46d2c88f4ff97b570355df70367e4ef226c5c34a5824512a90e0875e2810e2cfde85de98bbbfda6589a39c2d7a37c1d7146a9fa8994cbe6c026ffffb675eca7332588696ada3365e97b4aa32d41ec10e95da3a500d7fbcbf755193a925aa1e963d4fe5e75ed21e6e02a2e94b8d6258e3613f8722a9fe33de0ed6f34277bec8dbb287f4e3221bd465b54ac4e8f0c78a8c3b3408f2112ed2e3207f5822b728a9ea340349a1c0d6fd06b07d51d2a9e4a9f5767b30c9b308455ebf208ebab9c9c2e4fdaeefa10c08aec6b714675294603b5985980d76e3260a74dadba6cca4b4a93f05d2e9837ae2cd6f9111577003ab4392a29a01ed06b6a8c88373ca401e62a8bbe110027a3782cd093b98b0292e37d24e86452e3c2b1f022ff39d7590aa5ed4fbd1822948f47a74e3efb0b28f696480b2c10d90ae25a65c8ff68ab8ab22b0be2266d603d9c5807c4f2fba1dd346cfc121246f2c8b8c2f47fde991455594277202920524044ef918b073f1da401ed6c14c664455d5fd80b06ce466a83e3922c8bcf0bab932922a59bc62d9ab54998a69ddbb4e46c08b2a6b69660961178f7640d5446af6c59629bc0472937021285ce7ce78312194cc6d98a9b329686608380f1997100989b1508072b98b6f28a4fa2a70e19207e3f3b202181e88ed467e523332a936749cc628ed4ce369a3f25e13fa85d545068e237f16e1a03670bf1c3d4433ccdff3ae3b9b78b242f7d069c3e26ed60848f4baaf4568befad0bb55d640f2215bbeeaa913b71f5a1a68d442c026e4905f0f5b8f3f19a04c947a97b79276432e022154c01c182f90b2c7b2df57f8d335c76966274e965d57473a71d8874ddf2182c12c1d92294d6b6f0e83ab657d5f724ab469eef0ab4e501e887da25f3071e016b7007b18081ef4a3a692e9ef54bf0dfb5f77ce232e91b8f8ce317b9f822932fa2f68852e0064e033965a4b20c7782b1290ccf367baa3472f05314368d28d30624c37336607b3489937c3cd6e6d3b172acd94f647dd3db0adc7bd078a484e71207e64dd32d92d11f3f0cc21828fd91379809cf16959613ae2cf039318e066dae7b8ccd71d8d71de630becad27d0743b6de60be14f4c0accb084dd089aaf291df3cffcef74b8590703c62240de25bafcaadef75a4dfe296586635b04ffc67d892cf271708190047025a37456c491bd72af5de4d5477a264c69cb79af4faf512ddba8604a5abace78005bef710521e68dc4ab7bd8f858a9255dc4ce968d47f51ac8965cb689ec67df7e171b9b7999894f7e183712187123c306ade727938ccc40974ed3f1c28fc0d4bf1a40484d52679e8697cbdd362bc59347f4dae394c0d514d9c9841de7566d2e1e7bace1063b345cbafa22284ae3fe6f771ea6029a7201aba93fbc48b96f1f303025c33ec453a1176fd486f4029a6dc2efd2418cf173d460aef9e33ed0901f5d1e9f4bb25f1a0df8b18af49a3946dd7c76cf689d199b692dbb4c726a1845977b07b0408f446f8ae7acb375d3a6a542cb4e15722aa8359a203346c2658cb3279f21da954ce0866e6039069bf21f0724c7e9000d342f17d1ed190942c194f7fb6bfb4a275c11a2e25860346e00fdd62f527b6859c32a66cc74392d229b1d7e4ec5a15c2deda7fc219cd5a51bc9de7f4d7ab6444efcf225fde56d80da9af0f003db2a2ab64037fd5982fd2d55c0fda3cc72679c0d2c23f4378840b926e3b7357238982244ddbb6dfb09f4f7e5f86a5b0bb03d69a1d7b2ec0791fa0fd92692e0a182ebc0c76b102a9e13f3793af906a7a60ca4710d2430710c5add9f6efaeeae009c706ac2f3c6ee67716616c11b605dfc14e67ee49edf2aa50fe289dc53f340d35d3eb0e15a55e022f243e6ade4d468ffaaa0a1ba7b98a53c40e8949cbc9782aa3e1a505d1fa5672c258824c4cabe6d0b47ff540aee74353c78fc194b71e1ed5e8866368db0ddb0174a39ef4303f7de657315a12fcf0f5f3127aad60454e22cf8f998a8e64a66130fa6ffaa7f16a7cc4bfd35688a5b81546a88cbc6f176f36fafb052919a20b807d5c7a732f0ee6be1aa8aae5416629f3084cfdff3f641e385296413f4911d71d8a906d7a9c2cad61ce1ae9734b2c99862d84ea24c6451614653a8574a2a4196ce898bd9472b68df3275e8cb2d5b90763a5ae73fd0eeceee25594faedcee27adda6ca640d5a753920896165ee06314a6aa02c14aef6836837a43469c6f1135ad559128294d539136695b43462c5b11c6234cbf519a55ada9429199e950481a7c6ccb142b982bfb01daa3b3ee0df5783eb998f5920b58bd3f1d6ea69c4e1f5ca3bdf61a0e6bd742be55cc7ef839fb3d8fda27deb3efa5a162b26e3aedfa0c1808835201ebfc781eb3eb937fed3bf3fdc6cf9db82cd6b7127ba62a336a9f45294699fb4efea051730ebeff745955973bb2464c8995a3a5d8fbdcf6e5612eb688c5fdfd690aaec1a83ee31b61b713801a0581505fa4972f78d33d5892d547a97f85b6df06b21a87a24b3104f962f6c17b267dbb7b49bccb6e37aff81639c58a08bf37bcb26091ac6963afd5eef0a35b775a000bf7b8facaeea84acf01ae3398a6c0d3fefd18dd66f26672de36568ce1c51fe171e7d53dfc4a5b746fc525cf3f02291a4cedf8be367d3d8b00894064fa2ca6ad124916594fdc0ce6db4bb598ff51b06f0edc4a76038b8394c2107759a9b2290c2517de92b8f4e6b78e94e371d15884c301ef4e258f235fdbf887537cdd221759fab026bc61060646e0869282b53d1ec92f2e530c2f36f884ecf19dbaac3c4bdc229efa4d76bc44f5252fb92534370d7f55455003b42276666da169080e08b4cbe87653f77906031ac8c7db4d45e7f2199fded18f031cd4382ecd581b2a539b0bb8b1f439914da87da8244ad925db76b7ac08c47e8134f13566f1332fc03639617137ff2c6c6cf68b7ded1e5f4781e78252bcdbbc6bf5af0524e52f8024393dbd5927a1fc8c122e016a96adb0be82aa80206b891154dec6f6abd6950755c5a31d7f4bed1307d814c58d0f2d78a0de74bb0cfdfef1a1a5ad24859d4ba406fdc2977599e150bef735db738b1096bc2d5b468e841c45ee018a794b3d2598c37fc855e4bd7b318d794ef77df0267808eaf7f73c2aea1d15e0c4efc156085782ba824f467e65023d14a702d40cf5c348f598f6f934e094ce2f31638b0bc49f9b87f45e03e98955cc815aa0fbc774b81fa274e52245e2330d234b465d2c69553faf287ba2156d46ffee074aeb8233ba82dd615878ef315f0bcd6c53613a31e9bf08501127697d173139289718f8c37d7b012eaf00e714d25eb703c1b28ae9aa85af588b650cd319f67b77a2946238e33ca10139ac58570ed1e0783a5260ba9037ae8fc1e184ddfe937a929942adde3b253b822ebc968b0736ecdf7b0578f34feaf74ffe9728db17a7798ad92f43f9ff924306c31fe07115c782edac122076d0e265dba4d854aec8d17ffea40b289cf68b4239faf520ead223306e3deac6dfae5b16c7620fd20f99fb078ef04d2b83c64f1e8841de34973d226ea32b9f8a6210ecccebfbde59b097c359825d51d6b6afe0726b9518224023d73b9fdce9bd51a819fe02f481dfe0874187e5bde2b0ac8ee323a3afb732ab2f3cc6e19497b0e4ab1397bb878eb7cfc18a86498edea542d632f6f71239634bd71270d70d1e03968527286dea80196297815dd8e550c74946a4ee54f6fdc2b9c20b7f0ffa270ce3b466457c60ac66f892f7b3c751c7909986febc6eede7949786fac0a0c32eee57b9e1770bf773dad2d6c498a03909a5094db02de8caa7a1eb2adaf5f77bbc7db213a2b986b8f9f68ad92267522e85d597a77b7c36c8fee8a1ea0c6d1abfc98a1a87824575c7c73d70674e98072f8258ca7a3edda2fbb5f8ed4c94862c23634ee2e9aab3ebe1ffb0158efd6f307bdafabba98922b05ca589f0b37acb38ce6d54bc91c81e703f17f346475a4be91a26bc773792831cd05382ad62eace42453d588e5e458e9fd662a9c0368d7dfd4c7156e676890ad16fa8720b14ed8a23e1e59b8cae8ad34f717562a3cd68d2e62fc395d6665d6e59a7d0df012e617fc92ff70cb4222ff1e15d8491e11e797e8972e4d1e7064a0f161bcdc7780d0bbe2cb9de24513b60e3a208cd74a54582a4e384bbdaf4fe340d8f23a9cb1b06e8bb42014c64b1a519405073d818a253f922e4f0c56f6914d816a410c356083bebb081ae554ae611e55db2d7a1acb49e1f525a5460736fc5582ba4a1d99b29e58c96f44263edea66070a8c6adf9ed5e270a07208142c91a5a95278b29ef2a7ed572d19faddd756f4c94b1da8fb627a504defc018caed07c78ee047df8242599773616f9f9c6376b4e96deb05d5c6f827e24742144a62939c348eae94fcb944bf61feab9b7fc652ffea957a7477cd76e137ad46b12f060eb1d98998176ad7318e066e68eb5695ecba5915c29af8b142034e5d6dd06f7339ef6d005f9a55602f56d24aaa35b87fad2f680d140848d58ee8dc4aa2cda8e7b3f0a1112af07a1e33619cffcdbd995c667882003a720904f2818eaac18bce12604730bb77199feb49d25e743ddc154f03292b9fd403d2aa6f108ab909f65758b5f37312301558268d2a3c4df25dd2436eac72e4e4e7264862f1e2568e49f6122ac8fffa6cbd5dfa7c400d327f2efcec195a99b27d4c27e55cb71fb77abf9b965b8bf3b586b04d63e894c0801613560eb1a36d20ca4889057639d30d7ad926c25663ce94e4c6c5492df23982261fd4aa354facb2900fcc8c83e635b5c7cf9f54db4772d0772c59a991e008c4deea8eb9efe2f06f7c7f65317b1d18db5a837f1a947bb1d35ec199e91065340be8aca9dbdd8eeea5082695ab8dd03e593ef036a92f67504c8485d78fc824c2fd7ab7fd1fb3df5e2aca34c2f1b70f6c01f8bd6f634c6aff30e1092624f1c25969d9d1b436c57d3a97abfe01f908a718f6288426cf7d7bf1487a4c0eb98a62b85f8d02728040e30a92cc413aef5f223ad871ba33d45ef408d283dabc21ec8dff7410aaf000caebb9798920b7cf999800afbb2d0ccdd6ef1c7195734d9968d2b8a4eedb987e4579cf00b9cd86497d1a4d9d211f5e28aa84151b221c80b9c130c48e51a35cc7a19e497af8fc0d036c11de2afbddceef3cab7ba0e58c664a58cc41f5c6f22102b3c9eabc75548270bad7c40ab7607314310b3f3e12d214cbbc40ba949d7e1a8444048c304215155ef2beb088b5e4ee3ef7bb4e084671f953ce7017d6ba32e2da12bfed12d5f0dcbfd99dc21b2b4a421ee8066e1253e4ae06ded610a7dabbcc46335007bacef80d11172fe5542d9ec479bcac1bcb78fb29a075b2180c923f03172f0b799e59d61b16c32e06c37632528ef32770255a90c3128902ca3b67a1d8b03bcb29c45a6cd9da85c7f66fa955cd7865a520bc63a917f71a04a7c2ae6946b7075a59988003fc44ef3addc46a9a47c800b63a9910e9c4246cc2e0c46288f7d1fe61183d2be41888daa4de4f780a75975f35afc8e2519d1352b6c8d17a1dfb92cbd1d2db9f33646fba17106c59503ea2a5cb5227bf55bcd03782447522c4dc263096b28b22bcb53dab1264175f12787a64f10e20d7b97956764091b9250886fdf28e311e583d5277c8e39351ffe05d4c5a7fcde427916675b180dab55c9c6fbf4a67f6396b22b152875323d2451a391145c84daa105b60813298a2073edeffee4ba7f3a0e9e5645cfdf9cef8220053a2ca0b9b1d13f725c6d7362cde31fbffd542d5b270f52b32832c059558e0a1f92f6aaac28b7d3c1666ea8340a1c7094fb94208dacd4b0de938527b96e429c72067617132d558906b7f5a41598cf7061bcf14ada7ac25164c50dbffeca4362d5d3192005a2dffee722945f197da0583af29f42b2a057b987f186c110006fbebbd9ba1bdad3bdc8e7008d162f45d716ec206b2ae84261b2e326dca2f1267a408f68e9aebd78adeb41fb3e7d5f48361841777d0a7fa5613198f7165eaeac20bd18fef33001c41cf442db682a6007d7dedf36bb4f7fe5ae375dba5e53f48f75d8dff7e4e3f6030f0685f8c02f64f84874a5bd8acb99a72b82b9789c66979bbdac3f44862ac42dbe1d6855e1d78980a6cce32703021cfae53b0c2407f14a7396ef53d29be98a6a8bb92e5d11da47b6d674816a854aab2b5ab0f2d1e26452f1569cdfc1927fee80828dc558232e83993e0bc4012aeee29bd1629bc84eed1c9085fdcc0f2a259303aeec160888f967496b2cf2c86806e24abbae3e637766690f6cf2efb32fc43da19c21b76aa213b416bfea465a3fed81d94ec0d88898b086a7cb9ca351daec3506f476390877677e640dfd21d1d0c92cc70ec9a8201a8b3597356af9fcf61558c46e1945980ed9e6219d8e8c121f4c32c3d9e6ff6eef82fd912edd943bdede47e2f53fa90e6d90da97e7858e83a7ac2fdfeeb63c1e361893de45c77b3cc500d7580f959c204128b05e90c87bb7950b6577677053054790a5b98e1430e836b09b24818b3b413c3c4158887be7f2dc5da9ac19527238a6edd268f4cdc5d12863e350bcb4789ff41851fce5a06a5429994ad3b015f034732b36066bc1aa0e50c209ccb6b69d83348714cc571385fc82814ec3a805d6ecf1a394feea256dd32c1a1a19f93901d1b42a4f1bfb3324a627dd2c33ac2c09ea08a8bf092daa5ee74fb820248f98a8df1d50d169549ed08eaf51467f440938d0aa08753ee2a43b040445cbadd8bf1f63209d6f41569cf6c05df6214c40b9c10b9ee8bf7eaf5d4f12405a4c4eaa49aab04671df7cb517979f5cdd39382ac279b5817b848dc6db316c4beac831026f9595a04a8f4fd643c699852a187c4234d7aff1a326324bbf0f1153415800f0301d38a8950bdde27e40e56295a271cb2f25fdd2946bb369ef322dcafd23cab717c14c59ca06e00ce1593e787832eac7e5cdb81ffd78827c934898ec1ab7fd67d43826c7d6704d66a09df54a78a535e20c2c9acc3278f5f9e698d38ad34b7081d9642d98c7103db45adcd558db4be33427f0bfae33426a6209854012cd05e3f8d6617211821b1e478f32c8dd55ef6e477c4915898c833bb1532de9a2c92e7752b058062a98db731dafb6fa193827fca8700967563837333ba05484db26d318b5232878e3daa9db2cc14addd4d965ac96e86dc950dd527b80c25da4862b97ee813e714c043fac68009f55941bb61e7036c7373802edcaa795064b60077e570f24bca2ef98143a10869f7dea4265d63a7fe2362f1217268204abaac7ddcc43ee9a62776d61be8695d12d2c190a87c36308161d7a20d5912933aa35570c013bdf26ffbc0f98c25628a7e84a3ee08b856df38f60076cc54194a83d7290774da6dc71f5517dcd45989e4bd7f436b86c62f4a75cd2d5f84db9e69ad631beb180f85fe5f82fbf6412062601881b1f26145af246d7610202e496030b45690d424f6d8b8e476f9bc14c9e6e1476d0128a83f3e641a4c51d9e86ff4c7c4a03f4506bdecf0078fc079b568bf542fab0880a4bc60f9039786416e71ba773a2ec3fc58e5632405cedd051945e664b572d5135f281ac2630e9abdf0da81e1e73cc2c7684d7025a4b797dd7704102e77fc1b31c61af1478b30695ca1622e56f8b8d4166ba4593de0138b2d3ba729ec261e9898c16ab53c181f04d32d84305a9c095902fabd30f9bc2604f0a6d943d4094a81f8633249c961b34257424fa2f687bb1235316e6c11d67f2e3ca3fb1b453f5037642707adc40fbaf01921f6be547e9b6748b37c9a1dd6262ec365615f678ae4e3bd5f050dd4a668d436cb054664118597154a03b18c5f74551b6669c08737db380450f552bc7b2e963c5ed8a8d32deacb8172e2be97b9999f8603b26d437f124331e444c03938bb1630fb51664a5d6f24f1e475bf19efed1ca86eaf89aa91085c0ba04dcab01750a0044fd59c73591557ec2537148aeffabb609530b90e4994e2c5fa450483b47242186e991af386fffe1ca6782edbe21e1d3fb410dfab7d9a9b65ecd5558dcb9eef325860e15048bfe67b27f60f010ef54ff01efb79ca3c512d38b9c5b15e6dcb43f35273d15ab446fb61d5251ab4090cbf26fa80b6e8ba946f8b18521f0c6f9680fdecbabac872de39e492d05afca6266e4f3dea5c3cf843077980c157a99f0d3826e9491d2b1ffceaa2dc7d7c23290d6c11315ee6aa6a92c720223e8a3b88ad35c38d486d3489a48172ca7dcf842b7dabd9a6a748c58935ffbdb9f857ca41ed81ada2bfd3320b62675c44e3434fc79f358a3d95adc99fb81f4d0cfdb015c796d135725df075c63f7190cffdee7ed6976352cc26e20a9d961b2a3c41a9231a6dbff051c1b4b8bdd5bd90542a66830e31283f1484a86af7cb90321708ddeab4da8f27eedab09cf7fb5c9b2fc6f287ed52a9842b5daaef1d4e8e1a9bfb3228146f7b913e86c18d62d514d0c394b689fc075667f26ae42a5e10975c156380ec1010570a9ac4c12a985c4dd70e0e2535478e4a77a1ef5de846b84bfd0fed32ef57ab489b43e60219b967f69aba8183eab68e88f1db460c274024184da19f3f6f98b30f21b89f664a1e15f79939ce2e635ed9112c43bb4bbaf07d6124211a8646d93deb5aad98d3ff222d0b91a1bc44109cf0a04c592c6068ea1ad25f2405fa1ba42696951ce913c35eec98816569c957ce913e83c49f1833a0290be9b003a39518a3b5c77393a6e7a2159149f74e6d7c3db07866a0c9c87987daf5fcf735c149e1221d742a1c9c2d8b1373eb984cb9807c6261c7178f6dfa735d873d5edc967565c5ad528d87a29e5ba218126e13c2f4637ce84415341cc3b88eaee7f16405bbec8738264f095b7e9e1f96cf9614d08e2552f90177934a8d5a08f3800cb364a599de3e70360c4f04080b4bba22651f9afa450cc6ff25f06c11f5207f83cfe5d84669bd3e27452fc473ee74d3592e9c03efb11b294234b547ffa512c73c67523a62e406c98f735faa76ddc8b743307ca5a20e89331a9a15641895e0ee81f82d1aa5ebfad5d50d7d93dc8d32de59679e41ffca059b6cb1572187f3497f1b8e903bb3c3705ac432597761e0390f592644bd578e6771f07cd0ea15208252c23c3017a29c9237eee708ca9178b457821ef2b47e6e0fa49edda1f8266eddbc119fecb06e56afa89dc8aec86589691062774d8f2ba89133d1267dbc3c4f996a5cbfe6261ae6d7f2ebd6c518e34f8adeeb603634ad8d7975bd70137f7b87088247b3d7bda478c9f097f6b47efab63d2f97ca027f72a26086bff7a788be5ab02d0b5483914752d4366d2bc6c61cc69642d8973ce4cf6325f57fe916b5caf58f80193a13533472af9d3dff4ffc6a27d6fa059fb38dc2a3d6a284459a6c6a758e0f49133747c2af20efda040f4fe58831a4e84aa7b0a501f023fb425406388f50f4033825cb5a24a17ca2907d78aa5ae4310e90fb290230328aaf2e157adf5d515c0ecaf7582395dd36e3b053b30d3733fb5ed4b3594a33322b45e9d3a616f6f0090098fdc4b0700aa5b99713ea16e0eca3fb599d985b1f9dfc3e6d0d8c3e655c3c5d89eb86dde43af59d1acacf2bd98da67b252ce535adc4cc41c1302982931db8be167defe95942dd6fa304be1758c2bb002369f9489e39089d73a4ea6ec7b63d4baff6e692def6278d405a70da62ec950e27d67a8ddb447afde8bd6c24348a2a4b6bb74f59beca5bc155e6e408ec299e8550f04faf3ce8a00162eac32234b2de733146845e0e0fdbe6a2cf96b5a30181f27c6b53ab72f45634af49a5b40e2fef68411ba5eb815b816d1400a1cf572827c8915976782e82b41859099c91d3609badccad9b1f28be32547aad8e197ea7bd3a37b48b32eadc02f0f88ab884be9b683c5eede37c60fc9d006e6e56806a664cbee2461cbe6cf865a6c53fe6f78db975f4775497735be407b7445ad3610d4b92acf584fa121187b1d7112a0fc91a1c9208c39da321280a8e00d73753624af8411f49c47574a5822261852bf6cdc0619d7c7ed40762d49594350ca2198c23759efbbbf2dffc035653e380cca878e4e823a9f9129ab18b78fbf12124bef2e5558af5a332cd495254f33e3a520605511b4ed32175c797adf1686f1102472d48a26d0b24c0f762125b5ea12fe6abb1bf4138025067f9b2ba63b25df292098e095843c5638195314cfd029219052599b4b4ef001ba2b51ba9ea1f2ce0c9c0bbb280006effbfee32f325c207c70626c7ae70d408929caac0e652dc115278467fc47f54868d405217842a42672293ac69cb016641f4ff58798c719dd86aa48e7d9a809e5665911c8bc0bb3a39ca302366831e0929e9b3ab7ff7fbea49e385b7b16ef68acb8a5a9fcc16de4df2f275bc123ec8ba22c383ae5e156e62f87c828376ee5d57dd92def74bb0cd0cf1138b3121cd2343f1d9812b04b4cdf4f1aaad80000\";\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(\"Cyberlynx\", 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 lynx\", \"Cyber lynx\", \"Cyber lynx\", \"Cyber lynx\"];\n    }\n    function _T2() internal pure returns (string[4] memory) {\n        return [\"Chrome jacket\", \"Chrome jacket\", \"Chrome jacket\", \"Chrome 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\":\"Cyberlynx #', id.toString(),\n            '\",\"description\":\"Cyberlynx is 3223 Cyber lynx girl with glowing pink ears and teal 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\":\"Cyberlynx\",\"description\":\"Cyberlynx is 3223 Cyber lynx girl with glowing pink ears and teal 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":"58039477","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-02T04:56:21Z","match":"exact_match","chainId":"56","address":"0xD4D848F81216Ef2856fEe2cdFa529a1bB53c50C0"}