From 5f163af1d8240b88a14a214c5cf256f8b33d2fec Mon Sep 17 00:00:00 2001 From: senseiGai Date: Thu, 26 Feb 2026 01:57:15 +0500 Subject: [PATCH] feat: Introduce system accounts and verification badges - Added SystemAccounts enum to manage system account keys and titles. - Refactored Dialog model to replace isVerified with verified level. - Implemented effective verification logic for UI display in Dialog. - Updated DialogRepository to handle user verification levels. - Enhanced ProtocolManager and SessionManager to log user info with verification. - Modified AuthCoordinator to support back navigation to unlock screen. - Improved UnlockView and WelcomeView with new account creation flow. - Added VerifiedBadge component to visually represent account verification levels. - Updated ChatListView and SearchView to display verification badges for users. - Cleaned up debug print statements across various components. --- .gitignore | 2 + Rosetta/Core/Crypto/CryptoManager.swift | 228 +------ Rosetta/Core/Crypto/CryptoPrimitives.swift | 185 ++++++ Rosetta/Core/Crypto/MessageCrypto.swift | 609 +----------------- Rosetta/Core/Crypto/Poly1305Engine.swift | 153 +++++ Rosetta/Core/Crypto/XChaCha20Engine.swift | 201 ++++++ Rosetta/Core/Data/Models/Dialog.swift | 30 +- .../Data/Repositories/DialogRepository.swift | 5 +- .../Network/Protocol/ProtocolManager.swift | 23 +- Rosetta/Core/Services/SessionManager.swift | 5 +- Rosetta/Core/Utils/SystemAccountHelpers.swift | 12 + .../Components/GlassModifiers.swift | 41 ++ .../Components/RosettaTabBar.swift | 3 +- .../Components/VerifiedBadge.swift | 76 +++ Rosetta/Features/Auth/AuthCoordinator.swift | 8 +- .../Features/Auth/ConfirmSeedPhraseView.swift | 3 +- .../Features/Auth/ImportSeedPhraseView.swift | 3 +- Rosetta/Features/Auth/SetPasswordView.swift | 13 +- Rosetta/Features/Auth/UnlockView.swift | 299 ++++----- Rosetta/Features/Auth/WelcomeView.swift | 48 +- .../Chats/ChatList/ChatEmptyStateView.swift | 67 ++ .../ChatList/ChatListSearchContent.swift | 244 +++++++ .../Chats/ChatList/ChatListView.swift | 300 ++------- .../Chats/ChatList/ChatListViewModel.swift | 136 ++-- .../Chats/ChatList/ChatRowShimmerView.swift | 50 ++ .../Features/Chats/ChatList/ChatRowView.swift | 132 ++-- .../Chats/ChatList/SearchSkeletonView.swift | 86 +++ .../Chats/Search/SearchResultsSection.swift | 123 ++++ .../Features/Chats/Search/SearchView.swift | 151 ++--- .../Chats/Search/SearchViewModel.swift | 44 +- Rosetta/Features/MainTabView.swift | 30 +- Rosetta/Resources/Lottie/search.json | 1 + Rosetta/RosettaApp.swift | 58 +- 33 files changed, 1903 insertions(+), 1466 deletions(-) create mode 100644 Rosetta/Core/Crypto/CryptoPrimitives.swift create mode 100644 Rosetta/Core/Crypto/Poly1305Engine.swift create mode 100644 Rosetta/Core/Crypto/XChaCha20Engine.swift create mode 100644 Rosetta/Core/Utils/SystemAccountHelpers.swift create mode 100644 Rosetta/DesignSystem/Components/GlassModifiers.swift create mode 100644 Rosetta/DesignSystem/Components/VerifiedBadge.swift create mode 100644 Rosetta/Features/Chats/ChatList/ChatEmptyStateView.swift create mode 100644 Rosetta/Features/Chats/ChatList/ChatListSearchContent.swift create mode 100644 Rosetta/Features/Chats/ChatList/ChatRowShimmerView.swift create mode 100644 Rosetta/Features/Chats/ChatList/SearchSkeletonView.swift create mode 100644 Rosetta/Features/Chats/Search/SearchResultsSection.swift create mode 100644 Rosetta/Resources/Lottie/search.json diff --git a/.gitignore b/.gitignore index 829794d..3716042 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ # Exclude from repo +.gitignore +.claude/ rosetta-android/ sprints/ CLAUDE.md diff --git a/Rosetta/Core/Crypto/CryptoManager.swift b/Rosetta/Core/Crypto/CryptoManager.swift index 1072741..686d1e3 100644 --- a/Rosetta/Core/Crypto/CryptoManager.swift +++ b/Rosetta/Core/Crypto/CryptoManager.swift @@ -1,7 +1,6 @@ import Foundation import CryptoKit import CommonCrypto -import Compression import P256K // MARK: - Error Types @@ -34,6 +33,7 @@ enum CryptoError: LocalizedError { // MARK: - CryptoManager /// All methods are `nonisolated` — safe to call from any actor/thread. +/// Low-level primitives are in `CryptoPrimitives`. final class CryptoManager: @unchecked Sendable { static let shared = CryptoManager() @@ -41,19 +41,13 @@ final class CryptoManager: @unchecked Sendable { // MARK: - BIP39: Mnemonic Generation - /// Generates a cryptographically secure 12-word BIP39 mnemonic. nonisolated func generateMnemonic() throws -> [String] { - var entropy = Data(count: 16) // 128 bits - let status = entropy.withUnsafeMutableBytes { ptr in - SecRandomCopyBytes(kSecRandomDefault, 16, ptr.baseAddress!) - } - guard status == errSecSuccess else { throw CryptoError.invalidEntropy } + let entropy = try CryptoPrimitives.randomBytes(count: 16) return try mnemonicFromEntropy(entropy) } // MARK: - BIP39: Mnemonic Validation - /// Returns `true` if all 12 words are in the BIP39 word list and the checksum is valid. nonisolated func validateMnemonic(_ words: [String]) -> Bool { guard words.count == 12 else { return false } let normalized = words.map { $0.lowercased().trimmingCharacters(in: .whitespaces) } @@ -63,44 +57,37 @@ final class CryptoManager: @unchecked Sendable { // MARK: - BIP39: Mnemonic → Seed (PBKDF2-SHA512) - /// Derives the 64-byte seed from a mnemonic using PBKDF2-SHA512 with 2048 iterations. - /// Compatible with BIP39 specification (no passphrase). nonisolated func mnemonicToSeed(_ words: [String]) -> Data { let phrase = words.joined(separator: " ") - return pbkdf2(password: phrase, salt: "mnemonic", iterations: 2048, keyLength: 64, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA512)) + return CryptoPrimitives.pbkdf2( + password: phrase, salt: "mnemonic", iterations: 2048, + keyLength: 64, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA512) + ) } // MARK: - Key Pair Derivation (secp256k1) - /// Derives a secp256k1 key pair from a mnemonic phrase. - /// Returns (privateKey: 32 bytes, publicKey: 33 bytes compressed). nonisolated func deriveKeyPair(from mnemonic: [String]) throws -> (privateKey: Data, publicKey: Data) { let seed = mnemonicToSeed(mnemonic) let seedHex = seed.hexString - - // SHA256 of the UTF-8 bytes of the hex-encoded seed string let privateKey = Data(SHA256.hash(data: Data(seedHex.utf8))) - let publicKey = try deriveCompressedPublicKey(from: privateKey) return (privateKey, publicKey) } - // MARK: - Account Encryption (PBKDF2-SHA1 + zlib + AES-256-CBC) + // MARK: - Account Encryption (PBKDF2 + zlib + AES-256-CBC) - /// Encrypts `data` with a password using PBKDF2-HMAC-SHA1 + zlib deflate + AES-256-CBC. - /// Compatible with Android (crypto-js uses SHA1 by default) and JS (pako.deflate). - /// Output format: `Base64(IV):Base64(ciphertext)`. nonisolated func encryptWithPassword(_ data: Data, password: String) throws -> String { - let compressed = try rawDeflate(data) - let key = pbkdf2(password: password, salt: "rosetta", iterations: 1000, keyLength: 32, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1)) - let iv = try randomBytes(count: 16) - let ciphertext = try aesCBCEncrypt(compressed, key: key, iv: iv) + let compressed = try CryptoPrimitives.rawDeflate(data) + let key = CryptoPrimitives.pbkdf2( + password: password, salt: "rosetta", iterations: 1000, + keyLength: 32, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1) + ) + let iv = try CryptoPrimitives.randomBytes(count: 16) + let ciphertext = try CryptoPrimitives.aesCBCEncrypt(compressed, key: key, iv: iv) return "\(iv.base64EncodedString()):\(ciphertext.base64EncodedString())" } - /// Decrypts data encrypted with `encryptWithPassword(_:password:)`. - /// Tries PBKDF2-HMAC-SHA1 + zlib (Android-compatible) first, then falls back to - /// legacy PBKDF2-HMAC-SHA256 without compression (old iOS format) for migration. nonisolated func decryptWithPassword(_ encrypted: String, password: String) throws -> Data { let parts = encrypted.components(separatedBy: ":") guard parts.count == 2, @@ -111,16 +98,22 @@ final class CryptoManager: @unchecked Sendable { // Try current format: PBKDF2-SHA1 + AES-CBC + zlib inflate if let result = try? { - let key = pbkdf2(password: password, salt: "rosetta", iterations: 1000, keyLength: 32, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1)) - let decrypted = try aesCBCDecrypt(ciphertext, key: key, iv: iv) - return try rawInflate(decrypted) + let key = CryptoPrimitives.pbkdf2( + password: password, salt: "rosetta", iterations: 1000, + keyLength: 32, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1) + ) + let decrypted = try CryptoPrimitives.aesCBCDecrypt(ciphertext, key: key, iv: iv) + return try CryptoPrimitives.rawInflate(decrypted) }() { return result } // Fallback: legacy iOS format (PBKDF2-SHA256, no compression) - let legacyKey = pbkdf2(password: password, salt: "rosetta", iterations: 1000, keyLength: 32, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256)) - return try aesCBCDecrypt(ciphertext, key: legacyKey, iv: iv) + let legacyKey = CryptoPrimitives.pbkdf2( + password: password, salt: "rosetta", iterations: 1000, + keyLength: 32, prf: CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256) + ) + return try CryptoPrimitives.aesCBCDecrypt(ciphertext, key: legacyKey, iv: iv) } // MARK: - Utilities @@ -129,8 +122,6 @@ final class CryptoManager: @unchecked Sendable { Data(SHA256.hash(data: data)) } - /// Generates the private key hash used for server handshake authentication. - /// Formula: SHA256(privateKeyHex + "rosetta") → lowercase hex string. nonisolated func generatePrivateKeyHash(privateKeyHex: String) -> String { let combined = Data((privateKeyHex + "rosetta").utf8) return sha256(combined).hexString @@ -147,7 +138,6 @@ private extension CryptoManager { let hashBytes = Data(SHA256.hash(data: entropy)) let checksumByte = hashBytes[0] - // Build bit array: 128 entropy bits + 4 checksum bits = 132 bits var bits = [Bool]() bits.reserveCapacity(132) for byte in entropy { @@ -155,12 +145,10 @@ private extension CryptoManager { bits.append((byte >> shift) & 1 == 1) } } - // Top 4 bits of SHA256 hash are the checksum for shift in stride(from: 7, through: 4, by: -1) { bits.append((checksumByte >> shift) & 1 == 1) } - // Split into 12 × 11-bit groups, map to words return try (0..<12).map { chunk in let index = (0..<11).reduce(0) { acc, bit in acc * 2 + (bits[chunk * 11 + bit] ? 1 : 0) @@ -173,7 +161,6 @@ private extension CryptoManager { func entropyFromMnemonic(_ words: [String]) throws -> Data { guard words.count == 12 else { throw CryptoError.invalidMnemonic } - // Convert 12 × 11-bit word indices into a 132-bit array var bits = [Bool]() bits.reserveCapacity(132) for word in words { @@ -183,7 +170,6 @@ private extension CryptoManager { } } - // First 128 bits = entropy, last 4 bits = checksum var entropy = Data(count: 16) for byteIdx in 0..<16 { let value: UInt8 = (0..<8).reduce(0) { acc, bit in @@ -192,7 +178,6 @@ private extension CryptoManager { entropy[byteIdx] = value } - // Verify checksum let hashBytes = Data(SHA256.hash(data: entropy)) let expectedTopNibble = hashBytes[0] >> 4 let actualTopNibble: UInt8 = (0..<4).reduce(0) { acc, bit in @@ -208,172 +193,9 @@ private extension CryptoManager { extension CryptoManager { - /// Computes the 33-byte compressed secp256k1 public key from a 32-byte private key. nonisolated func deriveCompressedPublicKey(from privateKey: Data) throws -> Data { guard privateKey.count == 32 else { throw CryptoError.invalidPrivateKey } - // P256K v0.21+: init is `dataRepresentation:format:`, public key via `dataRepresentation` let signingKey = try P256K.Signing.PrivateKey(dataRepresentation: privateKey, format: .compressed) - // .compressed format → dataRepresentation returns 33-byte compressed public key return signingKey.publicKey.dataRepresentation } } - -// MARK: - Crypto Primitives - -private extension CryptoManager { - - func pbkdf2( - password: String, - salt: String, - iterations: Int, - keyLength: Int, - prf: CCPseudoRandomAlgorithm - ) -> Data { - var derivedKey = Data(repeating: 0, count: keyLength) - derivedKey.withUnsafeMutableBytes { keyPtr in - password.withCString { passPtr in - salt.withCString { saltPtr in - _ = CCKeyDerivationPBKDF( - CCPBKDFAlgorithm(kCCPBKDF2), - passPtr, strlen(passPtr), - saltPtr, strlen(saltPtr), - prf, - UInt32(iterations), - keyPtr.bindMemory(to: UInt8.self).baseAddress!, - keyLength - ) - } - } - } - return derivedKey - } - - func aesCBCEncrypt(_ data: Data, key: Data, iv: Data) throws -> Data { - let outputSize = data.count + kCCBlockSizeAES128 - var ciphertext = Data(count: outputSize) - var numBytes = 0 - let status = ciphertext.withUnsafeMutableBytes { ciphertextPtr in - data.withUnsafeBytes { dataPtr in - key.withUnsafeBytes { keyPtr in - iv.withUnsafeBytes { ivPtr in - CCCrypt( - CCOperation(kCCEncrypt), - CCAlgorithm(kCCAlgorithmAES), - CCOptions(kCCOptionPKCS7Padding), - keyPtr.baseAddress!, key.count, - ivPtr.baseAddress!, - dataPtr.baseAddress!, data.count, - ciphertextPtr.baseAddress!, outputSize, - &numBytes - ) - } - } - } - } - guard status == kCCSuccess else { throw CryptoError.encryptionFailed } - return ciphertext.prefix(numBytes) - } - - func aesCBCDecrypt(_ data: Data, key: Data, iv: Data) throws -> Data { - let outputSize = data.count + kCCBlockSizeAES128 - var plaintext = Data(count: outputSize) - var numBytes = 0 - let status = plaintext.withUnsafeMutableBytes { plaintextPtr in - data.withUnsafeBytes { dataPtr in - key.withUnsafeBytes { keyPtr in - iv.withUnsafeBytes { ivPtr in - CCCrypt( - CCOperation(kCCDecrypt), - CCAlgorithm(kCCAlgorithmAES), - CCOptions(kCCOptionPKCS7Padding), - keyPtr.baseAddress!, key.count, - ivPtr.baseAddress!, - dataPtr.baseAddress!, data.count, - plaintextPtr.baseAddress!, outputSize, - &numBytes - ) - } - } - } - } - guard status == kCCSuccess else { throw CryptoError.decryptionFailed } - return plaintext.prefix(numBytes) - } - - func randomBytes(count: Int) throws -> Data { - var data = Data(count: count) - let status = data.withUnsafeMutableBytes { ptr in - SecRandomCopyBytes(kSecRandomDefault, count, ptr.baseAddress!) - } - guard status == errSecSuccess else { throw CryptoError.invalidEntropy } - return data - } - - // MARK: - zlib Raw Deflate / Inflate - - /// Raw deflate compression (no zlib header, compatible with pako.deflate / Java Deflater(nowrap=true)). - func rawDeflate(_ data: Data) throws -> Data { - // Compression framework uses COMPRESSION_ZLIB which is raw deflate - let sourceSize = data.count - // Worst case: input size + 512 bytes overhead - let destinationSize = sourceSize + 512 - var destination = Data(count: destinationSize) - - let compressedSize = destination.withUnsafeMutableBytes { destPtr in - data.withUnsafeBytes { srcPtr in - compression_encode_buffer( - destPtr.bindMemory(to: UInt8.self).baseAddress!, - destinationSize, - srcPtr.bindMemory(to: UInt8.self).baseAddress!, - sourceSize, - nil, - COMPRESSION_ZLIB - ) - } - } - - guard compressedSize > 0 else { throw CryptoError.compressionFailed } - return destination.prefix(compressedSize) - } - - /// Raw inflate decompression (no zlib header, compatible with pako.inflate / Java Inflater(nowrap=true)). - func rawInflate(_ data: Data) throws -> Data { - let sourceSize = data.count - // Decompressed data can be much larger; start with 4x, retry if needed - var destinationSize = sourceSize * 4 - if destinationSize < 256 { destinationSize = 256 } - - for multiplier in [4, 8, 16, 32] { - destinationSize = sourceSize * multiplier - if destinationSize < 256 { destinationSize = 256 } - var destination = Data(count: destinationSize) - - let decompressedSize = destination.withUnsafeMutableBytes { destPtr in - data.withUnsafeBytes { srcPtr in - compression_decode_buffer( - destPtr.bindMemory(to: UInt8.self).baseAddress!, - destinationSize, - srcPtr.bindMemory(to: UInt8.self).baseAddress!, - sourceSize, - nil, - COMPRESSION_ZLIB - ) - } - } - - if decompressedSize > 0 && decompressedSize < destinationSize { - return destination.prefix(decompressedSize) - } - } - - throw CryptoError.compressionFailed - } -} - -// MARK: - Data Extension - -extension Data { - nonisolated var hexString: String { - map { String(format: "%02x", $0) }.joined() - } -} diff --git a/Rosetta/Core/Crypto/CryptoPrimitives.swift b/Rosetta/Core/Crypto/CryptoPrimitives.swift new file mode 100644 index 0000000..f31dc7e --- /dev/null +++ b/Rosetta/Core/Crypto/CryptoPrimitives.swift @@ -0,0 +1,185 @@ +import Foundation +import CommonCrypto +import Compression + +// MARK: - CryptoPrimitives + +/// Shared low-level cryptographic primitives used by both `CryptoManager` and `MessageCrypto`. +/// Centralizes AES-CBC, PBKDF2, random bytes, and zlib to avoid duplication. +enum CryptoPrimitives { + + // MARK: - AES-256-CBC + + static func aesCBCEncrypt(_ data: Data, key: Data, iv: Data) throws -> Data { + let outputSize = data.count + kCCBlockSizeAES128 + var ciphertext = Data(count: outputSize) + var numBytes = 0 + let status = ciphertext.withUnsafeMutableBytes { ciphertextPtr in + data.withUnsafeBytes { dataPtr in + key.withUnsafeBytes { keyPtr in + iv.withUnsafeBytes { ivPtr in + guard let cBase = ciphertextPtr.baseAddress, + let dBase = dataPtr.baseAddress, + let kBase = keyPtr.baseAddress, + let iBase = ivPtr.baseAddress else { return CCCryptorStatus(kCCParamError) } + return CCCrypt( + CCOperation(kCCEncrypt), + CCAlgorithm(kCCAlgorithmAES), + CCOptions(kCCOptionPKCS7Padding), + kBase, key.count, + iBase, + dBase, data.count, + cBase, outputSize, + &numBytes + ) + } + } + } + } + guard status == kCCSuccess else { throw CryptoError.encryptionFailed } + return ciphertext.prefix(numBytes) + } + + static func aesCBCDecrypt(_ data: Data, key: Data, iv: Data) throws -> Data { + let outputSize = data.count + kCCBlockSizeAES128 + var plaintext = Data(count: outputSize) + var numBytes = 0 + let status = plaintext.withUnsafeMutableBytes { plaintextPtr in + data.withUnsafeBytes { dataPtr in + key.withUnsafeBytes { keyPtr in + iv.withUnsafeBytes { ivPtr in + guard let pBase = plaintextPtr.baseAddress, + let dBase = dataPtr.baseAddress, + let kBase = keyPtr.baseAddress, + let iBase = ivPtr.baseAddress else { return CCCryptorStatus(kCCParamError) } + return CCCrypt( + CCOperation(kCCDecrypt), + CCAlgorithm(kCCAlgorithmAES), + CCOptions(kCCOptionPKCS7Padding), + kBase, key.count, + iBase, + dBase, data.count, + pBase, outputSize, + &numBytes + ) + } + } + } + } + guard status == kCCSuccess else { throw CryptoError.decryptionFailed } + return plaintext.prefix(numBytes) + } + + // MARK: - PBKDF2 + + static func pbkdf2( + password: String, + salt: String, + iterations: Int, + keyLength: Int, + prf: CCPseudoRandomAlgorithm + ) -> Data { + var derivedKey = Data(repeating: 0, count: keyLength) + derivedKey.withUnsafeMutableBytes { keyPtr in + guard let keyBase = keyPtr.bindMemory(to: UInt8.self).baseAddress else { return } + password.withCString { passPtr in + salt.withCString { saltPtr in + _ = CCKeyDerivationPBKDF( + CCPBKDFAlgorithm(kCCPBKDF2), + passPtr, strlen(passPtr), + saltPtr, strlen(saltPtr), + prf, + UInt32(iterations), + keyBase, + keyLength + ) + } + } + } + return derivedKey + } + + // MARK: - Random Bytes + + static func randomBytes(count: Int) throws -> Data { + var data = Data(count: count) + let status = data.withUnsafeMutableBytes { ptr -> OSStatus in + guard let base = ptr.baseAddress else { return errSecAllocate } + return SecRandomCopyBytes(kSecRandomDefault, count, base) + } + guard status == errSecSuccess else { throw CryptoError.invalidEntropy } + return data + } +} + +// MARK: - zlib Raw Deflate / Inflate + +extension CryptoPrimitives { + /// Raw deflate compression (no zlib header, compatible with pako.deflate / Java Deflater(nowrap=true)). + static func rawDeflate(_ data: Data) throws -> Data { + let sourceSize = data.count + let destinationSize = sourceSize + 512 + var destination = Data(count: destinationSize) + + let compressedSize = destination.withUnsafeMutableBytes { destPtr in + data.withUnsafeBytes { srcPtr in + guard let dBase = destPtr.bindMemory(to: UInt8.self).baseAddress, + let sBase = srcPtr.bindMemory(to: UInt8.self).baseAddress else { return 0 } + return compression_encode_buffer(dBase, destinationSize, sBase, sourceSize, nil, COMPRESSION_ZLIB) + } + } + guard compressedSize > 0 else { throw CryptoError.compressionFailed } + return destination.prefix(compressedSize) + } + + /// Raw inflate decompression (no zlib header, compatible with pako.inflate / Java Inflater(nowrap=true)). + static func rawInflate(_ data: Data) throws -> Data { + let sourceSize = data.count + + for multiplier in [4, 8, 16, 32] { + var destinationSize = max(sourceSize * multiplier, 256) + var destination = Data(count: destinationSize) + + let decompressedSize = destination.withUnsafeMutableBytes { destPtr in + data.withUnsafeBytes { srcPtr in + guard let dBase = destPtr.bindMemory(to: UInt8.self).baseAddress, + let sBase = srcPtr.bindMemory(to: UInt8.self).baseAddress else { return 0 } + return compression_decode_buffer(dBase, destinationSize, sBase, sourceSize, nil, COMPRESSION_ZLIB) + } + } + + if decompressedSize > 0 && decompressedSize < destinationSize { + return destination.prefix(decompressedSize) + } + } + throw CryptoError.compressionFailed + } +} + +// MARK: - Data Extensions + +extension Data { + /// Lowercase hex string representation. + nonisolated var hexString: String { + map { String(format: "%02x", $0) }.joined() + } + + /// Initialize from a hex string (case-insensitive). + init(hexString: String) { + let hex = hexString.lowercased() + var data = Data(capacity: hex.count / 2) + var index = hex.startIndex + while index < hex.endIndex { + let nextIndex = hex.index(index, offsetBy: 2, limitedBy: hex.endIndex) ?? hex.endIndex + if nextIndex == hex.endIndex && hex.distance(from: index, to: nextIndex) < 2 { + let byte = UInt8(hex[index...index], radix: 16) ?? 0 + data.append(byte) + } else { + let byte = UInt8(hex[index.. String { - // Step 1: ECDH decrypt the XChaCha20 key+nonce let keyAndNonce = try decryptKeyFromSender(encryptedKey: encryptedKey, myPrivateKeyHex: myPrivateKeyHex) guard keyAndNonce.count >= 56 else { throw CryptoError.invalidData("Key+nonce must be 56 bytes, got \(keyAndNonce.count)") } - let key = keyAndNonce[0..<32] // 32-byte XChaCha20 key - let nonce = keyAndNonce[32..<56] // 24-byte XChaCha20 nonce + let key = keyAndNonce[0..<32] + let nonce = keyAndNonce[32..<56] - // Step 2: XChaCha20-Poly1305 decrypt let ciphertextData = Data(hexString: ciphertext) - let plaintext = try xchacha20Poly1305Decrypt( - ciphertextWithTag: ciphertextData, - key: Data(key), - nonce: Data(nonce) + let plaintext = try XChaCha20Engine.decrypt( + ciphertextWithTag: ciphertextData, key: Data(key), nonce: Data(nonce) ) guard let text = String(data: plaintext, encoding: .utf8) else { throw CryptoError.invalidData("Decrypted data is not valid UTF-8") } - return text } @@ -61,32 +61,25 @@ enum MessageCrypto { throw CryptoError.invalidData("Cannot encode plaintext as UTF-8") } - // Generate random 32-byte key + 24-byte nonce - let key = try randomBytes(count: 32) - let nonce = try randomBytes(count: 24) + let key = try CryptoPrimitives.randomBytes(count: 32) + let nonce = try CryptoPrimitives.randomBytes(count: 24) let keyAndNonce = key + nonce - // XChaCha20-Poly1305 encrypt - let ciphertextWithTag = try xchacha20Poly1305Encrypt( + let ciphertextWithTag = try XChaCha20Engine.encrypt( plaintext: plaintextData, key: key, nonce: nonce ) - // Encrypt key+nonce for recipient via ECDH let chachaKey = try encryptKeyForRecipient( - keyAndNonce: keyAndNonce, - recipientPublicKeyHex: recipientPublicKeyHex + keyAndNonce: keyAndNonce, recipientPublicKeyHex: recipientPublicKeyHex ) - // Encrypt key+nonce for sender (self) via ECDH with sender's own public key let senderPrivKey = try P256K.Signing.PrivateKey( - dataRepresentation: Data(hexString: senderPrivateKeyHex), - format: .compressed + dataRepresentation: Data(hexString: senderPrivateKeyHex), format: .compressed ) let senderPublicKeyHex = senderPrivKey.publicKey.dataRepresentation.hexString let aesChachaKey = try encryptKeyForRecipient( - keyAndNonce: keyAndNonce, - recipientPublicKeyHex: senderPublicKeyHex + keyAndNonce: keyAndNonce, recipientPublicKeyHex: senderPublicKeyHex ) return ( @@ -126,68 +119,43 @@ private extension MessageCrypto { let iv = Data(hexString: ivHex) let encryptedKeyData = Data(hexString: encryptedKeyHex) - // ECDH: compute shared secret = myPublicKey × ephemeralPrivateKey - // Using P256K: create ephemeral private key, derive my public key, compute shared secret - let ephemeralPrivKeyData = Data(hexString: ephemeralPrivateKeyHex) - let myPrivKeyData = Data(hexString: myPrivateKeyHex) - let ephemeralPrivKey = try P256K.KeyAgreement.PrivateKey( - dataRepresentation: ephemeralPrivKeyData, format: .compressed + dataRepresentation: Data(hexString: ephemeralPrivateKeyHex), format: .compressed ) let myPrivKey = try P256K.KeyAgreement.PrivateKey( - dataRepresentation: myPrivKeyData, format: .compressed + dataRepresentation: Data(hexString: myPrivateKeyHex), format: .compressed ) - let myPublicKey = myPrivKey.publicKey // ECDH: ephemeralPrivateKey × myPublicKey → shared point - // P256K returns compressed format (1 + 32 bytes), we need just x-coordinate (bytes 1...32) - let sharedSecret = try ephemeralPrivKey.sharedSecretFromKeyAgreement(with: myPublicKey, format: .compressed) + let sharedSecret = try ephemeralPrivKey.sharedSecretFromKeyAgreement( + with: myPrivKey.publicKey, format: .compressed + ) let sharedSecretData = sharedSecret.withUnsafeBytes { Data($0) } - - // Extract x-coordinate (skip the 1-byte prefix) - let sharedKey: Data - if sharedSecretData.count == 33 { - sharedKey = sharedSecretData[1..<33] - } else if sharedSecretData.count == 32 { - sharedKey = sharedSecretData - } else { - throw CryptoError.invalidData("Unexpected shared secret length: \(sharedSecretData.count)") - } + let sharedKey = extractXCoordinate(from: sharedSecretData) // AES-256-CBC decrypt - let decryptedBytes = try aesCBCDecrypt(encryptedKeyData, key: sharedKey, iv: iv) + let decryptedBytes = try CryptoPrimitives.aesCBCDecrypt(encryptedKeyData, key: sharedKey, iv: iv) // UTF-8 → Latin1 conversion (reverse of JS crypto-js compatibility) - // The Android code does: String(bytes, UTF-8) → toByteArray(ISO_8859_1) guard let utf8String = String(data: decryptedBytes, encoding: .utf8) else { throw CryptoError.invalidData("Decrypted key is not valid UTF-8") } - let originalBytes = Data(utf8String.unicodeScalars.map { UInt8(truncatingIfNeeded: $0.value) }) - - return originalBytes + return Data(utf8String.unicodeScalars.map { UInt8(truncatingIfNeeded: $0.value) }) } /// Encrypts the XChaCha20 key+nonce for a recipient using ECDH. static func encryptKeyForRecipient(keyAndNonce: Data, recipientPublicKeyHex: String) throws -> String { - // Generate ephemeral key pair let ephemeralPrivKey = try P256K.KeyAgreement.PrivateKey() - // Parse recipient public key let recipientPubKey = try P256K.KeyAgreement.PublicKey( dataRepresentation: Data(hexString: recipientPublicKeyHex), format: .compressed ) - // ECDH: ephemeralPrivKey × recipientPubKey → shared secret - let sharedSecret = try ephemeralPrivKey.sharedSecretFromKeyAgreement(with: recipientPubKey, format: .compressed) + let sharedSecret = try ephemeralPrivKey.sharedSecretFromKeyAgreement( + with: recipientPubKey, format: .compressed + ) let sharedSecretData = sharedSecret.withUnsafeBytes { Data($0) } - - // Extract x-coordinate - let sharedKey: Data - if sharedSecretData.count == 33 { - sharedKey = sharedSecretData[1..<33] - } else { - sharedKey = sharedSecretData - } + let sharedKey = extractXCoordinate(from: sharedSecretData) // Convert keyAndNonce bytes to UTF-8 string representation (JS Buffer compatibility) let utf8Representation = String(keyAndNonce.map { Character(UnicodeScalar($0)) }) @@ -195,531 +163,22 @@ private extension MessageCrypto { throw CryptoError.encryptionFailed } - // AES-256-CBC encrypt - let iv = try randomBytes(count: 16) - let ciphertext = try aesCBCEncrypt(dataToEncrypt, key: sharedKey, iv: iv) - - // Get ephemeral private key hex + let iv = try CryptoPrimitives.randomBytes(count: 16) + let ciphertext = try CryptoPrimitives.aesCBCEncrypt(dataToEncrypt, key: sharedKey, iv: iv) let ephemeralPrivKeyHex = ephemeralPrivKey.rawRepresentation.hexString - // Format: Base64(ivHex:ciphertextHex:ephemeralPrivateKeyHex) let combined = "\(iv.hexString):\(ciphertext.hexString):\(ephemeralPrivKeyHex)" guard let base64 = combined.data(using: .utf8)?.base64EncodedString() else { throw CryptoError.encryptionFailed } - return base64 } -} -// MARK: - XChaCha20-Poly1305 - -private extension MessageCrypto { - - static let poly1305TagSize = 16 - - /// XChaCha20-Poly1305 decryption matching Android implementation. - static func xchacha20Poly1305Decrypt(ciphertextWithTag: Data, key: Data, nonce: Data) throws -> Data { - guard ciphertextWithTag.count > poly1305TagSize else { - throw CryptoError.invalidData("Ciphertext too short for Poly1305 tag") + /// Extracts the 32-byte x-coordinate from a compressed ECDH shared secret. + static func extractXCoordinate(from sharedSecretData: Data) -> Data { + if sharedSecretData.count == 33 { + return sharedSecretData[1..<33] } - guard key.count == 32, nonce.count == 24 else { - throw CryptoError.invalidData("Key must be 32 bytes, nonce must be 24 bytes") - } - - let ciphertext = ciphertextWithTag[0..<(ciphertextWithTag.count - poly1305TagSize)] - let tag = ciphertextWithTag[(ciphertextWithTag.count - poly1305TagSize)...] - - // Step 1: HChaCha20 — derive subkey from key + first 16 bytes of nonce - let subkey = hchacha20(key: key, nonce: Data(nonce[0..<16])) - - // Step 2: Build ChaCha20 nonce: [0,0,0,0] + nonce[16..<24] - var chacha20Nonce = Data(repeating: 0, count: 12) - chacha20Nonce[4..<12] = nonce[16..<24] - - // Step 3: Generate Poly1305 key from first 64 bytes of keystream (counter=0) - let poly1305Key = chacha20Block(key: subkey, nonce: chacha20Nonce, counter: 0)[0..<32] - - // Step 4: Verify Poly1305 tag - let computedTag = poly1305MAC( - data: Data(ciphertext), - key: Data(poly1305Key) - ) - - guard constantTimeEqual(Data(tag), computedTag) else { - throw CryptoError.decryptionFailed - } - - // Step 5: Decrypt with ChaCha20 (counter starts at 1) - let plaintext = chacha20Encrypt( - data: Data(ciphertext), - key: subkey, - nonce: chacha20Nonce, - initialCounter: 1 - ) - - return plaintext - } - - /// XChaCha20-Poly1305 encryption. - static func xchacha20Poly1305Encrypt(plaintext: Data, key: Data, nonce: Data) throws -> Data { - guard key.count == 32, nonce.count == 24 else { - throw CryptoError.invalidData("Key must be 32 bytes, nonce must be 24 bytes") - } - - // Step 1: HChaCha20 — derive subkey - let subkey = hchacha20(key: key, nonce: Data(nonce[0..<16])) - - // Step 2: Build ChaCha20 nonce - var chacha20Nonce = Data(repeating: 0, count: 12) - chacha20Nonce[4..<12] = nonce[16..<24] - - // Step 3: Generate Poly1305 key - let poly1305Key = chacha20Block(key: subkey, nonce: chacha20Nonce, counter: 0)[0..<32] - - // Step 4: Encrypt with ChaCha20 (counter starts at 1) - let ciphertext = chacha20Encrypt( - data: plaintext, - key: subkey, - nonce: chacha20Nonce, - initialCounter: 1 - ) - - // Step 5: Compute Poly1305 tag - let tag = poly1305MAC(data: ciphertext, key: Data(poly1305Key)) - - return ciphertext + tag - } -} - -// MARK: - ChaCha20 Core - -private extension MessageCrypto { - - /// ChaCha20 quarter round. - static func quarterRound(_ state: inout [UInt32], _ a: Int, _ b: Int, _ c: Int, _ d: Int) { - state[a] = state[a] &+ state[b]; state[d] ^= state[a]; state[d] = (state[d] << 16) | (state[d] >> 16) - state[c] = state[c] &+ state[d]; state[b] ^= state[c]; state[b] = (state[b] << 12) | (state[b] >> 20) - state[a] = state[a] &+ state[b]; state[d] ^= state[a]; state[d] = (state[d] << 8) | (state[d] >> 24) - state[c] = state[c] &+ state[d]; state[b] ^= state[c]; state[b] = (state[b] << 7) | (state[b] >> 25) - } - - /// Generates a 64-byte ChaCha20 block. - static func chacha20Block(key: Data, nonce: Data, counter: UInt32) -> Data { - var state = [UInt32](repeating: 0, count: 16) - - // Constants: "expand 32-byte k" - state[0] = 0x61707865 - state[1] = 0x3320646e - state[2] = 0x79622d32 - state[3] = 0x6b206574 - - // Key - for i in 0..<8 { - state[4 + i] = key.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } - } - - // Counter - state[12] = counter - - // Nonce - for i in 0..<3 { - state[13 + i] = nonce.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } - } - - var working = state - - // 20 rounds (10 double rounds) - for _ in 0..<10 { - quarterRound(&working, 0, 4, 8, 12) - quarterRound(&working, 1, 5, 9, 13) - quarterRound(&working, 2, 6, 10, 14) - quarterRound(&working, 3, 7, 11, 15) - quarterRound(&working, 0, 5, 10, 15) - quarterRound(&working, 1, 6, 11, 12) - quarterRound(&working, 2, 7, 8, 13) - quarterRound(&working, 3, 4, 9, 14) - } - - // Add initial state - for i in 0..<16 { - working[i] = working[i] &+ state[i] - } - - // Serialize to bytes (little-endian) - var result = Data(count: 64) - for i in 0..<16 { - let val = working[i].littleEndian - result[i * 4] = UInt8(truncatingIfNeeded: val) - result[i * 4 + 1] = UInt8(truncatingIfNeeded: val >> 8) - result[i * 4 + 2] = UInt8(truncatingIfNeeded: val >> 16) - result[i * 4 + 3] = UInt8(truncatingIfNeeded: val >> 24) - } - - return result - } - - /// ChaCha20 stream cipher encryption/decryption. - static func chacha20Encrypt(data: Data, key: Data, nonce: Data, initialCounter: UInt32) -> Data { - var result = Data(count: data.count) - var counter = initialCounter - - for offset in stride(from: 0, to: data.count, by: 64) { - let block = chacha20Block(key: key, nonce: nonce, counter: counter) - let blockSize = min(64, data.count - offset) - - for i in 0.. Data { - var state = [UInt32](repeating: 0, count: 16) - - // Constants - state[0] = 0x61707865 - state[1] = 0x3320646e - state[2] = 0x79622d32 - state[3] = 0x6b206574 - - // Key - for i in 0..<8 { - state[4 + i] = key.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } - } - - // Nonce (16 bytes → 4 uint32s) - for i in 0..<4 { - state[12 + i] = nonce.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } - } - - // 20 rounds - for _ in 0..<10 { - quarterRound(&state, 0, 4, 8, 12) - quarterRound(&state, 1, 5, 9, 13) - quarterRound(&state, 2, 6, 10, 14) - quarterRound(&state, 3, 7, 11, 15) - quarterRound(&state, 0, 5, 10, 15) - quarterRound(&state, 1, 6, 11, 12) - quarterRound(&state, 2, 7, 8, 13) - quarterRound(&state, 3, 4, 9, 14) - } - - // Output: first 4 words + last 4 words - var result = Data(count: 32) - for i in 0..<4 { - let val = state[i].littleEndian - result[i * 4] = UInt8(truncatingIfNeeded: val) - result[i * 4 + 1] = UInt8(truncatingIfNeeded: val >> 8) - result[i * 4 + 2] = UInt8(truncatingIfNeeded: val >> 16) - result[i * 4 + 3] = UInt8(truncatingIfNeeded: val >> 24) - } - for i in 0..<4 { - let val = state[12 + i].littleEndian - result[16 + i * 4] = UInt8(truncatingIfNeeded: val) - result[16 + i * 4 + 1] = UInt8(truncatingIfNeeded: val >> 8) - result[16 + i * 4 + 2] = UInt8(truncatingIfNeeded: val >> 16) - result[16 + i * 4 + 3] = UInt8(truncatingIfNeeded: val >> 24) - } - - return result - } -} - -// MARK: - Poly1305 - -private extension MessageCrypto { - - /// Poly1305 MAC computation matching the AEAD construction. - static func poly1305MAC(data: Data, key: Data) -> Data { - // Clamp r (first 16 bytes of key) - var r = [UInt8](key[0..<16]) - r[3] &= 15; r[7] &= 15; r[11] &= 15; r[15] &= 15 - r[4] &= 252; r[8] &= 252; r[12] &= 252 - - // s = last 16 bytes of key - let s = [UInt8](key[16..<32]) - - // Convert r and s to big integers using UInt128-like arithmetic - var rVal: (UInt64, UInt64) = (0, 0) // (low, high) - for i in stride(from: 15, through: 8, by: -1) { - rVal.1 = rVal.1 << 8 | UInt64(r[i]) - } - for i in stride(from: 7, through: 0, by: -1) { - rVal.0 = rVal.0 << 8 | UInt64(r[i]) - } - - // Use arrays for big number arithmetic (limbs approach) - // For simplicity and correctness, use a big-number representation - var accumulator = [UInt64](repeating: 0, count: 5) // 130-bit number in 26-bit limbs - let rLimbs = toLimbs26(r) - let p: UInt64 = (1 << 26) // 2^26 - - // Build padded data: data + padding to 16-byte boundary + lengths - var macInput = Data(data) - let padding = (16 - (data.count % 16)) % 16 - if padding > 0 { - macInput.append(Data(repeating: 0, count: padding)) - } - // AAD length (0 for our case — no associated data) - macInput.append(Data(repeating: 0, count: 8)) - // Ciphertext length (little-endian 64-bit) - var ctLen = UInt64(data.count).littleEndian - macInput.append(Data(bytes: &ctLen, count: 8)) - - // Process in 16-byte blocks - for offset in stride(from: 0, to: macInput.count, by: 16) { - let blockEnd = min(offset + 16, macInput.count) - var block = [UInt8](macInput[offset.. [UInt64] { - let b = bytes.count >= 16 ? bytes : bytes + [UInt8](repeating: 0, count: 16 - bytes.count) - var val: UInt64 = 0 - var limbs = [UInt64](repeating: 0, count: 5) - - // Read as little-endian 128-bit number - for i in stride(from: 15, through: 0, by: -1) { - val = val << 8 | UInt64(b[i]) - if i == 0 { - limbs[0] = val & 0x3FFFFFF - limbs[1] = (val >> 26) & 0x3FFFFFF - limbs[2] = (val >> 52) & 0x3FFFFFF - } - } - - // Re-read properly - var full = [UInt8](repeating: 0, count: 17) - for i in 0..> 26) & 0x3FFFFFF - limbs[2] = ((lo >> 52) | (hi << 12)) & 0x3FFFFFF - limbs[3] = (hi >> 14) & 0x3FFFFFF - limbs[4] = (hi >> 40) & 0x3FFFFFF - - return limbs - } - - /// Multiply two numbers in 26-bit limb form, reduce mod 2^130 - 5. - static func poly1305Multiply(_ a: [UInt64], _ r: [UInt64]) -> [UInt64] { - // Full multiply into 10 limbs, then reduce - let r0 = r[0], r1 = r[1], r2 = r[2], r3 = r[3], r4 = r[4] - let s1 = r1 * 5, s2 = r2 * 5, s3 = r3 * 5, s4 = r4 * 5 - let a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4] - - var h0 = a0 * r0 + a1 * s4 + a2 * s3 + a3 * s2 + a4 * s1 - var h1 = a0 * r1 + a1 * r0 + a2 * s4 + a3 * s3 + a4 * s2 - var h2 = a0 * r2 + a1 * r1 + a2 * r0 + a3 * s4 + a4 * s3 - var h3 = a0 * r3 + a1 * r2 + a2 * r1 + a3 * r0 + a4 * s4 - var h4 = a0 * r4 + a1 * r3 + a2 * r2 + a3 * r1 + a4 * r0 - - // Carry propagation - var c: UInt64 - c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF - c = h1 >> 26; h2 += c; h1 &= 0x3FFFFFF - c = h2 >> 26; h3 += c; h2 &= 0x3FFFFFF - c = h3 >> 26; h4 += c; h3 &= 0x3FFFFFF - c = h4 >> 26; h0 += c * 5; h4 &= 0x3FFFFFF - c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF - - return [h0, h1, h2, h3, h4] - } - - /// Final reduction and add s. - static func poly1305Freeze(_ h: [UInt64], s: [UInt8]) -> [UInt8] { - var h0 = h[0], h1 = h[1], h2 = h[2], h3 = h[3], h4 = h[4] - - // Full carry - var c: UInt64 - c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF - c = h1 >> 26; h2 += c; h1 &= 0x3FFFFFF - c = h2 >> 26; h3 += c; h2 &= 0x3FFFFFF - c = h3 >> 26; h4 += c; h3 &= 0x3FFFFFF - c = h4 >> 26; h0 += c * 5; h4 &= 0x3FFFFFF - c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF - - // Compute h + -(2^130 - 5) = h - p - var g0 = h0 &+ 5; c = g0 >> 26; g0 &= 0x3FFFFFF - var g1 = h1 &+ c; c = g1 >> 26; g1 &= 0x3FFFFFF - var g2 = h2 &+ c; c = g2 >> 26; g2 &= 0x3FFFFFF - var g3 = h3 &+ c; c = g3 >> 26; g3 &= 0x3FFFFFF - let g4 = h4 &+ c &- (1 << 26) - - // If g4 didn't underflow (bit 63 not set), use g (h >= p) - let mask = (g4 >> 63) &- 1 // 0 if g4 underflowed, 0xFFF...F otherwise - let nmask = ~mask - h0 = (h0 & nmask) | (g0 & mask) - h1 = (h1 & nmask) | (g1 & mask) - h2 = (h2 & nmask) | (g2 & mask) - h3 = (h3 & nmask) | (g3 & mask) - h4 = (h4 & nmask) | (g4 & mask) - - // Reassemble into 128-bit number - let f0 = h0 | (h1 << 26) - let f1 = (h1 >> 38) | (h2 << 12) | (h3 << 38) - let f2 = (h3 >> 26) | (h4 << 0) // unused high bits - - // Convert to two 64-bit values - let lo = h0 | (h1 << 26) | (h2 << 52) - let hi = (h2 >> 12) | (h3 << 14) | (h4 << 40) - - // Add s (little-endian) - var sLo: UInt64 = 0 - var sHi: UInt64 = 0 - for i in stride(from: 7, through: 0, by: -1) { - sLo = sLo << 8 | UInt64(s[i]) - } - for i in stride(from: 15, through: 8, by: -1) { - sHi = sHi << 8 | UInt64(s[i]) - } - - var resultLo = lo &+ sLo - var carry: UInt64 = resultLo < lo ? 1 : 0 - var resultHi = hi &+ sHi &+ carry - - // Output 16 bytes little-endian - var output = [UInt8](repeating: 0, count: 16) - for i in 0..<8 { - output[i] = UInt8(truncatingIfNeeded: resultLo >> (i * 8)) - } - for i in 0..<8 { - output[8 + i] = UInt8(truncatingIfNeeded: resultHi >> (i * 8)) - } - - return output - } - - static func constantTimeEqual(_ a: Data, _ b: Data) -> Bool { - guard a.count == b.count else { return false } - var result: UInt8 = 0 - for i in 0.. Data { - let outputSize = data.count + kCCBlockSizeAES128 - var ciphertext = Data(count: outputSize) - var numBytes = 0 - let status = ciphertext.withUnsafeMutableBytes { ciphertextPtr in - data.withUnsafeBytes { dataPtr in - key.withUnsafeBytes { keyPtr in - iv.withUnsafeBytes { ivPtr in - CCCrypt( - CCOperation(kCCEncrypt), - CCAlgorithm(kCCAlgorithmAES), - CCOptions(kCCOptionPKCS7Padding), - keyPtr.baseAddress!, key.count, - ivPtr.baseAddress!, - dataPtr.baseAddress!, data.count, - ciphertextPtr.baseAddress!, outputSize, - &numBytes - ) - } - } - } - } - guard status == kCCSuccess else { throw CryptoError.encryptionFailed } - return ciphertext.prefix(numBytes) - } - - static func aesCBCDecrypt(_ data: Data, key: Data, iv: Data) throws -> Data { - let outputSize = data.count + kCCBlockSizeAES128 - var plaintext = Data(count: outputSize) - var numBytes = 0 - let status = plaintext.withUnsafeMutableBytes { plaintextPtr in - data.withUnsafeBytes { dataPtr in - key.withUnsafeBytes { keyPtr in - iv.withUnsafeBytes { ivPtr in - CCCrypt( - CCOperation(kCCDecrypt), - CCAlgorithm(kCCAlgorithmAES), - CCOptions(kCCOptionPKCS7Padding), - keyPtr.baseAddress!, key.count, - ivPtr.baseAddress!, - dataPtr.baseAddress!, data.count, - plaintextPtr.baseAddress!, outputSize, - &numBytes - ) - } - } - } - } - guard status == kCCSuccess else { throw CryptoError.decryptionFailed } - return plaintext.prefix(numBytes) - } - - static func randomBytes(count: Int) throws -> Data { - var data = Data(count: count) - let status = data.withUnsafeMutableBytes { ptr in - SecRandomCopyBytes(kSecRandomDefault, count, ptr.baseAddress!) - } - guard status == errSecSuccess else { throw CryptoError.invalidEntropy } - return data - } -} - -// MARK: - Data Hex Extension - -extension Data { - /// Initialize from a hex string. - init(hexString: String) { - let hex = hexString.lowercased() - var data = Data(capacity: hex.count / 2) - var index = hex.startIndex - while index < hex.endIndex { - let nextIndex = hex.index(index, offsetBy: 2, limitedBy: hex.endIndex) ?? hex.endIndex - if nextIndex == hex.endIndex && hex.distance(from: index, to: nextIndex) < 2 { - // Odd hex character at end - let byte = UInt8(hex[index...index], radix: 16) ?? 0 - data.append(byte) - } else { - let byte = UInt8(hex[index.. Data { + // Clamp r (first 16 bytes of key) + var r = [UInt8](key[0..<16]) + r[3] &= 15; r[7] &= 15; r[11] &= 15; r[15] &= 15 + r[4] &= 252; r[8] &= 252; r[12] &= 252 + + // s = last 16 bytes of key + let s = [UInt8](key[16..<32]) + + var accumulator = [UInt64](repeating: 0, count: 5) + let rLimbs = toLimbs26(r) + + // Build padded data: data + padding to 16-byte boundary + lengths + var macInput = Data(data) + let padding = (16 - (data.count % 16)) % 16 + if padding > 0 { + macInput.append(Data(repeating: 0, count: padding)) + } + // AAD length (0 — no associated data) + macInput.append(Data(repeating: 0, count: 8)) + // Ciphertext length (little-endian 64-bit) + var ctLen = UInt64(data.count).littleEndian + macInput.append(Data(bytes: &ctLen, count: 8)) + + // Process in 16-byte blocks + for offset in stride(from: 0, to: macInput.count, by: 16) { + let blockEnd = min(offset + 16, macInput.count) + var block = [UInt8](macInput[offset.. [UInt64] { + let b = bytes.count >= 16 ? bytes : bytes + [UInt8](repeating: 0, count: 16 - bytes.count) + + var full = [UInt8](repeating: 0, count: 17) + for i in 0..> 26) & 0x3FFFFFF, + ((lo >> 52) | (hi << 12)) & 0x3FFFFFF, + (hi >> 14) & 0x3FFFFFF, + (hi >> 40) & 0x3FFFFFF + ] + } + + /// Multiply two numbers in 26-bit limb form, reduce mod 2^130 - 5. + static func multiply(_ a: [UInt64], _ r: [UInt64]) -> [UInt64] { + let r0 = r[0], r1 = r[1], r2 = r[2], r3 = r[3], r4 = r[4] + let s1 = r1 * 5, s2 = r2 * 5, s3 = r3 * 5, s4 = r4 * 5 + let a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4] + + var h0 = a0 * r0 + a1 * s4 + a2 * s3 + a3 * s2 + a4 * s1 + var h1 = a0 * r1 + a1 * r0 + a2 * s4 + a3 * s3 + a4 * s2 + var h2 = a0 * r2 + a1 * r1 + a2 * r0 + a3 * s4 + a4 * s3 + var h3 = a0 * r3 + a1 * r2 + a2 * r1 + a3 * r0 + a4 * s4 + var h4 = a0 * r4 + a1 * r3 + a2 * r2 + a3 * r1 + a4 * r0 + + var c: UInt64 + c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF + c = h1 >> 26; h2 += c; h1 &= 0x3FFFFFF + c = h2 >> 26; h3 += c; h2 &= 0x3FFFFFF + c = h3 >> 26; h4 += c; h3 &= 0x3FFFFFF + c = h4 >> 26; h0 += c * 5; h4 &= 0x3FFFFFF + c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF + + return [h0, h1, h2, h3, h4] + } + + /// Final reduction mod 2^130-5 and add s. + static func freeze(_ h: [UInt64], s: [UInt8]) -> [UInt8] { + var h0 = h[0], h1 = h[1], h2 = h[2], h3 = h[3], h4 = h[4] + + var c: UInt64 + c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF + c = h1 >> 26; h2 += c; h1 &= 0x3FFFFFF + c = h2 >> 26; h3 += c; h2 &= 0x3FFFFFF + c = h3 >> 26; h4 += c; h3 &= 0x3FFFFFF + c = h4 >> 26; h0 += c * 5; h4 &= 0x3FFFFFF + c = h0 >> 26; h1 += c; h0 &= 0x3FFFFFF + + // Compute h + -(2^130 - 5) = h - p + var g0 = h0 &+ 5; c = g0 >> 26; g0 &= 0x3FFFFFF + var g1 = h1 &+ c; c = g1 >> 26; g1 &= 0x3FFFFFF + var g2 = h2 &+ c; c = g2 >> 26; g2 &= 0x3FFFFFF + var g3 = h3 &+ c; c = g3 >> 26; g3 &= 0x3FFFFFF + let g4 = h4 &+ c &- (1 << 26) + + // If g4 didn't underflow, use g (h >= p) + let mask = (g4 >> 63) &- 1 + let nmask = ~mask + h0 = (h0 & nmask) | (g0 & mask) + h1 = (h1 & nmask) | (g1 & mask) + h2 = (h2 & nmask) | (g2 & mask) + h3 = (h3 & nmask) | (g3 & mask) + h4 = (h4 & nmask) | (g4 & mask) + + // Convert to two 64-bit values + let lo = h0 | (h1 << 26) | (h2 << 52) + let hi = (h2 >> 12) | (h3 << 14) | (h4 << 40) + + // Add s (little-endian) + var sLo: UInt64 = 0 + var sHi: UInt64 = 0 + for i in stride(from: 7, through: 0, by: -1) { sLo = sLo << 8 | UInt64(s[i]) } + for i in stride(from: 15, through: 8, by: -1) { sHi = sHi << 8 | UInt64(s[i]) } + + let resultLo = lo &+ sLo + let carry: UInt64 = resultLo < lo ? 1 : 0 + let resultHi = hi &+ sHi &+ carry + + var output = [UInt8](repeating: 0, count: 16) + for i in 0..<8 { output[i] = UInt8(truncatingIfNeeded: resultLo >> (i * 8)) } + for i in 0..<8 { output[8 + i] = UInt8(truncatingIfNeeded: resultHi >> (i * 8)) } + return output + } +} diff --git a/Rosetta/Core/Crypto/XChaCha20Engine.swift b/Rosetta/Core/Crypto/XChaCha20Engine.swift new file mode 100644 index 0000000..9e678c6 --- /dev/null +++ b/Rosetta/Core/Crypto/XChaCha20Engine.swift @@ -0,0 +1,201 @@ +import Foundation + +// MARK: - XChaCha20Engine + +/// XChaCha20-Poly1305 AEAD cipher implementation. +/// Matches the Android `MessageCrypto` XChaCha20 implementation for cross-platform compatibility. +enum XChaCha20Engine { + + static let poly1305TagSize = 16 + + // MARK: - XChaCha20-Poly1305 Decrypt + + /// Decrypts ciphertext+tag using XChaCha20-Poly1305. + static func decrypt(ciphertextWithTag: Data, key: Data, nonce: Data) throws -> Data { + guard ciphertextWithTag.count > poly1305TagSize else { + throw CryptoError.invalidData("Ciphertext too short for Poly1305 tag") + } + guard key.count == 32, nonce.count == 24 else { + throw CryptoError.invalidData("Key must be 32 bytes, nonce must be 24 bytes") + } + + let ciphertext = ciphertextWithTag[0..<(ciphertextWithTag.count - poly1305TagSize)] + let tag = ciphertextWithTag[(ciphertextWithTag.count - poly1305TagSize)...] + + // Step 1: HChaCha20 — derive subkey from key + first 16 bytes of nonce + let subkey = hchacha20(key: key, nonce: Data(nonce[0..<16])) + + // Step 2: Build ChaCha20 nonce: [0,0,0,0] + nonce[16..<24] + var chacha20Nonce = Data(repeating: 0, count: 12) + chacha20Nonce[4..<12] = nonce[16..<24] + + // Step 3: Generate Poly1305 key from first 64 bytes of keystream (counter=0) + let poly1305Key = chacha20Block(key: subkey, nonce: chacha20Nonce, counter: 0)[0..<32] + + // Step 4: Verify Poly1305 tag + let computedTag = Poly1305Engine.mac(data: Data(ciphertext), key: Data(poly1305Key)) + + guard constantTimeEqual(Data(tag), computedTag) else { + throw CryptoError.decryptionFailed + } + + // Step 5: Decrypt with ChaCha20 (counter starts at 1) + return chacha20Encrypt( + data: Data(ciphertext), key: subkey, nonce: chacha20Nonce, initialCounter: 1 + ) + } + + // MARK: - XChaCha20-Poly1305 Encrypt + + /// Encrypts plaintext using XChaCha20-Poly1305. + static func encrypt(plaintext: Data, key: Data, nonce: Data) throws -> Data { + guard key.count == 32, nonce.count == 24 else { + throw CryptoError.invalidData("Key must be 32 bytes, nonce must be 24 bytes") + } + + // Step 1: HChaCha20 — derive subkey + let subkey = hchacha20(key: key, nonce: Data(nonce[0..<16])) + + // Step 2: Build ChaCha20 nonce + var chacha20Nonce = Data(repeating: 0, count: 12) + chacha20Nonce[4..<12] = nonce[16..<24] + + // Step 3: Generate Poly1305 key + let poly1305Key = chacha20Block(key: subkey, nonce: chacha20Nonce, counter: 0)[0..<32] + + // Step 4: Encrypt with ChaCha20 (counter starts at 1) + let ciphertext = chacha20Encrypt( + data: plaintext, key: subkey, nonce: chacha20Nonce, initialCounter: 1 + ) + + // Step 5: Compute Poly1305 tag + let tag = Poly1305Engine.mac(data: ciphertext, key: Data(poly1305Key)) + + return ciphertext + tag + } +} + +// MARK: - ChaCha20 Core + +extension XChaCha20Engine { + + /// ChaCha20 quarter round. + static func quarterRound(_ state: inout [UInt32], _ a: Int, _ b: Int, _ c: Int, _ d: Int) { + state[a] = state[a] &+ state[b]; state[d] ^= state[a]; state[d] = (state[d] << 16) | (state[d] >> 16) + state[c] = state[c] &+ state[d]; state[b] ^= state[c]; state[b] = (state[b] << 12) | (state[b] >> 20) + state[a] = state[a] &+ state[b]; state[d] ^= state[a]; state[d] = (state[d] << 8) | (state[d] >> 24) + state[c] = state[c] &+ state[d]; state[b] ^= state[c]; state[b] = (state[b] << 7) | (state[b] >> 25) + } + + /// Generates a 64-byte ChaCha20 block. + static func chacha20Block(key: Data, nonce: Data, counter: UInt32) -> Data { + var state = [UInt32](repeating: 0, count: 16) + + // Constants: "expand 32-byte k" + state[0] = 0x61707865; state[1] = 0x3320646e + state[2] = 0x79622d32; state[3] = 0x6b206574 + + // Key (8 × UInt32, little-endian) + for i in 0..<8 { + state[4 + i] = key.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } + } + + state[12] = counter + + // Nonce (3 × UInt32, little-endian) + for i in 0..<3 { + state[13 + i] = nonce.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } + } + + var working = state + + // 20 rounds (10 double rounds) + for _ in 0..<10 { + quarterRound(&working, 0, 4, 8, 12); quarterRound(&working, 1, 5, 9, 13) + quarterRound(&working, 2, 6, 10, 14); quarterRound(&working, 3, 7, 11, 15) + quarterRound(&working, 0, 5, 10, 15); quarterRound(&working, 1, 6, 11, 12) + quarterRound(&working, 2, 7, 8, 13); quarterRound(&working, 3, 4, 9, 14) + } + + // Add initial state + for i in 0..<16 { working[i] = working[i] &+ state[i] } + + // Serialize to bytes (little-endian) + var result = Data(count: 64) + for i in 0..<16 { + let val = working[i].littleEndian + result[i * 4] = UInt8(truncatingIfNeeded: val) + result[i * 4 + 1] = UInt8(truncatingIfNeeded: val >> 8) + result[i * 4 + 2] = UInt8(truncatingIfNeeded: val >> 16) + result[i * 4 + 3] = UInt8(truncatingIfNeeded: val >> 24) + } + return result + } + + /// ChaCha20 stream cipher encryption/decryption. + static func chacha20Encrypt(data: Data, key: Data, nonce: Data, initialCounter: UInt32) -> Data { + var result = Data(count: data.count) + var counter = initialCounter + + for offset in stride(from: 0, to: data.count, by: 64) { + let block = chacha20Block(key: key, nonce: nonce, counter: counter) + let blockSize = min(64, data.count - offset) + + for i in 0.. Data { + var state = [UInt32](repeating: 0, count: 16) + + state[0] = 0x61707865; state[1] = 0x3320646e + state[2] = 0x79622d32; state[3] = 0x6b206574 + + for i in 0..<8 { + state[4 + i] = key.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } + } + for i in 0..<4 { + state[12 + i] = nonce.withUnsafeBytes { $0.load(fromByteOffset: i * 4, as: UInt32.self).littleEndian } + } + + for _ in 0..<10 { + quarterRound(&state, 0, 4, 8, 12); quarterRound(&state, 1, 5, 9, 13) + quarterRound(&state, 2, 6, 10, 14); quarterRound(&state, 3, 7, 11, 15) + quarterRound(&state, 0, 5, 10, 15); quarterRound(&state, 1, 6, 11, 12) + quarterRound(&state, 2, 7, 8, 13); quarterRound(&state, 3, 4, 9, 14) + } + + // Output: first 4 words + last 4 words + var result = Data(count: 32) + for i in 0..<4 { + let val = state[i].littleEndian + result[i * 4] = UInt8(truncatingIfNeeded: val) + result[i * 4 + 1] = UInt8(truncatingIfNeeded: val >> 8) + result[i * 4 + 2] = UInt8(truncatingIfNeeded: val >> 16) + result[i * 4 + 3] = UInt8(truncatingIfNeeded: val >> 24) + } + for i in 0..<4 { + let val = state[12 + i].littleEndian + result[16 + i * 4] = UInt8(truncatingIfNeeded: val) + result[16 + i * 4 + 1] = UInt8(truncatingIfNeeded: val >> 8) + result[16 + i * 4 + 2] = UInt8(truncatingIfNeeded: val >> 16) + result[16 + i * 4 + 3] = UInt8(truncatingIfNeeded: val >> 24) + } + return result + } + + /// Constant-time comparison of two Data objects. + static func constantTimeEqual(_ a: Data, _ b: Data) -> Bool { + guard a.count == b.count else { return false } + var result: UInt8 = 0 + for i in 0.. = [safePublicKey, updatesPublicKey] + + static func isSystemAccount(_ publicKey: String) -> Bool { + systemKeys.contains(publicKey) + } +} + // MARK: - DeliveryStatus enum DeliveryStatus: Int, Codable { @@ -28,7 +42,7 @@ struct Dialog: Identifiable, Codable, Equatable { var isOnline: Bool var lastSeen: Int64 - var isVerified: Bool + var verified: Int // 0 = none, 1 = public figure/brand, 2 = Rosetta admin, 3+ = group admin var iHaveSent: Bool // I have sent at least one message (chat vs request) var isPinned: Bool var isMuted: Bool @@ -40,6 +54,20 @@ struct Dialog: Identifiable, Codable, Equatable { var isSavedMessages: Bool { opponentKey == account } + /// Client-side heuristic matching Android: badge shown if verified > 0 OR isRosettaOfficial. + var isRosettaOfficial: Bool { + opponentTitle.caseInsensitiveCompare("Rosetta") == .orderedSame || + opponentUsername.caseInsensitiveCompare("rosetta") == .orderedSame || + SystemAccounts.isSystemAccount(opponentKey) + } + + /// Effective verification level for UI display. + var effectiveVerified: Int { + if verified > 0 { return verified } + if isRosettaOfficial { return 1 } + return 0 + } + var avatarColorIndex: Int { RosettaColors.avatarColorIndex(for: opponentKey) } diff --git a/Rosetta/Core/Data/Repositories/DialogRepository.swift b/Rosetta/Core/Data/Repositories/DialogRepository.swift index 7a8b962..f61094c 100644 --- a/Rosetta/Core/Data/Repositories/DialogRepository.swift +++ b/Rosetta/Core/Data/Repositories/DialogRepository.swift @@ -41,7 +41,7 @@ final class DialogRepository { unreadCount: 0, isOnline: false, lastSeen: 0, - isVerified: false, + verified: 0, iHaveSent: false, isPinned: false, isMuted: false, @@ -78,10 +78,11 @@ final class DialogRepository { dialogs[opponentKey] = dialog } - func updateUserInfo(publicKey: String, title: String, username: String) { + func updateUserInfo(publicKey: String, title: String, username: String, verified: Int = 0) { guard var dialog = dialogs[publicKey] else { return } if !title.isEmpty { dialog.opponentTitle = title } if !username.isEmpty { dialog.opponentUsername = username } + if verified > 0 { dialog.verified = max(dialog.verified, verified) } dialogs[publicKey] = dialog } diff --git a/Rosetta/Core/Network/Protocol/ProtocolManager.swift b/Rosetta/Core/Network/Protocol/ProtocolManager.swift index 50dae06..24c6f56 100644 --- a/Rosetta/Core/Network/Protocol/ProtocolManager.swift +++ b/Rosetta/Core/Network/Protocol/ProtocolManager.swift @@ -176,22 +176,25 @@ final class ProtocolManager: @unchecked Sendable { // MARK: - Packet Handling private func handleIncomingData(_ data: Data) { - print("[Protocol] Incoming data: \(data.count) bytes, first bytes: \(data.prefix(min(8, data.count)).map { String(format: "%02x", $0) }.joined(separator: " "))") + #if DEBUG + if data.count >= 2 { + let peekStream = Stream(data: data) + let rawId = peekStream.readInt16() + Self.logger.debug("📥 Incoming packet 0x\(String(rawId, radix: 16)), size: \(data.count)") + } + #endif guard let (packetId, packet) = PacketRegistry.decode(from: data) else { - // Try to read the packet ID manually to see what it is + #if DEBUG if data.count >= 2 { let stream = Stream(data: data) let rawId = stream.readInt16() - print("[Protocol] Unknown packet ID: 0x\(String(rawId, radix: 16)) (\(rawId)), data size: \(data.count)") - } else { - print("[Protocol] Packet too small: \(data.count) bytes") + Self.logger.debug("Unknown packet ID: 0x\(String(rawId, radix: 16)), size: \(data.count)") } + #endif return } - print("[Protocol] Received packet 0x\(String(packetId, radix: 16)) (\(type(of: packet)))") - switch packetId { case 0x00: if let p = packet as? PacketHandshake { @@ -199,17 +202,15 @@ final class ProtocolManager: @unchecked Sendable { } case 0x01: if let p = packet as? PacketUserInfo { - print("[Protocol] UserInfo received: username='\(p.username)', title='\(p.title)'") onUserInfoReceived?(p) } case 0x02: if let p = packet as? PacketResult { - let code = ResultCode(rawValue: p.resultCode) - print("[Protocol] Result received: code=\(p.resultCode) (\(code.map { "\($0)" } ?? "unknown"))") + let _ = ResultCode(rawValue: p.resultCode) } case 0x03: if let p = packet as? PacketSearch { - print("[Protocol] Search result received: \(p.users.count) users") + Self.logger.debug("📥 Search result: \(p.users.count) users, callback=\(self.onSearchResult != nil)") onSearchResult?(p) } case 0x05: diff --git a/Rosetta/Core/Services/SessionManager.swift b/Rosetta/Core/Services/SessionManager.swift index c077918..6b153b5 100644 --- a/Rosetta/Core/Services/SessionManager.swift +++ b/Rosetta/Core/Services/SessionManager.swift @@ -178,7 +178,7 @@ final class SessionManager { proto.onUserInfoReceived = { [weak self] packet in guard let self else { return } Task { @MainActor in - print("[Session] UserInfo received: username='\(packet.username)', title='\(packet.title)'") + Self.logger.debug("UserInfo received: username='\(packet.username)', title='\(packet.title)'") if !packet.title.isEmpty { self.displayName = packet.title AccountManager.shared.updateProfile(displayName: packet.title, username: nil) @@ -210,10 +210,9 @@ final class SessionManager { userInfoPacket.avatar = "" userInfoPacket.title = name userInfoPacket.privateKey = hash - print("[Session] Sending UserInfo: username='\(uname)', title='\(name)'") ProtocolManager.shared.sendPacket(userInfoPacket) } else { - print("[Session] Skipping UserInfo — no profile data to send") + Self.logger.debug("Skipping UserInfo — no profile data to send") } } } diff --git a/Rosetta/Core/Utils/SystemAccountHelpers.swift b/Rosetta/Core/Utils/SystemAccountHelpers.swift new file mode 100644 index 0000000..95d7216 --- /dev/null +++ b/Rosetta/Core/Utils/SystemAccountHelpers.swift @@ -0,0 +1,12 @@ +import Foundation + +// MARK: - System Account Helpers + +/// Client-side heuristic for Rosetta-official accounts (matches Android logic). +/// Returns `true` if the user's title or username matches "Rosetta" (case-insensitive) +/// or if the public key belongs to a system account. +func isRosettaOfficial(_ user: SearchUser) -> Bool { + user.title.caseInsensitiveCompare("Rosetta") == .orderedSame || + user.username.caseInsensitiveCompare("rosetta") == .orderedSame || + SystemAccounts.isSystemAccount(user.publicKey) +} diff --git a/Rosetta/DesignSystem/Components/GlassModifiers.swift b/Rosetta/DesignSystem/Components/GlassModifiers.swift new file mode 100644 index 0000000..0db332e --- /dev/null +++ b/Rosetta/DesignSystem/Components/GlassModifiers.swift @@ -0,0 +1,41 @@ +import SwiftUI + +// MARK: - Glass Navigation Bar Modifier + +/// Applies glassmorphism effect to the navigation bar on iOS 26+, falling back to ultra-thin material. +struct GlassNavBarModifier: ViewModifier { + func body(content: Content) -> some View { + if #available(iOS 26, *) { + content + } else { + content + .toolbarBackground(.ultraThinMaterial, for: .navigationBar) + } + } +} + +extension View { + func applyGlassNavBar() -> some View { + modifier(GlassNavBarModifier()) + } +} + +// MARK: - Glass Search Bar Modifier + +/// Applies glassmorphism capsule effect on iOS 26+. +struct GlassSearchBarModifier: ViewModifier { + func body(content: Content) -> some View { + if #available(iOS 26, *) { + content + .glassEffect(.regular, in: .capsule) + } else { + content + } + } +} + +extension View { + func applyGlassSearchBar() -> some View { + modifier(GlassSearchBarModifier()) + } +} diff --git a/Rosetta/DesignSystem/Components/RosettaTabBar.swift b/Rosetta/DesignSystem/Components/RosettaTabBar.swift index da34410..761e0e1 100644 --- a/Rosetta/DesignSystem/Components/RosettaTabBar.swift +++ b/Rosetta/DesignSystem/Components/RosettaTabBar.swift @@ -60,8 +60,7 @@ struct RosettaTabBar: View { searchPill } .padding(.horizontal, 25) - .padding(.top, 16) - .padding(.bottom, safeAreaBottom > 0 ? safeAreaBottom : 25) + .padding(.top, 4) } } diff --git a/Rosetta/DesignSystem/Components/VerifiedBadge.swift b/Rosetta/DesignSystem/Components/VerifiedBadge.swift new file mode 100644 index 0000000..e125204 --- /dev/null +++ b/Rosetta/DesignSystem/Components/VerifiedBadge.swift @@ -0,0 +1,76 @@ +import SwiftUI + +// MARK: - VerifiedBadge + +/// Displays a verified rosette badge for accounts with server-assigned verification. +/// +/// Verification levels (from server `verified` field): +/// - `0` — not verified (badge hidden) +/// - `1` — public figure, brand, or organization +/// - `2` — official Rosetta administration account +/// - `3+` — group administrator +/// +/// Tapping the badge presents a dialog explaining the verification level. +struct VerifiedBadge: View { + let verified: Int + var size: CGFloat = 16 + var badgeTint: Color? + + @Environment(\.colorScheme) private var colorScheme + @State private var showExplanation = false + + var body: some View { + if verified > 0 { + Image(systemName: "checkmark.seal.fill") + .font(.system(size: size)) + .foregroundStyle(resolvedColor) + .onTapGesture { showExplanation = true } + .accessibilityLabel("Verified account") + .alert("Verified Account", isPresented: $showExplanation) { + Button("OK", role: .cancel) {} + } message: { + Text(annotationText) + } + } + } + + // MARK: - Private + + private var resolvedColor: Color { + if let badgeTint { return badgeTint } + return colorScheme == .dark + ? RosettaColors.primaryBlue // #248AE6 + : Color(hex: 0xACD2F9) // soft blue (light theme) + } + + private var annotationText: String { + switch verified { + case 1: + return "This is an official account belonging to a public figure, brand, or organization." + case 2: + return "This is an official account belonging to the administration of Rosetta." + default: + return "This user is an administrator of this group." + } + } +} + +// MARK: - Preview + +#Preview { + VStack(spacing: 16) { + HStack { + Text("Level 1") + VerifiedBadge(verified: 1, size: 16) + } + HStack { + Text("Level 2") + VerifiedBadge(verified: 2, size: 20) + } + HStack { + Text("Not verified") + VerifiedBadge(verified: 0, size: 16) + } + } + .padding() +} diff --git a/Rosetta/Features/Auth/AuthCoordinator.swift b/Rosetta/Features/Auth/AuthCoordinator.swift index 1f9fdc1..1e4ec98 100644 --- a/Rosetta/Features/Auth/AuthCoordinator.swift +++ b/Rosetta/Features/Auth/AuthCoordinator.swift @@ -14,6 +14,7 @@ enum AuthScreen: Equatable { struct AuthCoordinator: View { let onAuthComplete: () -> Void + var onBackToUnlock: (() -> Void)? @State private var currentScreen: AuthScreen = .welcome @State private var seedPhrase: [String] = [] @@ -94,7 +95,8 @@ private extension AuthCoordinator { onImportSeed: { isImportMode = true navigateTo(.importSeed) - } + }, + onBack: onBackToUnlock ) case .seedPhrase: @@ -146,11 +148,11 @@ private extension AuthCoordinator { case .welcome: EmptyView() case .seedPhrase: - WelcomeView(onGenerateSeed: {}, onImportSeed: {}) + WelcomeView(onGenerateSeed: {}, onImportSeed: {}, onBack: onBackToUnlock) case .confirmSeed: SeedPhraseView(seedPhrase: .constant(seedPhrase), onContinue: {}, onBack: {}) case .importSeed: - WelcomeView(onGenerateSeed: {}, onImportSeed: {}) + WelcomeView(onGenerateSeed: {}, onImportSeed: {}, onBack: onBackToUnlock) case .setPassword: if isImportMode { ImportSeedPhraseView(seedPhrase: .constant(seedPhrase), onContinue: {}, onBack: {}) diff --git a/Rosetta/Features/Auth/ConfirmSeedPhraseView.swift b/Rosetta/Features/Auth/ConfirmSeedPhraseView.swift index b9ea0a0..c3f12b8 100644 --- a/Rosetta/Features/Auth/ConfirmSeedPhraseView.swift +++ b/Rosetta/Features/Auth/ConfirmSeedPhraseView.swift @@ -37,7 +37,8 @@ struct ConfirmSeedPhraseView: View { .padding(.bottom, 100) } .scrollDismissesKeyboard(.interactively) - .onTapGesture { focusedInputIndex = nil } + .onTapGesture(count: 1) { focusedInputIndex = nil } + .simultaneousGesture(TapGesture().onEnded {}) confirmButton .padding(.horizontal, 24) diff --git a/Rosetta/Features/Auth/ImportSeedPhraseView.swift b/Rosetta/Features/Auth/ImportSeedPhraseView.swift index 42e2a28..716c402 100644 --- a/Rosetta/Features/Auth/ImportSeedPhraseView.swift +++ b/Rosetta/Features/Auth/ImportSeedPhraseView.swift @@ -30,7 +30,8 @@ struct ImportSeedPhraseView: View { .padding(.bottom, 100) } .scrollDismissesKeyboard(.interactively) - .onTapGesture { focusedWordIndex = nil } + .onTapGesture(count: 1) { focusedWordIndex = nil } + .simultaneousGesture(TapGesture().onEnded {}) continueButton .padding(.horizontal, 24) diff --git a/Rosetta/Features/Auth/SetPasswordView.swift b/Rosetta/Features/Auth/SetPasswordView.swift index b052e13..d4280f7 100644 --- a/Rosetta/Features/Auth/SetPasswordView.swift +++ b/Rosetta/Features/Auth/SetPasswordView.swift @@ -55,19 +55,18 @@ struct SetPasswordView: View { .multilineTextAlignment(.center) .transition(.opacity.combined(with: .scale(scale: 0.95))) } + + createButton + .padding(.top, 4) } .padding(.horizontal, 24) .padding(.top, 8) - .padding(.bottom, 100) + .padding(.bottom, 32) } .scrollDismissesKeyboard(.interactively) - .onTapGesture { focusedField = nil } - - createButton - .padding(.horizontal, 24) - .padding(.bottom, 16) + .onTapGesture(count: 1) { focusedField = nil } + .simultaneousGesture(TapGesture().onEnded {}) } - .geometryGroup() } } diff --git a/Rosetta/Features/Auth/UnlockView.swift b/Rosetta/Features/Auth/UnlockView.swift index f672a4c..9fd860c 100644 --- a/Rosetta/Features/Auth/UnlockView.swift +++ b/Rosetta/Features/Auth/UnlockView.swift @@ -1,8 +1,9 @@ import SwiftUI -/// Password unlock screen matching rosetta-android design with liquid glass styling. +/// Password unlock screen matching rosetta-android design. struct UnlockView: View { let onUnlocked: () -> Void + var onCreateNewAccount: (() -> Void)? @State private var password = "" @State private var isUnlocking = false @@ -23,29 +24,26 @@ struct UnlockView: View { account?.publicKey ?? "" } - /// First 2 chars of public key, uppercased — matching Android's `getAvatarText()`. + /// First 2 chars of public key — matching Android's avatar text. private var avatarText: String { RosettaColors.avatarText(publicKey: publicKey) } - /// Color index using Java-compatible hashCode — matching Android's `getAvatarColor()`. private var avatarColorIndex: Int { RosettaColors.avatarColorIndex(for: publicKey) } - /// Display name, or first 20 chars of public key if no name set. - private var displayName: String { - let name = account?.displayName ?? "" - if name.isEmpty { - return publicKey.isEmpty ? "Rosetta" : String(publicKey.prefix(20)) + "..." - } - return name + /// Short public key — 7 characters like Android (e.g. "0325a4d"). + private var shortPublicKey: String { + guard publicKey.count >= 7 else { return publicKey } + return String(publicKey.prefix(7)) } - /// Truncated public key for subtitle. - private var publicKeyPreview: String { - guard publicKey.count > 20 else { return publicKey } - return String(publicKey.prefix(20)) + "..." + /// Display name or short public key. + private var displayTitle: String { + let name = account?.displayName ?? "" + if !name.isEmpty { return name } + return shortPublicKey } var body: some View { @@ -69,27 +67,17 @@ struct UnlockView: View { Spacer().frame(height: 20) - // Display name - Text(displayName) + // Short public key (7 chars like Android) + Text(shortPublicKey) .font(.system(size: 24, weight: .bold)) .foregroundStyle(.white) .opacity(showTitle ? 1 : 0) .offset(y: showTitle ? 0 : 8) - // Public key preview (below name) - if !(account?.displayName ?? "").isEmpty { - Text(publicKeyPreview) - .font(.system(size: 13)) - .foregroundStyle(RosettaColors.secondaryText) - .padding(.top, 4) - .opacity(showTitle ? 1 : 0) - .offset(y: showTitle ? 0 : 8) - } - Spacer().frame(height: 8) - // Subtitle - Text("Enter password to unlock") + // Subtitle — matching Android + Text("For unlock account enter password") .font(.system(size: 15)) .foregroundStyle(RosettaColors.secondaryText) .opacity(showSubtitle ? 1 : 0) @@ -97,125 +85,25 @@ struct UnlockView: View { Spacer().frame(height: 40) - // Password input — glass card - VStack(alignment: .leading, spacing: 8) { - GlassCard(cornerRadius: 14, fillOpacity: 0.08) { - HStack(spacing: 12) { - Group { - if showPassword { - TextField("Password", text: $password) - } else { - SecureField("Password", text: $password) - } - } - .font(.system(size: 16)) - .foregroundStyle(.white) - .textContentType(.password) - .submitLabel(.done) - .onSubmit { unlock() } - - Button { - showPassword.toggle() - } label: { - Image(systemName: showPassword ? "eye.slash" : "eye") - .font(.system(size: 18)) - .foregroundStyle(Color(white: 0.45)) - } - } - .padding(.horizontal, 16) - .padding(.vertical, 14) - } - .overlay { - RoundedRectangle(cornerRadius: 14) - .stroke( - errorMessage != nil ? RosettaColors.error : Color.clear, - lineWidth: 1 - ) - } - - if let error = errorMessage { - Text(error) - .font(.system(size: 14)) - .foregroundStyle(RosettaColors.error) - .padding(.leading, 4) - .transition(.opacity) - } - } - .padding(.horizontal, 24) - .opacity(showInput ? 1 : 0) - .offset(y: showInput ? 0 : 12) + // Password input + passwordField + .padding(.horizontal, 24) + .opacity(showInput ? 1 : 0) + .offset(y: showInput ? 0 : 12) Spacer().frame(height: 24) - // Unlock button - Button(action: unlock) { - HStack(spacing: 10) { - if isUnlocking { - ProgressView() - .tint(.white) - .scaleEffect(0.9) - } else { - Image(systemName: "lock.open.fill") - .font(.system(size: 16)) - Text("Unlock") - .font(.system(size: 16, weight: .semibold)) - } - } - .foregroundStyle(.white) - .frame(maxWidth: .infinity) - .frame(height: 54) - .background( - RoundedRectangle(cornerRadius: 14) - .fill(password.isEmpty ? RosettaColors.primaryBlue.opacity(0.4) : RosettaColors.primaryBlue) - ) - } - .disabled(password.isEmpty || isUnlocking) - .padding(.horizontal, 24) - .opacity(showButton ? 1 : 0) - .offset(y: showButton ? 0 : 12) + // Enter button — matching onboarding style + unlockButton + .padding(.horizontal, 24) + .opacity(showButton ? 1 : 0) + .offset(y: showButton ? 0 : 12) - Spacer().frame(height: 40) + Spacer().frame(height: 60) - // Footer — "or" divider + secondary actions - VStack(spacing: 16) { - HStack(spacing: 12) { - Rectangle() - .fill(RosettaColors.secondaryText.opacity(0.3)) - .frame(height: 0.5) - Text("or") - .font(.system(size: 13)) - .foregroundStyle(RosettaColors.secondaryText) - Rectangle() - .fill(RosettaColors.secondaryText.opacity(0.3)) - .frame(height: 0.5) - } - .padding(.horizontal, 40) - - Button { - // TODO: Recover account flow - } label: { - HStack(spacing: 8) { - Image(systemName: "key.fill") - .font(.system(size: 14)) - Text("Recover account") - .font(.system(size: 15, weight: .medium)) - } - .foregroundStyle(RosettaColors.primaryBlue) - } - - Button { - // TODO: Create new account flow - } label: { - HStack(spacing: 8) { - Image(systemName: "person.badge.plus") - .font(.system(size: 14)) - Text("Create new account") - .font(.system(size: 15, weight: .medium)) - } - .foregroundStyle(RosettaColors.secondaryText) - } - } - .opacity(showFooter ? 1 : 0) + // Footer — "You can also recover your password or create a new account." + footerView + .opacity(showFooter ? 1 : 0) Spacer().frame(height: 40) } @@ -224,10 +112,131 @@ struct UnlockView: View { } .onAppear { startAnimations() } } +} - // MARK: - Actions +// MARK: - Password Field - private func unlock() { +private extension UnlockView { + var passwordField: some View { + VStack(alignment: .leading, spacing: 8) { + GlassCard(cornerRadius: 14, fillOpacity: 0.08) { + HStack(spacing: 12) { + Group { + if showPassword { + TextField("Password", text: $password) + } else { + SecureField("Password", text: $password) + } + } + .font(.system(size: 16)) + .foregroundStyle(.white) + .textContentType(.password) + .submitLabel(.done) + .onSubmit { unlock() } + + Button { + showPassword.toggle() + } label: { + Image(systemName: showPassword ? "eye.slash" : "eye") + .font(.system(size: 18)) + .foregroundStyle(Color(white: 0.45)) + } + } + .padding(.horizontal, 16) + .padding(.vertical, 14) + } + .overlay { + RoundedRectangle(cornerRadius: 14) + .stroke( + errorMessage != nil ? RosettaColors.error : Color.clear, + lineWidth: 1 + ) + } + + if let error = errorMessage { + Text(error) + .font(.system(size: 14)) + .foregroundStyle(RosettaColors.error) + .padding(.leading, 4) + .transition(.opacity) + } + } + } +} + +// MARK: - Unlock Button + +private extension UnlockView { + var unlockButton: some View { + Button(action: unlock) { + HStack(spacing: 10) { + if isUnlocking { + ProgressView() + .tint(.white) + .scaleEffect(0.9) + } else { + Image(systemName: "lock.open.fill") + .font(.system(size: 16)) + Text("Enter") + .font(.system(size: 16, weight: .semibold)) + } + } + .foregroundStyle(.white) + .frame(maxWidth: .infinity) + .frame(height: 56) + } + .buttonStyle(RosettaPrimaryButtonStyle(isEnabled: !password.isEmpty && !isUnlocking)) + .disabled(password.isEmpty || isUnlocking) + } +} + +// MARK: - Footer + +private extension UnlockView { + var footerView: some View { + VStack(spacing: 4) { + HStack(spacing: 0) { + Text("You can also ") + .foregroundStyle(RosettaColors.secondaryText) + + Button { + onCreateNewAccount?() + } label: { + Text("recover your password") + .fontWeight(.semibold) + .foregroundStyle(RosettaColors.primaryBlue) + } + .buttonStyle(.plain) + + Text(" or") + .foregroundStyle(RosettaColors.secondaryText) + } + .font(.system(size: 15)) + + HStack(spacing: 0) { + Text("create a ") + .foregroundStyle(RosettaColors.secondaryText) + + Button { + onCreateNewAccount?() + } label: { + Text("new account.") + .fontWeight(.semibold) + .foregroundStyle(RosettaColors.primaryBlue) + } + .buttonStyle(.plain) + } + .font(.system(size: 15)) + } + .multilineTextAlignment(.center) + .padding(.horizontal, 32) + } +} + +// MARK: - Actions + +private extension UnlockView { + func unlock() { guard !password.isEmpty, !isUnlocking else { return } isUnlocking = true errorMessage = nil @@ -245,7 +254,7 @@ struct UnlockView: View { } } - private func startAnimations() { + func startAnimations() { withAnimation(.easeOut(duration: 0.3)) { showAvatar = true } withAnimation(.easeOut(duration: 0.3).delay(0.08)) { showTitle = true } withAnimation(.easeOut(duration: 0.3).delay(0.12)) { showSubtitle = true } diff --git a/Rosetta/Features/Auth/WelcomeView.swift b/Rosetta/Features/Auth/WelcomeView.swift index a139318..c7f8560 100644 --- a/Rosetta/Features/Auth/WelcomeView.swift +++ b/Rosetta/Features/Auth/WelcomeView.swift @@ -4,31 +4,47 @@ import Lottie struct WelcomeView: View { let onGenerateSeed: () -> Void let onImportSeed: () -> Void + var onBack: (() -> Void)? @State private var isVisible = false var body: some View { - VStack(spacing: 0) { - Spacer() + ZStack(alignment: .topLeading) { + VStack(spacing: 0) { + Spacer() - lockAnimation - .padding(.bottom, 32) + lockAnimation + .padding(.bottom, 32) - titleSection - .padding(.bottom, 16) + titleSection + .padding(.bottom, 16) - subtitleSection - .padding(.bottom, 24) + subtitleSection + .padding(.bottom, 24) - featureBadges - .padding(.bottom, 32) + featureBadges + .padding(.bottom, 32) - Spacer() - Spacer().frame(height: 16) + Spacer() + Spacer().frame(height: 16) - buttonsSection - .padding(.horizontal, 24) - .padding(.bottom, 16) + buttonsSection + .padding(.horizontal, 24) + .padding(.bottom, 16) + } + + // Back button (only shows when coming from Unlock screen) + if let onBack { + Button(action: onBack) { + Image(systemName: "chevron.left") + .font(.system(size: 18, weight: .medium)) + .foregroundStyle(.white) + .frame(width: 44, height: 44) + } + .padding(.leading, 12) + .padding(.top, 8) + .opacity(isVisible ? 1.0 : 0.0) + } } .onAppear { withAnimation(.easeOut(duration: 0.5)) { isVisible = true } @@ -146,7 +162,7 @@ private extension WelcomeView { } #Preview { - WelcomeView(onGenerateSeed: {}, onImportSeed: {}) + WelcomeView(onGenerateSeed: {}, onImportSeed: {}, onBack: {}) .preferredColorScheme(.dark) .background(RosettaColors.authBackground) } diff --git a/Rosetta/Features/Chats/ChatList/ChatEmptyStateView.swift b/Rosetta/Features/Chats/ChatList/ChatEmptyStateView.swift new file mode 100644 index 0000000..3fe0a40 --- /dev/null +++ b/Rosetta/Features/Chats/ChatList/ChatEmptyStateView.swift @@ -0,0 +1,67 @@ +import SwiftUI +import Lottie + +// MARK: - ChatEmptyStateView + +struct ChatEmptyStateView: View { + let searchText: String + + var body: some View { + VStack(spacing: 0) { + if searchText.isEmpty { + noConversationsContent + } else { + noSearchResultsContent + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .offset(y: -40) + } +} + +// MARK: - Content Variants + +private extension ChatEmptyStateView { + var noConversationsContent: some View { + Group { + LottieView(animationName: "letter", loopMode: .playOnce, animationSpeed: 1.0) + .frame(width: 150, height: 150) + + Spacer().frame(height: 24) + + Text("No conversations yet") + .font(.system(size: 18, weight: .semibold)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .multilineTextAlignment(.center) + + Spacer().frame(height: 8) + + Text("Start a new conversation to get started") + .font(.system(size: 15)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .multilineTextAlignment(.center) + .padding(.horizontal, 40) + } + } + + var noSearchResultsContent: some View { + Group { + Image(systemName: "magnifyingglass") + .font(.system(size: 52)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary.opacity(0.5)) + + Spacer().frame(height: 16) + + Text("No results for \"\(searchText)\"") + .font(.system(size: 18, weight: .semibold)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .multilineTextAlignment(.center) + } + } +} + +// MARK: - Preview + +#Preview { + ChatEmptyStateView(searchText: "") +} diff --git a/Rosetta/Features/Chats/ChatList/ChatListSearchContent.swift b/Rosetta/Features/Chats/ChatList/ChatListSearchContent.swift new file mode 100644 index 0000000..3213033 --- /dev/null +++ b/Rosetta/Features/Chats/ChatList/ChatListSearchContent.swift @@ -0,0 +1,244 @@ +import Lottie +import SwiftUI + +// MARK: - Chat List Search Content + +/// Search overlay for ChatListView — shows recent searches or search results. +/// Matches Android's three-state pattern: skeleton → empty → results. +struct ChatListSearchContent: View { + let searchText: String + @ObservedObject var viewModel: ChatListViewModel + var onSelectRecent: (String) -> Void + + var body: some View { + let trimmed = searchText.trimmingCharacters(in: .whitespaces) + if trimmed.isEmpty { + recentSearchesSection + } else { + activeSearchContent + } + } +} + +// MARK: - Active Search (Three States) + +private extension ChatListSearchContent { + /// Android-style: skeleton ↔ empty ↔ results — only one visible at a time. + @ViewBuilder + var activeSearchContent: some View { + let localResults = viewModel.filteredDialogs + let localKeys = Set(localResults.map(\.opponentKey)) + let serverOnly = viewModel.serverSearchResults.filter { + !localKeys.contains($0.publicKey) + } + let hasAnyResult = !localResults.isEmpty || !serverOnly.isEmpty + + if viewModel.isServerSearching && !hasAnyResult { + SearchSkeletonView() + } else if !viewModel.isServerSearching && !hasAnyResult { + noResultsState + } else { + resultsList(localResults: localResults, serverOnly: serverOnly) + } + } + + /// Lottie animation + "No results found" — matches Android's empty state. + var noResultsState: some View { + VStack(spacing: 20) { + Spacer() + LottieView(animationName: "search", loopMode: .playOnce, animationSpeed: 1.0) + .frame(width: 120, height: 120) + Text("Search for users") + .font(.system(size: 17, weight: .medium)) + .foregroundStyle(RosettaColors.Adaptive.text) + Text("Enter username or public key") + .font(.system(size: 14)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + Spacer() + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + + /// Scrollable list of local dialogs + server results. + func resultsList(localResults: [Dialog], serverOnly: [SearchUser]) -> some View { + ScrollView { + LazyVStack(spacing: 0) { + ForEach(localResults) { dialog in + ChatRowView(dialog: dialog) + } + + ForEach(serverOnly, id: \.publicKey) { user in + serverUserRow(user) + if user.publicKey != serverOnly.last?.publicKey { + Divider() + .padding(.leading, 76) + .foregroundStyle(RosettaColors.Adaptive.divider) + } + } + + Spacer().frame(height: 80) + } + } + .scrollDismissesKeyboard(.interactively) + } +} + +// MARK: - Recent Searches + +private extension ChatListSearchContent { + @ViewBuilder + var recentSearchesSection: some View { + if viewModel.recentSearches.isEmpty { + searchPlaceholder + } else { + ScrollView { + VStack(spacing: 0) { + HStack { + Text("RECENT") + .font(.system(size: 13)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + Spacer() + Button { viewModel.clearRecentSearches() } label: { + Text("Clear") + .font(.system(size: 13)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + } + } + .padding(.horizontal, 16) + .padding(.top, 8) + .padding(.bottom, 6) + + ForEach(viewModel.recentSearches, id: \.publicKey) { recent in + recentRow(recent) + } + } + } + .scrollDismissesKeyboard(.interactively) + } + } + + var searchPlaceholder: some View { + VStack(spacing: 20) { + Spacer() + LottieView(animationName: "search", loopMode: .loop, animationSpeed: 1.0) + .frame(width: 120, height: 120) + Text("Search for users") + .font(.system(size: 17, weight: .medium)) + .foregroundStyle(RosettaColors.Adaptive.text) + Text("Find people by username or public key") + .font(.system(size: 14)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .multilineTextAlignment(.center) + .padding(.horizontal, 40) + Spacer() + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + + func recentRow(_ user: RecentSearch) -> some View { + let isSelf = user.publicKey == SessionManager.shared.currentPublicKey + let initials = isSelf ? "S" : RosettaColors.initials( + name: user.title, publicKey: user.publicKey + ) + let colorIdx = RosettaColors.avatarColorIndex(for: user.publicKey) + + return Button { + onSelectRecent(user.username.isEmpty ? user.publicKey : user.username) + } label: { + HStack(spacing: 10) { + ZStack(alignment: .topTrailing) { + AvatarView( + initials: initials, colorIndex: colorIdx, + size: 42, isSavedMessages: isSelf + ) + Button { + viewModel.removeRecentSearch(publicKey: user.publicKey) + } label: { + Image(systemName: "xmark") + .font(.system(size: 9, weight: .bold)) + .foregroundStyle(.white) + .frame(width: 18, height: 18) + .background(Circle().fill(RosettaColors.figmaBlue)) + } + .offset(x: 4, y: -4) + } + + VStack(alignment: .leading, spacing: 1) { + Text(isSelf ? "Saved Messages" : ( + user.title.isEmpty + ? String(user.publicKey.prefix(16)) + "..." + : user.title + )) + .font(.system(size: 17, weight: .medium)) + .foregroundStyle(RosettaColors.Adaptive.text) + .lineLimit(1) + if !user.lastSeenText.isEmpty { + Text(user.lastSeenText) + .font(.system(size: 13)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .lineLimit(1) + } + } + Spacer() + } + .padding(.horizontal, 16) + .padding(.vertical, 5) + } + .buttonStyle(.plain) + } +} + +// MARK: - Server User Row + +private extension ChatListSearchContent { + func serverUserRow(_ user: SearchUser) -> some View { + let isSelf = user.publicKey == SessionManager.shared.currentPublicKey + let initials = isSelf ? "S" : RosettaColors.initials( + name: user.title, publicKey: user.publicKey + ) + let colorIdx = RosettaColors.avatarColorIndex(for: user.publicKey) + + return Button { + viewModel.addToRecent(user) + } label: { + HStack(spacing: 12) { + AvatarView( + initials: initials, colorIndex: colorIdx, + size: 48, isOnline: user.online == 1, + isSavedMessages: isSelf + ) + + VStack(alignment: .leading, spacing: 2) { + HStack(spacing: 4) { + Text(isSelf ? "Saved Messages" : ( + user.title.isEmpty + ? String(user.publicKey.prefix(10)) + : user.title + )) + .font(.system(size: 16, weight: .medium)) + .foregroundStyle(RosettaColors.Adaptive.text) + .lineLimit(1) + if !isSelf && (user.verified > 0 || isRosettaOfficial(user)) { + VerifiedBadge( + verified: user.verified > 0 ? user.verified : 1, + size: 16 + ) + } + } + Text(isSelf ? "Notes" : ( + user.username.isEmpty + ? "@\(String(user.publicKey.prefix(10)))..." + : "@\(user.username)" + )) + .font(.system(size: 14)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .lineLimit(1) + } + Spacer() + } + .padding(.horizontal, 16) + .padding(.vertical, 12) + } + .buttonStyle(.plain) + } +} diff --git a/Rosetta/Features/Chats/ChatList/ChatListView.swift b/Rosetta/Features/Chats/ChatList/ChatListView.swift index 2ea9825..4f4de9e 100644 --- a/Rosetta/Features/Chats/ChatList/ChatListView.swift +++ b/Rosetta/Features/Chats/ChatList/ChatListView.swift @@ -3,9 +3,9 @@ import SwiftUI // MARK: - ChatListView struct ChatListView: View { - @State private var viewModel = ChatListViewModel() + @Binding var isSearchActive: Bool + @StateObject private var viewModel = ChatListViewModel() @State private var searchText = "" - @State private var isSearchPresented = false var body: some View { NavigationStack { @@ -13,7 +13,15 @@ struct ChatListView: View { RosettaColors.Adaptive.background .ignoresSafeArea() - chatContent + if isSearchActive { + ChatListSearchContent( + searchText: searchText, + viewModel: viewModel, + onSelectRecent: { searchText = $0 } + ) + } else { + normalContent + } } .navigationBarTitleDisplayMode(.inline) .toolbar { toolbarContent } @@ -21,7 +29,7 @@ struct ChatListView: View { .applyGlassNavBar() .searchable( text: $searchText, - isPresented: $isSearchPresented, + isPresented: $isSearchActive, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search" ) @@ -33,29 +41,19 @@ struct ChatListView: View { } } -// MARK: - Glass Nav Bar Modifier - -private struct GlassNavBarModifier: ViewModifier { - func body(content: Content) -> some View { - if #available(iOS 26, *) { - content - } else { - content - .toolbarBackground(.ultraThinMaterial, for: .navigationBar) - } - } -} - -private extension View { - func applyGlassNavBar() -> some View { - modifier(GlassNavBarModifier()) - } -} - -// MARK: - Chat Content +// MARK: - Normal Content private extension ChatListView { - var chatContent: some View { + @ViewBuilder + var normalContent: some View { + if viewModel.filteredDialogs.isEmpty && !viewModel.isLoading { + ChatEmptyStateView(searchText: "") + } else { + dialogList + } + } + + var dialogList: some View { List { if viewModel.isLoading { ForEach(0..<8, id: \.self) { _ in @@ -64,29 +62,19 @@ private extension ChatListView { .listRowBackground(Color.clear) .listRowSeparator(.hidden) } - } else if viewModel.filteredDialogs.isEmpty && !viewModel.showServerResults { - emptyState - .listRowInsets(EdgeInsets()) - .listRowBackground(Color.clear) - .listRowSeparator(.hidden) } else { - // Local dialog results if !viewModel.pinnedDialogs.isEmpty { - pinnedSection + ForEach(viewModel.pinnedDialogs) { dialog in + chatRow(dialog) + .listRowBackground(RosettaColors.Adaptive.backgroundSecondary) + } } - ForEach(viewModel.unpinnedDialogs) { dialog in chatRow(dialog) } - - // Server search results - if viewModel.showServerResults { - serverSearchSection - } } - Color.clear - .frame(height: 80) + Color.clear.frame(height: 80) .listRowInsets(EdgeInsets()) .listRowBackground(Color.clear) .listRowSeparator(.hidden) @@ -95,17 +83,6 @@ private extension ChatListView { .scrollContentBackground(.hidden) .scrollDismissesKeyboard(.interactively) } -} - -// MARK: - Pinned Section - -private extension ChatListView { - var pinnedSection: some View { - ForEach(viewModel.pinnedDialogs) { dialog in - chatRow(dialog) - .listRowBackground(RosettaColors.Adaptive.backgroundSecondary) - } - } func chatRow(_ dialog: Dialog) -> some View { ChatRowView(dialog: dialog) @@ -119,7 +96,6 @@ private extension ChatListView { } label: { Label("Delete", systemImage: "trash") } - Button { viewModel.toggleMute(dialog) } label: { @@ -137,7 +113,6 @@ private extension ChatListView { Label("Read", systemImage: "envelope.open") } .tint(RosettaColors.figmaBlue) - Button { viewModel.togglePin(dialog) } label: { @@ -154,9 +129,7 @@ private extension ChatListView { @ToolbarContentBuilder var toolbarContent: some ToolbarContent { ToolbarItem(placement: .navigationBarLeading) { - Button { - // TODO: Edit mode - } label: { + Button { } label: { Text("Edit") .font(.system(size: 17, weight: .medium)) .foregroundStyle(RosettaColors.Adaptive.text) @@ -166,218 +139,41 @@ private extension ChatListView { ToolbarItem(placement: .principal) { HStack(spacing: 4) { storiesAvatars - Text("Chats") .font(.system(size: 17, weight: .semibold)) .foregroundStyle(RosettaColors.Adaptive.text) - - Image(systemName: "checkmark.seal.fill") - .font(.system(size: 14)) - .foregroundStyle(RosettaColors.figmaBlue) } } ToolbarItemGroup(placement: .navigationBarTrailing) { - Button { - // TODO: Camera - } label: { - Image(systemName: "camera") - .font(.system(size: 18)) - .foregroundStyle(RosettaColors.Adaptive.text) + HStack(spacing: 8) { + Button { } label: { + Image(systemName: "camera") + .font(.system(size: 16, weight: .regular)) + .foregroundStyle(RosettaColors.Adaptive.text) + } + .accessibilityLabel("Camera") + Button { } label: { + Image(systemName: "square.and.pencil") + .font(.system(size: 17, weight: .regular)) + .foregroundStyle(RosettaColors.Adaptive.text) + } + .padding(.bottom, 2) + .accessibilityLabel("New chat") } - .accessibilityLabel("Camera") - - Button { - // TODO: Compose new message - } label: { - Image(systemName: "square.and.pencil") - .font(.system(size: 18)) - .foregroundStyle(RosettaColors.Adaptive.text) - } - .accessibilityLabel("New chat") } } @ViewBuilder private var storiesAvatars: some View { let pk = AccountManager.shared.currentAccount?.publicKey ?? "" - let initials = RosettaColors.initials(name: SessionManager.shared.displayName, publicKey: pk) - let colorIdx = RosettaColors.avatarColorIndex(for: pk) - - ZStack { - AvatarView(initials: initials, colorIndex: colorIdx, size: 28) - } - } -} - -// MARK: - Server Search Results - -private extension ChatListView { - @ViewBuilder - var serverSearchSection: some View { - if viewModel.isServerSearching { - HStack { - Spacer() - ProgressView() - .tint(RosettaColors.Adaptive.textSecondary) - Text("Searching users...") - .font(.system(size: 15)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - Spacer() - } - .padding(.vertical, 16) - .listRowInsets(EdgeInsets()) - .listRowBackground(Color.clear) - .listRowSeparator(.hidden) - } else if !viewModel.serverSearchResults.isEmpty { - Section { - ForEach(viewModel.serverSearchResults, id: \.publicKey) { user in - serverSearchRow(user) - } - } header: { - Text("GLOBAL SEARCH") - .font(.system(size: 13)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - } - } else if viewModel.filteredDialogs.isEmpty { - emptyState - .listRowInsets(EdgeInsets()) - .listRowBackground(Color.clear) - .listRowSeparator(.hidden) - } - } - - func serverSearchRow(_ user: SearchUser) -> some View { - let isSelf = user.publicKey == SessionManager.shared.currentPublicKey - let initials = isSelf ? "S" : RosettaColors.initials(name: user.title, publicKey: user.publicKey) - let colorIdx = RosettaColors.avatarColorIndex(for: user.publicKey) - - return Button { - // TODO: Navigate to ChatDetailView - } label: { - HStack(spacing: 12) { - AvatarView( - initials: initials, - colorIndex: colorIdx, - size: 52, - isOnline: user.online == 1, - isSavedMessages: isSelf - ) - - VStack(alignment: .leading, spacing: 2) { - HStack(spacing: 4) { - Text(isSelf ? "Saved Messages" : (user.title.isEmpty ? String(user.publicKey.prefix(16)) + "..." : user.title)) - .font(.system(size: 17, weight: .medium)) - .foregroundStyle(RosettaColors.Adaptive.text) - .lineLimit(1) - - if user.verified > 0 { - Image(systemName: "checkmark.seal.fill") - .font(.system(size: 12)) - .foregroundStyle(RosettaColors.figmaBlue) - } - } - - if !user.username.isEmpty { - Text("@\(user.username)") - .font(.system(size: 14)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - .lineLimit(1) - } - } - - Spacer() - - if user.online == 1 { - Circle() - .fill(RosettaColors.online) - .frame(width: 8, height: 8) - } - } - .padding(.horizontal, 16) - .padding(.vertical, 6) - } - .buttonStyle(.plain) - .listRowInsets(EdgeInsets()) - } -} - -// MARK: - Empty State - -private extension ChatListView { - var emptyState: some View { - VStack(spacing: 16) { - Image(systemName: searchText.isEmpty ? "bubble.left.and.bubble.right" : "magnifyingglass") - .font(.system(size: 52)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary.opacity(0.5)) - .padding(.top, 80) - - Text(searchText.isEmpty ? "No chats yet" : "No results for \"\(searchText)\"") - .font(.system(size: 17, weight: .semibold)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - - if searchText.isEmpty { - Text("Start a conversation by tapping the search tab") - .font(.system(size: 15)) - .foregroundStyle(RosettaColors.Adaptive.textTertiary) - .multilineTextAlignment(.center) - .padding(.horizontal, 40) - } - } - .frame(maxWidth: .infinity) - } -} - -// MARK: - Shimmer Row - -private struct ChatRowShimmerView: View { - @State private var phase: CGFloat = 0 - @Environment(\.colorScheme) private var colorScheme - - var body: some View { - HStack(spacing: 12) { - Circle() - .fill(shimmerGradient) - .frame(width: 62, height: 62) - - VStack(alignment: .leading, spacing: 8) { - RoundedRectangle(cornerRadius: 4) - .fill(shimmerGradient) - .frame(width: 140, height: 14) - - RoundedRectangle(cornerRadius: 4) - .fill(shimmerGradient) - .frame(width: 200, height: 12) - } - - Spacer() - } - .padding(.horizontal, 16) - .padding(.vertical, 10) - .onAppear { - withAnimation(.linear(duration: 1.4).repeatForever(autoreverses: false)) { - phase = 1 - } - } - } - - var shimmerGradient: LinearGradient { - let baseOpacity = colorScheme == .dark ? 0.06 : 0.08 - let peakOpacity = colorScheme == .dark ? 0.12 : 0.16 - return LinearGradient( - colors: [ - Color.gray.opacity(baseOpacity), - Color.gray.opacity(peakOpacity), - Color.gray.opacity(baseOpacity), - ], - startPoint: UnitPoint(x: phase - 0.4, y: 0), - endPoint: UnitPoint(x: phase + 0.4, y: 0) + let initials = RosettaColors.initials( + name: SessionManager.shared.displayName, publicKey: pk ) + let colorIdx = RosettaColors.avatarColorIndex(for: pk) + ZStack { AvatarView(initials: initials, colorIndex: colorIdx, size: 28) } } } -// MARK: - Preview +#Preview { ChatListView(isSearchActive: .constant(false)) } -#Preview { - ChatListView() -} diff --git a/Rosetta/Features/Chats/ChatList/ChatListViewModel.swift b/Rosetta/Features/Chats/ChatList/ChatListViewModel.swift index b8fdbfc..f66e83b 100644 --- a/Rosetta/Features/Chats/ChatList/ChatListViewModel.swift +++ b/Rosetta/Features/Chats/ChatList/ChatListViewModel.swift @@ -1,23 +1,34 @@ +import Combine import Foundation +import os // MARK: - ChatListViewModel -@Observable @MainActor -final class ChatListViewModel { +final class ChatListViewModel: ObservableObject { + + private static let logger = Logger(subsystem: "com.rosetta.messenger", category: "ChatListVM") // MARK: - State - private(set) var isLoading = false - private(set) var searchQuery = "" + @Published var isLoading = false + @Published var searchQuery = "" + @Published var serverSearchResults: [SearchUser] = [] + @Published var isServerSearching = false + @Published var recentSearches: [RecentSearch] = [] - // Server search state - private(set) var serverSearchResults: [SearchUser] = [] - private(set) var isServerSearching = false private var searchTask: Task? private var lastSearchedText = "" + private static let maxRecent = 20 + + private var recentKey: String { + "rosetta_recent_searches_\(SessionManager.shared.currentPublicKey)" + } + + // MARK: - Init init() { + loadRecentSearches() setupSearchCallback() } @@ -25,7 +36,6 @@ final class ChatListViewModel { var filteredDialogs: [Dialog] { var result = DialogRepository.shared.sortedDialogs - let query = searchQuery.trimmingCharacters(in: .whitespaces).lowercased() if !query.isEmpty { result = result.filter { @@ -34,17 +44,11 @@ final class ChatListViewModel { || $0.lastMessage.lowercased().contains(query) } } - return result } - var pinnedDialogs: [Dialog] { - filteredDialogs.filter(\.isPinned) - } - - var unpinnedDialogs: [Dialog] { - filteredDialogs.filter { !$0.isPinned } - } + var pinnedDialogs: [Dialog] { filteredDialogs.filter(\.isPinned) } + var unpinnedDialogs: [Dialog] { filteredDialogs.filter { !$0.isPinned } } var totalUnreadCount: Int { DialogRepository.shared.sortedDialogs @@ -54,12 +58,6 @@ final class ChatListViewModel { var hasUnread: Bool { totalUnreadCount > 0 } - /// True when searching and no local results — shows server results section - var showServerResults: Bool { - let query = searchQuery.trimmingCharacters(in: .whitespaces) - return !query.isEmpty - } - // MARK: - Actions func setSearchQuery(_ query: String) { @@ -85,6 +83,30 @@ final class ChatListViewModel { // MARK: - Server Search + private func setupSearchCallback() { + Self.logger.debug("Setting up search callback") + ProtocolManager.shared.onSearchResult = { [weak self] packet in + DispatchQueue.main.async { [weak self] in + guard let self else { + Self.logger.debug("Search callback: self is nil") + return + } + Self.logger.debug("📥 Search results received: \(packet.users.count) users") + self.serverSearchResults = packet.users + self.isServerSearching = false + Self.logger.debug("📥 isServerSearching=\(self.isServerSearching), count=\(self.serverSearchResults.count)") + for user in packet.users { + DialogRepository.shared.updateUserInfo( + publicKey: user.publicKey, + title: user.title, + username: user.username, + verified: user.verified + ) + } + } + } + } + private func triggerServerSearch() { searchTask?.cancel() searchTask = nil @@ -97,15 +119,11 @@ final class ChatListViewModel { return } - if trimmed == lastSearchedText { - return - } - + if trimmed == lastSearchedText { return } isServerSearching = true searchTask = Task { [weak self] in try? await Task.sleep(for: .seconds(1)) - guard let self, !Task.isCancelled else { return } let currentQuery = self.searchQuery.trimmingCharacters(in: .whitespaces) @@ -113,41 +131,65 @@ final class ChatListViewModel { let connState = ProtocolManager.shared.connectionState let hash = SessionManager.shared.privateKeyHash - print("[Search] connState=\(connState.rawValue), hasHash=\(hash != nil), query='\(currentQuery)'") guard connState == .authenticated, let hash else { - print("[Search] NOT AUTHENTICATED - aborting") self.isServerSearching = false return } self.lastSearchedText = currentQuery - var packet = PacketSearch() packet.privateKey = hash packet.search = currentQuery - print("[Search] Sending PacketSearch for '\(currentQuery)'") + Self.logger.debug("📤 Sending search packet for '\(currentQuery)' with hash \(hash.prefix(10))...") ProtocolManager.shared.sendPacket(packet) } } - private func setupSearchCallback() { - print("[Search] Setting up search callback") - ProtocolManager.shared.onSearchResult = { [weak self] packet in - print("[Search] CALLBACK: received \(packet.users.count) users") - Task { @MainActor [weak self] in - guard let self else { return } - self.serverSearchResults = packet.users - self.isServerSearching = false + // MARK: - Recent Searches - for user in packet.users { - DialogRepository.shared.updateUserInfo( - publicKey: user.publicKey, - title: user.title, - username: user.username - ) - } - } + func addToRecent(_ user: SearchUser) { + let recent = RecentSearch( + publicKey: user.publicKey, + title: user.title, + username: user.username, + lastSeenText: user.online == 1 ? "online" : "last seen recently" + ) + recentSearches.removeAll { $0.publicKey == user.publicKey } + recentSearches.insert(recent, at: 0) + if recentSearches.count > Self.maxRecent { + recentSearches = Array(recentSearches.prefix(Self.maxRecent)) + } + saveRecentSearches() + } + + func removeRecentSearch(publicKey: String) { + recentSearches.removeAll { $0.publicKey == publicKey } + saveRecentSearches() + } + + func clearRecentSearches() { + recentSearches = [] + saveRecentSearches() + } + + private func loadRecentSearches() { + if let data = UserDefaults.standard.data(forKey: recentKey), + let list = try? JSONDecoder().decode([RecentSearch].self, from: data) { + recentSearches = list + return + } + let oldKey = "rosetta_recent_searches" + if let data = UserDefaults.standard.data(forKey: oldKey), + let list = try? JSONDecoder().decode([RecentSearch].self, from: data) { + recentSearches = list + saveRecentSearches() + UserDefaults.standard.removeObject(forKey: oldKey) } } + + private func saveRecentSearches() { + guard let data = try? JSONEncoder().encode(recentSearches) else { return } + UserDefaults.standard.set(data, forKey: recentKey) + } } diff --git a/Rosetta/Features/Chats/ChatList/ChatRowShimmerView.swift b/Rosetta/Features/Chats/ChatList/ChatRowShimmerView.swift new file mode 100644 index 0000000..74ee276 --- /dev/null +++ b/Rosetta/Features/Chats/ChatList/ChatRowShimmerView.swift @@ -0,0 +1,50 @@ +import SwiftUI + +// MARK: - ChatRowShimmerView + +/// Placeholder shimmer row displayed during chat list loading. +struct ChatRowShimmerView: View { + @State private var phase: CGFloat = 0 + @Environment(\.colorScheme) private var colorScheme + + var body: some View { + HStack(spacing: 12) { + Circle() + .fill(shimmerGradient) + .frame(width: 62, height: 62) + + VStack(alignment: .leading, spacing: 8) { + RoundedRectangle(cornerRadius: 4) + .fill(shimmerGradient) + .frame(width: 140, height: 14) + + RoundedRectangle(cornerRadius: 4) + .fill(shimmerGradient) + .frame(width: 200, height: 12) + } + + Spacer() + } + .padding(.horizontal, 16) + .padding(.vertical, 10) + .task { + withAnimation(.linear(duration: 1.4).repeatForever(autoreverses: false)) { + phase = 1 + } + } + } + + private var shimmerGradient: LinearGradient { + let baseOpacity = colorScheme == .dark ? 0.06 : 0.08 + let peakOpacity = colorScheme == .dark ? 0.12 : 0.16 + return LinearGradient( + colors: [ + Color.gray.opacity(baseOpacity), + Color.gray.opacity(peakOpacity), + Color.gray.opacity(baseOpacity), + ], + startPoint: UnitPoint(x: phase - 0.4, y: 0), + endPoint: UnitPoint(x: phase + 0.4, y: 0) + ) + } +} diff --git a/Rosetta/Features/Chats/ChatList/ChatRowView.swift b/Rosetta/Features/Chats/ChatList/ChatRowView.swift index 4670637..0fdc972 100644 --- a/Rosetta/Features/Chats/ChatList/ChatRowView.swift +++ b/Rosetta/Features/Chats/ChatList/ChatRowView.swift @@ -2,11 +2,14 @@ import SwiftUI // MARK: - ChatRowView -/// Chat row matching Figma spec: -/// Row: paddingLeft=10, paddingRight=16, height=78 -/// Avatar: 62px + 10pt right padding -/// Title: SFPro-Medium 17pt, message: SFPro-Regular 15pt -/// Time: SFPro-Regular 14pt, subtitle color: #3C3C43/60% +/// Chat row matching Figma "Row - Chats" component spec: +/// Row: height 78, paddingLeft 10, paddingRight 16, vertical center +/// Avatar: 62px circle, 10pt trailing padding +/// Title: SF Pro Medium 17pt, tracking -0.43, primary color +/// Message: SF Pro Regular 15pt, tracking -0.23, secondary color +/// Time: SF Pro Regular 14pt, tracking -0.23, secondary color +/// Badges gap: 6pt — verified 12px, muted 12px +/// Trailing: pt 8, pb 14 — readStatus + time (gap 2), pin/count at bottom struct ChatRowView: View { let dialog: Dialog @@ -38,21 +41,27 @@ private extension ChatRowView { } } -// MARK: - Content Section +// MARK: - Content Section (two-column: title+detail | trailing accessories) private extension ChatRowView { var contentSection: some View { - VStack(alignment: .leading, spacing: 0) { - Spacer(minLength: 0) - titleRow - Spacer().frame(height: 3) - subtitleRow - Spacer(minLength: 0) + HStack(alignment: .center, spacing: 6) { + // Left column: title + message + VStack(alignment: .leading, spacing: 2) { + titleRow + messageRow + } + .frame(maxWidth: .infinity, alignment: .leading) + .clipped() + + // Right column: time + pin/badge + trailingColumn } + .frame(height: 63) } } -// MARK: - Title Row (name + badges + delivery + time) +// MARK: - Title Row (name + badges) private extension ChatRowView { var titleRow: some View { @@ -63,10 +72,11 @@ private extension ChatRowView { .foregroundStyle(RosettaColors.Adaptive.text) .lineLimit(1) - if dialog.isVerified { - Image(systemName: "checkmark.seal.fill") - .font(.system(size: 14)) - .foregroundStyle(RosettaColors.figmaBlue) + if !dialog.isSavedMessages && dialog.effectiveVerified > 0 { + VerifiedBadge( + verified: dialog.effectiveVerified, + size: 12 + ) } if dialog.isMuted { @@ -74,47 +84,19 @@ private extension ChatRowView { .font(.system(size: 12)) .foregroundStyle(RosettaColors.Adaptive.textSecondary) } - - Spacer(minLength: 4) - - if dialog.lastMessageFromMe && !dialog.isSavedMessages { - deliveryIcon - } - - Text(formattedTime) - .font(.system(size: 14)) - .foregroundStyle( - dialog.unreadCount > 0 && !dialog.isMuted - ? RosettaColors.figmaBlue - : RosettaColors.Adaptive.textSecondary - ) } } } -// MARK: - Subtitle Row (message + pin + badge) +// MARK: - Message Row private extension ChatRowView { - var subtitleRow: some View { - HStack(spacing: 4) { - Text(messageText) - .font(.system(size: 15)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - .lineLimit(1) - - Spacer(minLength: 4) - - if dialog.isPinned && dialog.unreadCount == 0 { - Image(systemName: "pin.fill") - .font(.system(size: 13)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - .rotationEffect(.degrees(45)) - } - - if dialog.unreadCount > 0 { - unreadBadge - } - } + var messageRow: some View { + Text(messageText) + .font(.system(size: 15)) + .tracking(-0.23) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .lineLimit(1) } var messageText: String { @@ -123,6 +105,48 @@ private extension ChatRowView { } return dialog.lastMessage } +} + +// MARK: - Trailing Column (time + delivery on top, pin/badge on bottom) + +private extension ChatRowView { + var trailingColumn: some View { + VStack(alignment: .trailing, spacing: 0) { + // Top: read status + time + HStack(spacing: 2) { + if dialog.lastMessageFromMe && !dialog.isSavedMessages { + deliveryIcon + } + + Text(formattedTime) + .font(.system(size: 14)) + .tracking(-0.23) + .foregroundStyle( + dialog.unreadCount > 0 && !dialog.isMuted + ? RosettaColors.figmaBlue + : RosettaColors.Adaptive.textSecondary + ) + } + .padding(.top, 2) + + Spacer(minLength: 0) + + // Bottom: pin or unread badge + HStack(spacing: 8) { + if dialog.isPinned && dialog.unreadCount == 0 { + Image(systemName: "pin.fill") + .font(.system(size: 15)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .rotationEffect(.degrees(45)) + } + + if dialog.unreadCount > 0 { + unreadBadge + } + } + .padding(.bottom, 2) + } + } @ViewBuilder var deliveryIcon: some View { @@ -160,9 +184,11 @@ private extension ChatRowView { return Text(text) .font(.system(size: 15)) + .tracking(-0.23) .foregroundStyle(.white) .padding(.horizontal, 4) .frame(minWidth: 20, minHeight: 20) + .frame(maxWidth: 37) .background { Capsule() .fill(isMuted ? Color(hex: 0x787880) : RosettaColors.figmaBlue) @@ -208,7 +234,7 @@ private extension ChatRowView { lastMessage: "Hey, how are you?", lastMessageTimestamp: Int64(Date().timeIntervalSince1970 * 1000), unreadCount: 3, isOnline: true, lastSeen: 0, - isVerified: true, iHaveSent: true, + verified: 1, iHaveSent: true, isPinned: false, isMuted: false, lastMessageFromMe: true, lastMessageDelivered: .read ) diff --git a/Rosetta/Features/Chats/ChatList/SearchSkeletonView.swift b/Rosetta/Features/Chats/ChatList/SearchSkeletonView.swift new file mode 100644 index 0000000..6856b8a --- /dev/null +++ b/Rosetta/Features/Chats/ChatList/SearchSkeletonView.swift @@ -0,0 +1,86 @@ +import SwiftUI + +// MARK: - SearchSkeletonView + +/// Telegram-style skeleton loading for search results. +/// Matches the Figma chat row layout: 62px avatar, two-line text, trailing time. +struct SearchSkeletonView: View { + @State private var phase: CGFloat = 0 + + var body: some View { + ScrollView { + VStack(spacing: 0) { + ForEach(0..<7, id: \.self) { index in + skeletonRow(index: index) + if index < 6 { + Divider() + .foregroundStyle(RosettaColors.Adaptive.divider) + .padding(.leading, 82) + } + } + } + } + .scrollDisabled(true) + .task { + withAnimation(.linear(duration: 1.5).repeatForever(autoreverses: false)) { + phase = 1 + } + } + } + + private func skeletonRow(index: Int) -> some View { + HStack(spacing: 0) { + // Avatar — 62pt circle matching Figma + Circle() + .fill(shimmerGradient) + .frame(width: 62, height: 62) + .padding(.leading, 10) + .padding(.trailing, 10) + + // Text block — two lines matching Figma row heights + VStack(alignment: .leading, spacing: 8) { + // Title line — name width varies per row + RoundedRectangle(cornerRadius: 4) + .fill(shimmerGradient) + .frame(width: titleWidth(for: index), height: 16) + + // Subtitle line — message preview + RoundedRectangle(cornerRadius: 4) + .fill(shimmerGradient) + .frame(width: subtitleWidth(for: index), height: 14) + } + + Spacer() + + // Trailing time placeholder + RoundedRectangle(cornerRadius: 3) + .fill(shimmerGradient) + .frame(width: 40, height: 12) + .padding(.trailing, 16) + } + .frame(height: 78) + } + + // Vary widths to look natural (not uniform blocks) + private func titleWidth(for index: Int) -> CGFloat { + let widths: [CGFloat] = [130, 100, 160, 90, 140, 110, 150] + return widths[index % widths.count] + } + + private func subtitleWidth(for index: Int) -> CGFloat { + let widths: [CGFloat] = [200, 170, 220, 150, 190, 180, 210] + return widths[index % widths.count] + } + + private var shimmerGradient: LinearGradient { + LinearGradient( + colors: [ + Color.gray.opacity(0.08), + Color.gray.opacity(0.15), + Color.gray.opacity(0.08), + ], + startPoint: UnitPoint(x: phase - 0.4, y: 0), + endPoint: UnitPoint(x: phase + 0.4, y: 0) + ) + } +} diff --git a/Rosetta/Features/Chats/Search/SearchResultsSection.swift b/Rosetta/Features/Chats/Search/SearchResultsSection.swift new file mode 100644 index 0000000..1051ca3 --- /dev/null +++ b/Rosetta/Features/Chats/Search/SearchResultsSection.swift @@ -0,0 +1,123 @@ +import SwiftUI + +// MARK: - SearchResultsSection + +struct SearchResultsSection: View { + let isSearching: Bool + let searchResults: [SearchUser] + var onSelectUser: (SearchUser) -> Void + + var body: some View { + if isSearching { + loadingState + } else if searchResults.isEmpty { + noResultsState + } else { + VStack(spacing: 0) { + ForEach(searchResults, id: \.publicKey) { user in + searchResultRow(user) + } + } + } + } +} + +// MARK: - States + +private extension SearchResultsSection { + var loadingState: some View { + VStack(spacing: 12) { + Spacer().frame(height: 40) + ProgressView() + .tint(RosettaColors.Adaptive.textSecondary) + Text("Searching...") + .font(.system(size: 15)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + } + .frame(maxWidth: .infinity) + } + + var noResultsState: some View { + VStack(spacing: 12) { + Spacer().frame(height: 40) + Image(systemName: "person.slash") + .font(.system(size: 40)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary.opacity(0.5)) + Text("No users found") + .font(.system(size: 17, weight: .medium)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + Text("Try a different username or public key") + .font(.system(size: 15)) + .foregroundStyle(RosettaColors.Adaptive.textTertiary) + } + .frame(maxWidth: .infinity) + } +} + +// MARK: - Result Row + +private extension SearchResultsSection { + func searchResultRow(_ user: SearchUser) -> some View { + let isSelf = user.publicKey == SessionManager.shared.currentPublicKey + let initials = isSelf ? "S" : RosettaColors.initials(name: user.title, publicKey: user.publicKey) + let colorIdx = RosettaColors.avatarColorIndex(for: user.publicKey) + + return Button { + onSelectUser(user) + } label: { + HStack(spacing: 12) { + AvatarView( + initials: initials, + colorIndex: colorIdx, + size: 42, + isOnline: user.online == 1, + isSavedMessages: isSelf + ) + + VStack(alignment: .leading, spacing: 1) { + HStack(spacing: 4) { + Text(isSelf ? "Saved Messages" : (user.title.isEmpty ? String(user.publicKey.prefix(16)) + "..." : user.title)) + .font(.system(size: 17, weight: .medium)) + .foregroundStyle(RosettaColors.Adaptive.text) + .lineLimit(1) + + if user.verified > 0 || isRosettaOfficial(user) { + VerifiedBadge( + verified: user.verified > 0 ? user.verified : 1, + size: 12 + ) + } + } + + if !user.username.isEmpty { + Text("@\(user.username)") + .font(.system(size: 13)) + .foregroundStyle(RosettaColors.Adaptive.textSecondary) + .lineLimit(1) + } + } + + Spacer() + + if user.online == 1 { + Circle() + .fill(RosettaColors.online) + .frame(width: 8, height: 8) + } + } + .padding(.horizontal, 16) + .padding(.vertical, 5) + } + .buttonStyle(.plain) + } +} + +// MARK: - Preview + +#Preview { + SearchResultsSection( + isSearching: false, + searchResults: [], + onSelectUser: { _ in } + ) +} diff --git a/Rosetta/Features/Chats/Search/SearchView.swift b/Rosetta/Features/Chats/Search/SearchView.swift index 94b5207..4e05400 100644 --- a/Rosetta/Features/Chats/Search/SearchView.swift +++ b/Rosetta/Features/Chats/Search/SearchView.swift @@ -15,6 +15,7 @@ struct SearchView: View { ScrollView { VStack(spacing: 0) { if searchText.isEmpty { + favoriteContactsRow recentSection } else { searchResultsContent @@ -28,9 +29,13 @@ struct SearchView: View { searchBar } .onChange(of: searchText) { _, newValue in - print("[SearchView] onChange fired: '\(newValue)'") viewModel.setSearchQuery(newValue) } + .task { + // Auto-focus search field when the view appears + try? await Task.sleep(for: .milliseconds(300)) + isSearchFocused = true + } } } @@ -111,25 +116,48 @@ private extension SearchView { } } -// MARK: - Glass Search Bar Modifier -private struct GlassSearchBarModifier: ViewModifier { - func body(content: Content) -> some View { - if #available(iOS 26, *) { - content - .glassEffect(.regular, in: .capsule) - } else { - content +// MARK: - Favorite Contacts (Figma: horizontal scroll at top) + +private extension SearchView { + @ViewBuilder + var favoriteContactsRow: some View { + let dialogs = DialogRepository.shared.sortedDialogs.prefix(10) + if !dialogs.isEmpty { + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 4) { + ForEach(Array(dialogs), id: \.id) { dialog in + Button { + // TODO: Navigate to chat + } label: { + VStack(spacing: 4) { + AvatarView( + initials: dialog.initials, + colorIndex: dialog.avatarColorIndex, + size: 62, + isOnline: dialog.isOnline, + isSavedMessages: dialog.isSavedMessages + ) + + Text(dialog.isSavedMessages ? "Saved" : dialog.opponentTitle.components(separatedBy: " ").first ?? "") + .font(.system(size: 11)) + .tracking(0.06) + .foregroundStyle(RosettaColors.Adaptive.text) + .lineLimit(1) + .frame(width: 78) + } + .frame(width: 78) + } + .buttonStyle(.plain) + } + } + .padding(.horizontal, 2) + } + .padding(.top, 12) } } } -private extension View { - func applyGlassSearchBar() -> some View { - modifier(GlassSearchBarModifier()) - } -} - // MARK: - Recent Section private extension SearchView { @@ -243,93 +271,15 @@ private extension SearchView { // MARK: - Search Results Content private extension SearchView { - @ViewBuilder var searchResultsContent: some View { - if viewModel.isSearching { - VStack(spacing: 12) { - Spacer().frame(height: 40) - ProgressView() - .tint(RosettaColors.Adaptive.textSecondary) - Text("Searching...") - .font(.system(size: 15)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) + SearchResultsSection( + isSearching: viewModel.isSearching, + searchResults: viewModel.searchResults, + onSelectUser: { user in + viewModel.addToRecent(user) + // TODO: Navigate to ChatDetailView for user.publicKey } - .frame(maxWidth: .infinity) - } else if viewModel.searchResults.isEmpty { - VStack(spacing: 12) { - Spacer().frame(height: 40) - Image(systemName: "person.slash") - .font(.system(size: 40)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary.opacity(0.5)) - Text("No users found") - .font(.system(size: 17, weight: .medium)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - Text("Try a different username or public key") - .font(.system(size: 15)) - .foregroundStyle(RosettaColors.Adaptive.textTertiary) - } - .frame(maxWidth: .infinity) - } else { - VStack(spacing: 0) { - ForEach(viewModel.searchResults, id: \.publicKey) { user in - searchResultRow(user) - } - } - } - } - - func searchResultRow(_ user: SearchUser) -> some View { - let isSelf = user.publicKey == SessionManager.shared.currentPublicKey - let initials = isSelf ? "S" : RosettaColors.initials(name: user.title, publicKey: user.publicKey) - let colorIdx = RosettaColors.avatarColorIndex(for: user.publicKey) - - return Button { - viewModel.addToRecent(user) - // TODO: Navigate to ChatDetailView for user.publicKey - } label: { - HStack(spacing: 12) { - AvatarView( - initials: initials, - colorIndex: colorIdx, - size: 42, - isOnline: user.online == 1, - isSavedMessages: isSelf - ) - - VStack(alignment: .leading, spacing: 1) { - HStack(spacing: 4) { - Text(isSelf ? "Saved Messages" : (user.title.isEmpty ? String(user.publicKey.prefix(16)) + "..." : user.title)) - .font(.system(size: 17, weight: .medium)) - .foregroundStyle(RosettaColors.Adaptive.text) - .lineLimit(1) - - if user.verified > 0 { - Image(systemName: "checkmark.seal.fill") - .font(.system(size: 12)) - .foregroundStyle(RosettaColors.figmaBlue) - } - } - - if !user.username.isEmpty { - Text("@\(user.username)") - .font(.system(size: 13)) - .foregroundStyle(RosettaColors.Adaptive.textSecondary) - .lineLimit(1) - } - } - - Spacer() - - if user.online == 1 { - Circle() - .fill(RosettaColors.online) - .frame(width: 8, height: 8) - } - } - .padding(.horizontal, 16) - .padding(.vertical, 5) - } - .buttonStyle(.plain) + ) } } @@ -338,3 +288,4 @@ private extension SearchView { #Preview { SearchView() } + diff --git a/Rosetta/Features/Chats/Search/SearchViewModel.swift b/Rosetta/Features/Chats/Search/SearchViewModel.swift index 84acdea..9612bc6 100644 --- a/Rosetta/Features/Chats/Search/SearchViewModel.swift +++ b/Rosetta/Features/Chats/Search/SearchViewModel.swift @@ -29,7 +29,10 @@ final class SearchViewModel { private var searchTask: Task? private var lastSearchedText = "" - private static let recentKey = "rosetta_recent_searches" + private var recentKey: String { + let pk = SessionManager.shared.currentPublicKey ?? "" + return "rosetta_recent_searches_\(pk)" + } private static let maxRecent = 20 // MARK: - Init @@ -42,7 +45,7 @@ final class SearchViewModel { // MARK: - Search Logic func setSearchQuery(_ query: String) { - print("[Search] setSearchQuery called: '\(query)'") + searchQuery = query onSearchQueryChanged() } @@ -60,34 +63,34 @@ final class SearchViewModel { } if trimmed == lastSearchedText { - print("[Search] Query unchanged, skipping") + return } isSearching = true - print("[Search] Starting debounce for '\(trimmed)'") + // Debounce 1 second (like Android) searchTask = Task { [weak self] in try? await Task.sleep(for: .seconds(1)) guard let self, !Task.isCancelled else { - print("[Search] Task cancelled during debounce") + return } let currentQuery = self.searchQuery.trimmingCharacters(in: .whitespaces) guard !currentQuery.isEmpty, currentQuery == trimmed else { - print("[Search] Query changed during debounce, aborting") + return } let connState = ProtocolManager.shared.connectionState let hash = SessionManager.shared.privateKeyHash - print("[Search] connState=\(connState.rawValue), hasHash=\(hash != nil), query='\(currentQuery)'") + guard connState == .authenticated, let hash else { - print("[Search] NOT AUTHENTICATED - aborting search") + self.isSearching = false return } @@ -97,7 +100,7 @@ final class SearchViewModel { var packet = PacketSearch() packet.privateKey = hash packet.search = currentQuery - print("[Search] Sending PacketSearch for '\(currentQuery)' with hash prefix: \(String(hash.prefix(16)))...") + ProtocolManager.shared.sendPacket(packet) } } @@ -114,10 +117,8 @@ final class SearchViewModel { // MARK: - Search Callback private func setupSearchCallback() { - print("[Search] Setting up search callback on ProtocolManager") ProtocolManager.shared.onSearchResult = { [weak self] packet in - print("[Search] CALLBACK: received \(packet.users.count) users") - Task { @MainActor [weak self] in + DispatchQueue.main.async { [weak self] in guard let self else { return } self.searchResults = packet.users self.isSearching = false @@ -127,7 +128,8 @@ final class SearchViewModel { DialogRepository.shared.updateUserInfo( publicKey: user.publicKey, title: user.title, - username: user.username + username: user.username, + verified: user.verified ) } } @@ -166,15 +168,23 @@ final class SearchViewModel { } private func loadRecentSearches() { - guard let data = UserDefaults.standard.data(forKey: Self.recentKey), - let list = try? JSONDecoder().decode([RecentSearch].self, from: data) else { + if let data = UserDefaults.standard.data(forKey: recentKey), + let list = try? JSONDecoder().decode([RecentSearch].self, from: data) { + recentSearches = list return } - recentSearches = list + // Migrate from old static key + let oldKey = "rosetta_recent_searches" + if let data = UserDefaults.standard.data(forKey: oldKey), + let list = try? JSONDecoder().decode([RecentSearch].self, from: data) { + recentSearches = list + saveRecentSearches() + UserDefaults.standard.removeObject(forKey: oldKey) + } } private func saveRecentSearches() { guard let data = try? JSONEncoder().encode(recentSearches) else { return } - UserDefaults.standard.set(data, forKey: Self.recentKey) + UserDefaults.standard.set(data, forKey: recentKey) } } diff --git a/Rosetta/Features/MainTabView.swift b/Rosetta/Features/MainTabView.swift index 6443b9d..e5bc334 100644 --- a/Rosetta/Features/MainTabView.swift +++ b/Rosetta/Features/MainTabView.swift @@ -4,6 +4,7 @@ import SwiftUI struct MainTabView: View { var onLogout: (() -> Void)? @State private var selectedTab: RosettaTab = .chats + @State private var isChatSearchActive = false var body: some View { ZStack(alignment: .bottom) { @@ -13,24 +14,31 @@ struct MainTabView: View { Group { switch selectedTab { case .chats: - ChatListView() + ChatListView(isSearchActive: $isChatSearchActive) + .transition(.opacity) case .settings: SettingsView(onLogout: onLogout) + .transition(.opacity) case .search: SearchView() + .transition(.move(edge: .bottom).combined(with: .opacity)) } } + .animation(.easeInOut(duration: 0.3), value: selectedTab) - RosettaTabBar( - selectedTab: selectedTab, - onTabSelected: { tab in - withAnimation(.easeInOut(duration: 0.15)) { - selectedTab = tab - } - }, - badges: tabBadges - ) - .ignoresSafeArea(.keyboard) + if !isChatSearchActive { + RosettaTabBar( + selectedTab: selectedTab, + onTabSelected: { tab in + withAnimation(.easeInOut(duration: 0.3)) { + selectedTab = tab + } + }, + badges: tabBadges + ) + .ignoresSafeArea(.keyboard) + .transition(.move(edge: .bottom).combined(with: .opacity)) + } } } diff --git a/Rosetta/Resources/Lottie/search.json b/Rosetta/Resources/Lottie/search.json new file mode 100644 index 0000000..199630f --- /dev/null +++ b/Rosetta/Resources/Lottie/search.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":180,"w":512,"h":512,"nm":"Magnification glass - right","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Handle new","sr":1,"ks":{"r":{"a":0,"k":1},"p":{"a":0,"k":[129.262,374.479,0]},"a":{"a":0,"k":[138.762,365.479,0]},"s":{"a":0,"k":[99,99,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[8.941,11.312],[-1.929,-7.173],[0.919,-3.281],[0,0]],"o":[[0,0],[1.481,5.507],[0,0],[0,0]],"v":[[-6.814,-13.943],[5.965,2.039],[5.806,13.943],[-1.324,9.7]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.29411765933,0.349019616842,0.388235300779,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[216.283,328.92]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[15.651,5.402],[-16.992,9.701]],"o":[[-6.851,3.348],[0,0],[0,0]],"v":[[14,-5.421],[-17.631,-0.836],[17.631,1.677]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.29411765933,0.349019616842,0.388235300779,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[103.03,444.412]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.482,2.482],[0,0],[-2.482,2.482],[0,0],[-2.482,-2.482],[0,0],[2.482,-2.482],[0,0]],"o":[[0,0],[-2.482,-2.482],[0,0],[2.482,-2.482],[0,0],[2.482,2.482],[0,0],[-2.482,2.482]],"v":[[-48.443,48.443],[-48.443,48.443],[-48.443,39.454],[39.455,-48.443],[48.443,-48.443],[48.443,-48.443],[48.443,-39.455],[-39.455,48.443]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.054901961237,0.058823529631,0.066666670144,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[151.179,385.309]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-18.37,18.37],[-0.906,10.578]],"o":[[12.119,-6.039],[35.378,-35.378],[0,0]],"v":[[-50.069,51.976],[-6.472,13.369],[50.069,-51.976]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.29411765933,0.349019616842,0.388235300779,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[168.891,390.597]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.02,1.186]],"o":[[-3.418,-3.513],[0,0]],"v":[[4.563,3.494],[-4.563,-3.494]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.435294121504,0.537254929543,0.607843160629,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[173.589,285.593]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":30},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-24.617,24.617],[-0.906,10.578],[18.238,18.238],[11.598,-0.993],[35.377,-35.377],[0.036,-16],[-6.989,-6.989],[-16,0.035]],"o":[[35.378,-35.378],[0.993,-11.598],[-18.441,-18.441],[-10.578,0.906],[-24.617,24.617],[-0.035,16],[6.989,6.989],[16,-0.035]],"v":[[25.682,40.53],[82.223,-24.815],[57.453,-57.457],[24.816,-82.222],[-40.529,-25.681],[-82.309,30.105],[-64.162,64.163],[-30.104,82.31]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.058823529631,0.06274510175,0.066666670144,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[136.737,363.435]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[8.234,8.234],[0,0],[-8.234,8.234],[0,0],[-6.613,-6.613],[0,0],[6.613,-6.613],[0,0]],"o":[[0,0],[-8.234,-8.234],[0,0],[6.613,-6.613],[0,0],[6.613,6.613],[0,0],[-8.234,8.234]],"v":[[-52.32,52.32],[-52.32,52.32],[-52.32,22.502],[23.718,-53.535],[47.666,-53.535],[53.535,-47.666],[53.535,-23.718],[-22.502,52.32]],"c":true}},"nm":"Path 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.553,0.592,0.635,0.139,0.557,0.596,0.637,0.492,0.561,0.6,0.639,0.839,0.551,0.59,0.633,0.999,0.541,0.58,0.627,0,0,0.139,0.5,0.492,1,0.839,0.5,0.999,0]}},"s":{"a":0,"k":[-10.915,-18.839]},"e":{"a":0,"k":[19.277,10.854]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[121.95,351.273]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-24.617,24.617],[-0.906,10.578],[18.238,18.238],[11.598,-0.993],[35.377,-35.377],[0.036,-16],[-6.989,-6.989],[-16,0.035]],"o":[[35.378,-35.378],[0.993,-11.598],[-18.441,-18.441],[-10.578,0.906],[-24.617,24.617],[-0.035,16],[6.989,6.989],[16,-0.035]],"v":[[25.682,40.53],[82.223,-24.815],[57.453,-57.457],[24.816,-82.222],[-40.529,-25.681],[-82.309,30.105],[-64.162,64.163],[-30.104,82.31]],"c":true}},"nm":"Path 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.082,0.114,0.165,0.201,0.069,0.084,0.114,0.313,0.055,0.055,0.063]}},"s":{"a":0,"k":[86.76,63.518]},"e":{"a":0,"k":[-15.984,166.26]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[136.737,363.435]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":0,"op":9999,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"glass 2","sr":1,"ks":{"r":{"a":0,"k":45.436},"p":{"a":0,"k":[297.107,206.008,0]},"a":{"a":0,"k":[-4.714,-102.353,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":1,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[57.449,-1.813],[1.813,57.449],[-57.449,1.813],[-1.813,-57.449]],"o":[[-57.449,1.813],[-1.813,-57.449],[57.449,-1.813],[1.813,57.449]],"v":[[-1.421,1.659],[-108.72,-99.075],[-7.986,-206.374],[99.313,-105.64]],"c":true}]},{"t":9,"s":[{"i":[[6.83,-1.813],[0.216,57.449],[-6.83,1.813],[-0.216,-57.449]],"o":[[-6.83,1.813],[-0.216,-57.449],[6.83,-1.813],[0.215,57.449]],"v":[[16.348,1.799],[3.592,-98.935],[15.567,-206.234],[28.323,-105.5]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-0.099,-1.813],[-0.003,57.449],[0.099,1.813],[0.003,-57.449]],"o":[[0.099,1.813],[0.003,-57.449],[-0.099,-1.813],[-0.003,57.449]],"v":[[-27.22,1.636],[-27.034,-99.098],[-27.209,-206.397],[-27.394,-105.662]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[57.449,-1.813],[1.813,57.449],[-57.449,1.813],[-1.813,-57.449]],"o":[[-57.449,1.813],[-1.813,-57.449],[57.449,-1.813],[1.813,57.449]],"v":[[-1.421,1.659],[-108.72,-99.075],[-7.986,-206.374],[99.313,-105.64]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[57.449,-1.813],[1.813,57.449],[-57.449,1.813],[-1.813,-57.449]],"o":[[-57.449,1.813],[-1.813,-57.449],[57.449,-1.813],[1.813,57.449]],"v":[[-1.421,1.659],[-108.72,-99.075],[-7.986,-206.374],[99.313,-105.64]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.099,-1.813],[-0.003,57.449],[0.099,1.813],[0.003,-57.449]],"o":[[0.099,1.813],[0.003,-57.449],[-0.099,-1.813],[-0.003,57.449]],"v":[[-27.22,1.636],[-27.034,-99.098],[-27.209,-206.397],[-27.394,-105.662]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":151,"s":[{"i":[[6.83,-1.813],[0.216,57.449],[-6.83,1.813],[-0.216,-57.449]],"o":[[-6.83,1.813],[-0.216,-57.449],[6.83,-1.813],[0.215,57.449]],"v":[[16.348,1.799],[3.592,-98.935],[15.567,-206.234],[28.323,-105.5]],"c":true}]},{"t":160,"s":[{"i":[[57.449,-1.813],[1.813,57.449],[-57.449,1.813],[-1.813,-57.449]],"o":[[-57.449,1.813],[-1.813,-57.449],[57.449,-1.813],[1.813,57.449]],"v":[[-1.421,1.659],[-108.72,-99.075],[-7.986,-206.374],[99.313,-105.64]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":1,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[2.119,67.151],[67.151,-2.119],[-2.119,-67.151],[-67.143,2.126]],"o":[[-2.111,-67.144],[-67.151,2.119],[2.119,67.151],[67.151,-2.119]],"v":[[116.87,-106.194],[-8.547,-223.938],[-126.299,-98.513],[-0.881,19.231]],"c":true}]},{"t":9,"s":[{"i":[[0.252,67.151],[7.983,-2.119],[-0.252,-67.151],[-7.982,2.126]],"o":[[-0.251,-67.144],[-7.983,2.119],[0.252,67.151],[7.983,-2.119]],"v":[[30.41,-106.054],[15.501,-223.798],[1.502,-98.373],[16.412,19.371]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-0.004,67.151],[-0.116,-2.119],[0.004,-67.151],[0.117,2.126]],"o":[[0.004,-67.144],[0.116,2.119],[-0.004,67.151],[-0.116,-2.119]],"v":[[-27.425,-106.217],[-27.208,-223.961],[-27.004,-98.536],[-27.221,19.208]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[2.119,67.151],[67.151,-2.119],[-2.119,-67.151],[-67.143,2.126]],"o":[[-2.111,-67.144],[-67.151,2.119],[2.119,67.151],[67.151,-2.119]],"v":[[116.87,-106.194],[-8.547,-223.938],[-126.299,-98.513],[-0.881,19.231]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[2.119,67.151],[67.151,-2.119],[-2.119,-67.151],[-67.143,2.126]],"o":[[-2.111,-67.144],[-67.151,2.119],[2.119,67.151],[67.151,-2.119]],"v":[[116.87,-106.194],[-8.547,-223.938],[-126.299,-98.513],[-0.881,19.231]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.004,67.151],[-0.116,-2.119],[0.004,-67.151],[0.117,2.126]],"o":[[0.004,-67.144],[0.116,2.119],[-0.004,67.151],[-0.116,-2.119]],"v":[[-27.425,-106.217],[-27.208,-223.961],[-27.004,-98.536],[-27.221,19.208]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":151,"s":[{"i":[[0.252,67.151],[7.983,-2.119],[-0.252,-67.151],[-7.982,2.126]],"o":[[-0.251,-67.144],[-7.983,2.119],[0.252,67.151],[7.983,-2.119]],"v":[[30.41,-106.054],[15.501,-223.798],[1.502,-98.373],[16.412,19.371]],"c":true}]},{"t":160,"s":[{"i":[[2.119,67.151],[67.151,-2.119],[-2.119,-67.151],[-67.143,2.126]],"o":[[-2.111,-67.144],[-67.151,2.119],[2.119,67.151],[67.151,-2.119]],"v":[[116.87,-106.194],[-8.547,-223.938],[-126.299,-98.513],[-0.881,19.231]],"c":true}]}]},"nm":"Контур 2","hd":false},{"ty":"fl","c":{"a":0,"k":[0.415686279535,0.435294121504,0.46274510026,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":10},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":1,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0.361,-67.182],[67.182,0.361],[-0.361,67.182],[-67.182,-0.361]],"o":[[-0.361,67.182],[-67.182,-0.361],[0.361,-67.182],[67.182,0.361]],"v":[[116.932,-101.699],[-5.366,19.289],[-126.354,-103.008],[-4.057,-223.997]],"c":true}]},{"t":9,"s":[{"i":[[0.043,-67.182],[7.987,0.361],[-0.043,67.182],[-7.987,-0.361]],"o":[[-0.043,67.182],[-7.987,-0.361],[0.043,-67.182],[7.987,0.361]],"v":[[30.418,-101.559],[15.879,19.429],[1.495,-102.868],[16.034,-223.857]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-0.001,-67.182],[-0.116,0.361],[0.001,67.182],[0.116,-0.361]],"o":[[0.001,67.182],[0.116,-0.361],[-0.001,-67.182],[-0.116,0.361]],"v":[[-27.425,-101.722],[-27.213,19.267],[-27.004,-103.031],[-27.215,-224.019]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0.361,-67.182],[67.182,0.361],[-0.361,67.182],[-67.182,-0.361]],"o":[[-0.361,67.182],[-67.182,-0.361],[0.361,-67.182],[67.182,0.361]],"v":[[116.932,-101.699],[-5.366,19.289],[-126.354,-103.008],[-4.057,-223.997]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0.361,-67.182],[67.182,0.361],[-0.361,67.182],[-67.182,-0.361]],"o":[[-0.361,67.182],[-67.182,-0.361],[0.361,-67.182],[67.182,0.361]],"v":[[116.932,-101.699],[-5.366,19.289],[-126.354,-103.008],[-4.057,-223.997]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.001,-67.182],[-0.116,0.361],[0.001,67.182],[0.116,-0.361]],"o":[[0.001,67.182],[0.116,-0.361],[-0.001,-67.182],[-0.116,0.361]],"v":[[-27.425,-101.722],[-27.213,19.267],[-27.004,-103.031],[-27.215,-224.019]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":151,"s":[{"i":[[0.043,-67.182],[7.987,0.361],[-0.043,67.182],[-7.987,-0.361]],"o":[[-0.043,67.182],[-7.987,-0.361],[0.043,-67.182],[7.987,0.361]],"v":[[30.418,-101.559],[15.879,19.429],[1.495,-102.868],[16.034,-223.857]],"c":true}]},{"t":160,"s":[{"i":[[0.361,-67.182],[67.182,0.361],[-0.361,67.182],[-67.182,-0.361]],"o":[[-0.361,67.182],[-67.182,-0.361],[0.361,-67.182],[67.182,0.361]],"v":[[116.932,-101.699],[-5.366,19.289],[-126.354,-103.008],[-4.057,-223.997]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.729411780834,0.745098054409,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":50},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":1,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[2.601,-1.199],[0,0],[0.718,2.938],[0,0],[-2.098,0.96],[0,0],[-1.376,-1.731],[-2.19,-3.709]],"o":[[0,0],[-2.747,1.266],[0,0],[-0.548,-2.241],[0,0],[2.011,-0.92],[2.742,3.45],[1.456,2.466]],"v":[[75.909,-148.294],[25.912,-125.258],[19.227,-128.485],[16.232,-140.742],[18.904,-146.258],[64.851,-167.272],[70.624,-165.895],[78.023,-155.141]],"c":true}]},{"t":9,"s":[{"i":[[0.309,-1.199],[0,0],[0.085,2.938],[0,0],[-0.249,0.96],[0,0],[-0.164,-1.731],[-0.26,-3.709]],"o":[[0,0],[-0.327,1.266],[0,0],[-0.065,-2.241],[0,0],[0.239,-0.92],[0.326,3.45],[0.173,2.466]],"v":[[25.541,-148.154],[19.597,-125.118],[18.802,-128.345],[18.446,-140.602],[18.764,-146.118],[24.226,-167.132],[24.913,-165.755],[25.792,-155.002]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-0.005,-1.199],[0,0],[-0.001,2.938],[0,0],[0.004,0.96],[0,0],[0.002,-1.731],[0.004,-3.709]],"o":[[0,0],[0.005,1.266],[0,0],[0.001,-2.241],[0,0],[-0.003,-0.92],[-0.005,3.45],[-0.003,2.466]],"v":[[-27.354,-148.316],[-27.267,-125.281],[-27.256,-128.508],[-27.25,-140.765],[-27.255,-146.28],[-27.335,-167.295],[-27.345,-165.918],[-27.357,-155.164]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[2.601,-1.199],[0,0],[0.718,2.938],[0,0],[-2.098,0.96],[0,0],[-1.376,-1.731],[-2.19,-3.709]],"o":[[0,0],[-2.747,1.266],[0,0],[-0.548,-2.241],[0,0],[2.011,-0.92],[2.742,3.45],[1.456,2.466]],"v":[[75.909,-148.294],[25.912,-125.258],[19.227,-128.485],[16.232,-140.742],[18.904,-146.258],[64.851,-167.272],[70.624,-165.895],[78.023,-155.141]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[2.601,-1.199],[0,0],[0.718,2.938],[0,0],[-2.098,0.96],[0,0],[-1.376,-1.731],[-2.19,-3.709]],"o":[[0,0],[-2.747,1.266],[0,0],[-0.548,-2.241],[0,0],[2.011,-0.92],[2.742,3.45],[1.456,2.466]],"v":[[75.909,-148.294],[25.912,-125.258],[19.227,-128.485],[16.232,-140.742],[18.904,-146.258],[64.851,-167.272],[70.624,-165.895],[78.023,-155.141]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.005,-1.199],[0,0],[-0.001,2.938],[0,0],[0.004,0.96],[0,0],[0.002,-1.731],[0.004,-3.709]],"o":[[0,0],[0.005,1.266],[0,0],[0.001,-2.241],[0,0],[-0.003,-0.92],[-0.005,3.45],[-0.003,2.466]],"v":[[-27.354,-148.316],[-27.267,-125.281],[-27.256,-128.508],[-27.25,-140.765],[-27.255,-146.28],[-27.335,-167.295],[-27.345,-165.918],[-27.357,-155.164]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":151,"s":[{"i":[[0.309,-1.199],[0,0],[0.085,2.938],[0,0],[-0.249,0.96],[0,0],[-0.164,-1.731],[-0.26,-3.709]],"o":[[0,0],[-0.327,1.266],[0,0],[-0.065,-2.241],[0,0],[0.239,-0.92],[0.326,3.45],[0.173,2.466]],"v":[[25.541,-148.154],[19.597,-125.118],[18.802,-128.345],[18.446,-140.602],[18.764,-146.118],[24.226,-167.132],[24.913,-165.755],[25.792,-155.002]],"c":true}]},{"t":160,"s":[{"i":[[2.601,-1.199],[0,0],[0.718,2.938],[0,0],[-2.098,0.96],[0,0],[-1.376,-1.731],[-2.19,-3.709]],"o":[[0,0],[-2.747,1.266],[0,0],[-0.548,-2.241],[0,0],[2.011,-0.92],[2.742,3.45],[1.456,2.466]],"v":[[75.909,-148.294],[25.912,-125.258],[19.227,-128.485],[16.232,-140.742],[18.904,-146.258],[64.851,-167.272],[70.624,-165.895],[78.023,-155.141]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":20},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":1,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[2.052,-0.946],[0,0],[0.477,3.168],[0,0],[-1.951,0.892],[0,0],[-0.657,-2.994],[0,0]],"o":[[0,0],[-2.91,1.341],[0,0],[-0.319,-2.121],[0,0],[2.788,-1.275],[0,0],[0.485,2.207]],"v":[[7.963,-116.992],[-22.51,-106.459],[-29.279,-110.111],[-29.919,-114.355],[-27.163,-119.445],[1.218,-138.174],[7.916,-134.832],[10.648,-122.392]],"c":true}]},{"t":9,"s":[{"i":[[0.244,-0.946],[0,0],[0.057,3.168],[0,0],[-0.232,0.892],[0,0],[-0.078,-2.994],[0,0]],"o":[[0,0],[-0.346,1.341],[0,0],[-0.038,-2.121],[0,0],[0.331,-1.275],[0,0],[0.058,2.207]],"v":[[17.463,-116.852],[13.841,-106.319],[13.036,-109.971],[12.96,-114.215],[13.288,-119.305],[16.661,-138.034],[17.458,-134.692],[17.783,-122.252]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-0.004,-0.946],[0,0],[-0.001,3.168],[0,0],[0.003,0.892],[0,0],[0.001,-2.994],[0,0]],"o":[[0,0],[0.005,1.341],[0,0],[0.001,-2.121],[0,0],[-0.005,-1.275],[0,0],[-0.001,2.207]],"v":[[-27.236,-117.015],[-27.183,-106.482],[-27.172,-110.134],[-27.171,-114.378],[-27.175,-119.468],[-27.224,-138.197],[-27.236,-134.855],[-27.241,-122.414]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[2.052,-0.946],[0,0],[0.477,3.168],[0,0],[-1.951,0.892],[0,0],[-0.657,-2.994],[0,0]],"o":[[0,0],[-2.91,1.341],[0,0],[-0.319,-2.121],[0,0],[2.788,-1.275],[0,0],[0.485,2.207]],"v":[[7.963,-116.992],[-22.51,-106.459],[-29.279,-110.111],[-29.919,-114.355],[-27.163,-119.445],[1.218,-138.174],[7.916,-134.832],[10.648,-122.392]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[2.052,-0.946],[0,0],[0.477,3.168],[0,0],[-1.951,0.892],[0,0],[-0.657,-2.994],[0,0]],"o":[[0,0],[-2.91,1.341],[0,0],[-0.319,-2.121],[0,0],[2.788,-1.275],[0,0],[0.485,2.207]],"v":[[7.963,-116.992],[-22.51,-106.459],[-29.279,-110.111],[-29.919,-114.355],[-27.163,-119.445],[1.218,-138.174],[7.916,-134.832],[10.648,-122.392]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.004,-0.946],[0,0],[-0.001,3.168],[0,0],[0.003,0.892],[0,0],[0.001,-2.994],[0,0]],"o":[[0,0],[0.005,1.341],[0,0],[0.001,-2.121],[0,0],[-0.005,-1.275],[0,0],[-0.001,2.207]],"v":[[-27.236,-117.015],[-27.183,-106.482],[-27.172,-110.134],[-27.171,-114.378],[-27.175,-119.468],[-27.224,-138.197],[-27.236,-134.855],[-27.241,-122.414]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":151,"s":[{"i":[[0.244,-0.946],[0,0],[0.057,3.168],[0,0],[-0.232,0.892],[0,0],[-0.078,-2.994],[0,0]],"o":[[0,0],[-0.346,1.341],[0,0],[-0.038,-2.121],[0,0],[0.331,-1.275],[0,0],[0.058,2.207]],"v":[[17.463,-116.852],[13.841,-106.319],[13.036,-109.971],[12.96,-114.215],[13.288,-119.305],[16.661,-138.034],[17.458,-134.692],[17.783,-122.252]],"c":true}]},{"t":160,"s":[{"i":[[2.052,-0.946],[0,0],[0.477,3.168],[0,0],[-1.951,0.892],[0,0],[-0.657,-2.994],[0,0]],"o":[[0,0],[-2.91,1.341],[0,0],[-0.319,-2.121],[0,0],[2.788,-1.275],[0,0],[0.485,2.207]],"v":[[7.963,-116.992],[-22.51,-106.459],[-29.279,-110.111],[-29.919,-114.355],[-27.163,-119.445],[1.218,-138.174],[7.916,-134.832],[10.648,-122.392]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":20},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":1,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[1.124,-0.518],[0,0],[0.315,1.92],[0,0],[-1.207,0.552],[0,0],[-0.168,-2.034],[0,0]],"o":[[0,0],[-1.767,0.814],[0,0],[-0.215,-1.31],[0,0],[1.856,-0.849],[0,0],[0.102,1.233]],"v":[[-72.908,-84.704],[-75.5,-83.509],[-79.638,-85.707],[-80.94,-93.644],[-79.259,-96.799],[-76.044,-98.27],[-71.884,-95.834],[-71.206,-87.621]],"c":true}]},{"t":9,"s":[{"i":[[0.134,-0.518],[0,0],[0.037,1.92],[0,0],[-0.144,0.552],[0,0],[-0.02,-2.034],[0,0]],"o":[[0,0],[-0.21,0.814],[0,0],[-0.026,-1.31],[0,0],[0.221,-0.849],[0,0],[0.012,1.233]],"v":[[7.849,-84.564],[7.541,-83.37],[7.049,-85.567],[6.894,-93.505],[7.094,-96.659],[7.477,-98.13],[7.971,-95.694],[8.052,-87.481]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-0.002,-0.518],[0,0],[-0.001,1.92],[0,0],[0.002,0.552],[0,0],[0,-2.034],[0,0]],"o":[[0,0],[0.003,0.814],[0,0],[0,-1.31],[0,0],[-0.003,-0.849],[0,0],[0,1.233]],"v":[[-27.096,-84.727],[-27.092,-83.532],[-27.084,-85.73],[-27.082,-93.667],[-27.085,-96.821],[-27.091,-98.293],[-27.098,-95.857],[-27.099,-87.643]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[1.124,-0.518],[0,0],[0.315,1.92],[0,0],[-1.207,0.552],[0,0],[-0.168,-2.034],[0,0]],"o":[[0,0],[-1.767,0.814],[0,0],[-0.215,-1.31],[0,0],[1.856,-0.849],[0,0],[0.102,1.233]],"v":[[-72.908,-84.704],[-75.5,-83.509],[-79.638,-85.707],[-80.94,-93.644],[-79.259,-96.799],[-76.044,-98.27],[-71.884,-95.834],[-71.206,-87.621]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[1.124,-0.518],[0,0],[0.315,1.92],[0,0],[-1.207,0.552],[0,0],[-0.168,-2.034],[0,0]],"o":[[0,0],[-1.767,0.814],[0,0],[-0.215,-1.31],[0,0],[1.856,-0.849],[0,0],[0.102,1.233]],"v":[[-72.908,-84.704],[-75.5,-83.509],[-79.638,-85.707],[-80.94,-93.644],[-79.259,-96.799],[-76.044,-98.27],[-71.884,-95.834],[-71.206,-87.621]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.002,-0.518],[0,0],[-0.001,1.92],[0,0],[0.002,0.552],[0,0],[0,-2.034],[0,0]],"o":[[0,0],[0.003,0.814],[0,0],[0,-1.31],[0,0],[-0.003,-0.849],[0,0],[0,1.233]],"v":[[-27.096,-84.727],[-27.092,-83.532],[-27.084,-85.73],[-27.082,-93.667],[-27.085,-96.821],[-27.091,-98.293],[-27.098,-95.857],[-27.099,-87.643]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":151,"s":[{"i":[[0.134,-0.518],[0,0],[0.037,1.92],[0,0],[-0.144,0.552],[0,0],[-0.02,-2.034],[0,0]],"o":[[0,0],[-0.21,0.814],[0,0],[-0.026,-1.31],[0,0],[0.221,-0.849],[0,0],[0.012,1.233]],"v":[[7.849,-84.564],[7.541,-83.37],[7.049,-85.567],[6.894,-93.505],[7.094,-96.659],[7.477,-98.13],[7.971,-95.694],[8.052,-87.481]],"c":true}]},{"t":160,"s":[{"i":[[1.124,-0.518],[0,0],[0.315,1.92],[0,0],[-1.207,0.552],[0,0],[-0.168,-2.034],[0,0]],"o":[[0,0],[-1.767,0.814],[0,0],[-0.215,-1.31],[0,0],[1.856,-0.849],[0,0],[0.102,1.233]],"v":[[-72.908,-84.704],[-75.5,-83.509],[-79.638,-85.707],[-80.94,-93.644],[-79.259,-96.799],[-76.044,-98.27],[-71.884,-95.834],[-71.206,-87.621]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":20},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":1,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-0.182,-1.043],[0,0],[0.666,-0.307],[0,0],[0.313,0.912],[0.281,1.49],[-0.676,0.309],[0,0]],"o":[[0,0],[0.126,0.722],[0,0],[-0.875,0.404],[-0.496,-1.446],[-0.137,-0.73],[0,0],[0.963,-0.44]],"v":[[-87.149,-87.819],[-86.389,-83.465],[-87.305,-81.72],[-89.202,-80.846],[-91.413,-81.804],[-92.578,-86.214],[-91.66,-87.983],[-89.413,-89.011]],"c":true}]},{"t":9,"s":[{"i":[[-0.022,-1.043],[0,0],[0.079,-0.307],[0,0],[0.037,0.912],[0.033,1.49],[-0.08,0.309],[0,0]],"o":[[0,0],[0.015,0.722],[0,0],[-0.104,0.404],[-0.059,-1.446],[-0.016,-0.73],[0,0],[0.114,-0.44]],"v":[[6.156,-87.679],[6.247,-83.325],[6.138,-81.58],[5.912,-80.706],[5.649,-81.665],[5.511,-86.074],[5.62,-87.843],[5.887,-88.871]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[0,-1.043],[0,0],[-0.001,-0.307],[0,0],[-0.001,0.912],[0,1.49],[0.001,0.309],[0,0]],"o":[[0,0],[0,0.722],[0,0],[0.002,0.404],[0.001,-1.446],[0,-0.73],[0,0],[-0.002,-0.44]],"v":[[-27.071,-87.842],[-27.073,-83.488],[-27.071,-81.743],[-27.068,-80.868],[-27.064,-81.827],[-27.062,-86.237],[-27.064,-88.006],[-27.068,-89.034]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-0.182,-1.043],[0,0],[0.666,-0.307],[0,0],[0.313,0.912],[0.281,1.49],[-0.676,0.309],[0,0]],"o":[[0,0],[0.126,0.722],[0,0],[-0.875,0.404],[-0.496,-1.446],[-0.137,-0.73],[0,0],[0.963,-0.44]],"v":[[-87.149,-87.819],[-86.389,-83.465],[-87.305,-81.72],[-89.202,-80.846],[-91.413,-81.804],[-92.578,-86.214],[-91.66,-87.983],[-89.413,-89.011]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-0.182,-1.043],[0,0],[0.666,-0.307],[0,0],[0.313,0.912],[0.281,1.49],[-0.676,0.309],[0,0]],"o":[[0,0],[0.126,0.722],[0,0],[-0.875,0.404],[-0.496,-1.446],[-0.137,-0.73],[0,0],[0.963,-0.44]],"v":[[-87.149,-87.819],[-86.389,-83.465],[-87.305,-81.72],[-89.202,-80.846],[-91.413,-81.804],[-92.578,-86.214],[-91.66,-87.983],[-89.413,-89.011]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,-1.043],[0,0],[-0.001,-0.307],[0,0],[-0.001,0.912],[0,1.49],[0.001,0.309],[0,0]],"o":[[0,0],[0,0.722],[0,0],[0.002,0.404],[0.001,-1.446],[0,-0.73],[0,0],[-0.002,-0.44]],"v":[[-27.071,-87.842],[-27.073,-83.488],[-27.071,-81.743],[-27.068,-80.868],[-27.064,-81.827],[-27.062,-86.237],[-27.064,-88.006],[-27.068,-89.034]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":151,"s":[{"i":[[-0.022,-1.043],[0,0],[0.079,-0.307],[0,0],[0.037,0.912],[0.033,1.49],[-0.08,0.309],[0,0]],"o":[[0,0],[0.015,0.722],[0,0],[-0.104,0.404],[-0.059,-1.446],[-0.016,-0.73],[0,0],[0.114,-0.44]],"v":[[6.156,-87.679],[6.247,-83.325],[6.138,-81.58],[5.912,-80.706],[5.649,-81.665],[5.511,-86.074],[5.62,-87.843],[5.887,-88.871]],"c":true}]},{"t":160,"s":[{"i":[[-0.182,-1.043],[0,0],[0.666,-0.307],[0,0],[0.313,0.912],[0.281,1.49],[-0.676,0.309],[0,0]],"o":[[0,0],[0.126,0.722],[0,0],[-0.875,0.404],[-0.496,-1.446],[-0.137,-0.73],[0,0],[0.963,-0.44]],"v":[[-87.149,-87.819],[-86.389,-83.465],[-87.305,-81.72],[-89.202,-80.846],[-91.413,-81.804],[-92.578,-86.214],[-91.66,-87.983],[-89.413,-89.011]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":20},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"base-details 2","sr":1,"ks":{"r":{"a":0,"k":45.436},"p":{"a":0,"k":[279.992,220.637,0]},"a":{"a":0,"k":[-6.301,-79.894,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[19.628,16.939],[-10,-18.623],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[86.801,-208.277],[126.042,-171.807],[118.572,-168.909]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.009,16.939],[-0.005,-18.623],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.467,-208.316],[15.485,-171.846],[15.482,-168.948]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0.009,16.939],[-0.005,-18.623],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.467,-208.316],[15.485,-171.846],[15.482,-168.948]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0.009,16.939],[-0.005,-18.623],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.467,-208.316],[15.485,-171.846],[15.482,-168.948]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.009,16.939],[-0.005,-18.623],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.467,-208.316],[15.485,-171.846],[15.482,-168.948]],"c":true}]},{"t":160,"s":[{"i":[[19.628,16.939],[-10,-18.623],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[86.801,-208.277],[126.042,-171.807],[118.572,-168.909]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.603921592236,0.556862771511,0.501960813999,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[45.514,8.781],[-24.215,-33.57],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[30.873,-214.492],[90.197,-171.714],[96.705,-176.544]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.02,8.781],[-0.011,-33.57],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.442,-214.531],[15.469,-171.753],[15.472,-176.583]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0.02,8.781],[-0.011,-33.57],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.442,-214.531],[15.469,-171.753],[15.472,-176.583]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0.02,8.781],[-0.011,-33.57],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.442,-214.531],[15.469,-171.753],[15.472,-176.583]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.02,8.781],[-0.011,-33.57],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.442,-214.531],[15.469,-171.753],[15.472,-176.583]],"c":true}]},{"t":160,"s":[{"i":[[45.514,8.781],[-24.215,-33.57],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[30.873,-214.492],[90.197,-171.714],[96.705,-176.544]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.596078455448,0.647058844566,0.729411780834,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0.296,-1.243],[1.556,-20.315],[-2.157,13.842],[0,0],[0,0]],"o":[[0,0],[0,0],[2.157,-13.842],[0,0],[0,0]],"v":[[-140.112,-137.119],[-152.156,-94.342],[-151.312,-122.074],[-146.548,-143.94],[-139.109,-140.8]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,-1.243],[0.001,-20.315],[-0.001,13.842],[0,0],[0,0]],"o":[[0,0],[0,0],[0.001,-13.842],[0,0],[0,0]],"v":[[-24.635,-137.27],[-24.64,-94.493],[-24.64,-122.225],[-24.637,-144.092],[-24.634,-140.952]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,-1.243],[0.001,-20.315],[-0.001,13.842],[0,0],[0,0]],"o":[[0,0],[0,0],[0.001,-13.842],[0,0],[0,0]],"v":[[-24.635,-137.27],[-24.64,-94.493],[-24.64,-122.225],[-24.637,-144.092],[-24.634,-140.952]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,-1.243],[0.001,-20.315],[-0.001,13.842],[0,0],[0,0]],"o":[[0,0],[0,0],[0.001,-13.842],[0,0],[0,0]],"v":[[-24.635,-137.27],[-24.64,-94.493],[-24.64,-122.225],[-24.637,-144.092],[-24.634,-140.952]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,-1.243],[0.001,-20.315],[-0.001,13.842],[0,0],[0,0]],"o":[[0,0],[0,0],[0.001,-13.842],[0,0],[0,0]],"v":[[-24.635,-137.27],[-24.64,-94.493],[-24.64,-122.225],[-24.637,-144.092],[-24.634,-140.952]],"c":true}]},{"t":160,"s":[{"i":[[0.296,-1.243],[1.556,-20.315],[-2.157,13.842],[0,0],[0,0]],"o":[[0,0],[0,0],[2.157,-13.842],[0,0],[0,0]],"v":[[-140.112,-137.119],[-152.156,-94.342],[-151.312,-122.074],[-146.548,-143.94],[-139.109,-140.8]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.392156869173,0.596078455448,0.749019622803,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-11.716,23.528],[-10.343,-37.016],[0,0]],"o":[[0,0],[0,0],[-6.274,-20.242]],"v":[[-116.974,-137.597],[-117.819,-69.923],[-125.592,-68.049]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.005,23.528],[-0.005,-37.016],[0,0]],"o":[[0,0],[0,0],[-0.003,-20.242]],"v":[[15.376,-137.636],[15.375,-69.962],[15.372,-68.088]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-0.005,23.528],[-0.005,-37.016],[0,0]],"o":[[0,0],[0,0],[-0.003,-20.242]],"v":[[15.376,-137.636],[15.375,-69.962],[15.372,-68.088]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-0.005,23.528],[-0.005,-37.016],[0,0]],"o":[[0,0],[0,0],[-0.003,-20.242]],"v":[[15.376,-137.636],[15.375,-69.962],[15.372,-68.088]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.005,23.528],[-0.005,-37.016],[0,0]],"o":[[0,0],[0,0],[-0.003,-20.242]],"v":[[15.376,-137.636],[15.375,-69.962],[15.372,-68.088]],"c":true}]},{"t":160,"s":[{"i":[[-11.716,23.528],[-10.343,-37.016],[0,0]],"o":[[0,0],[0,0],[-6.274,-20.242]],"v":[[-116.974,-137.597],[-117.819,-69.923],[-125.592,-68.049]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.596078455448,0.647058844566,0.729411780834,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[39.949,-53.683],[50.88,70.829],[-81.857,46.009]],"o":[[0,0],[-44.845,60.261],[0,0],[65.74,-36.95]],"v":[[122.174,-124.285],[98.91,-20.454],[-100.491,-22.998],[61.025,0.282]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.018,-53.683],[0.023,70.829],[-0.037,46.009]],"o":[[0,0],[-0.02,60.261],[0,0],[0.03,-36.95]],"v":[[15.483,-124.324],[15.473,-20.494],[15.383,-23.037],[15.456,0.243]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[0.018,-53.683],[0.023,70.829],[-0.037,46.009]],"o":[[0,0],[-0.02,60.261],[0,0],[0.03,-36.95]],"v":[[15.483,-124.324],[15.473,-20.494],[15.383,-23.037],[15.456,0.243]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[0.018,-53.683],[0.023,70.829],[-0.037,46.009]],"o":[[0,0],[-0.02,60.261],[0,0],[0.03,-36.95]],"v":[[15.483,-124.324],[15.473,-20.494],[15.383,-23.037],[15.456,0.243]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.018,-53.683],[0.023,70.829],[-0.037,46.009]],"o":[[0,0],[-0.02,60.261],[0,0],[0.03,-36.95]],"v":[[15.483,-124.324],[15.473,-20.494],[15.383,-23.037],[15.456,0.243]],"c":true}]},{"t":160,"s":[{"i":[[0,0],[39.949,-53.683],[50.88,70.829],[-81.857,46.009]],"o":[[0,0],[-44.845,60.261],[0,0],[65.74,-36.95]],"v":[[122.174,-124.285],[98.91,-20.454],[-100.491,-22.998],[61.025,0.282]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.29411765933,0.301960796118,0.309803932905,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":60},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[2.981,-1.281]],"o":[[-4.9,-0.093],[0,0]],"v":[[-28.685,53.104],[-40.086,54.555]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.001,-1.281]],"o":[[-0.002,-0.093],[0,0]],"v":[[-35.608,54.4],[-35.613,55.85]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[0.001,-1.281]],"o":[[-0.002,-0.093],[0,0]],"v":[[-36.052,54.138],[-36.057,55.588]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[0.001,-1.281]],"o":[[-0.002,-0.093],[0,0]],"v":[[-36.052,54.138],[-36.057,55.588]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.001,-1.281]],"o":[[-0.002,-0.093],[0,0]],"v":[[-35.608,54.4],[-35.613,55.85]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[2.981,-1.281]],"o":[[-4.9,-0.093],[0,0]],"v":[[-28.685,53.104],[-40.086,54.555]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.411764711142,0.537254929543,0.611764729023,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":30},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[68.948,-3.921],[-37.061,-97.117],[55.005,-26.361],[-0.455,-31.703],[0,0],[-25.777,10.455],[-18.086,44.216],[21.507,24.355]],"o":[[0,0],[28.693,75.19],[-8.792,4.213],[0,0],[0,0],[25.777,-10.455],[18.086,-44.216],[-21.507,-24.355]],"v":[[-26.688,-220.424],[130.635,-151.664],[62.531,25.204],[28.32,64.49],[9.363,64.388],[28.611,10.377],[103.379,-56.158],[92.574,-174.816]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.031,-3.921],[-0.017,-97.117],[0.025,-26.361],[0,-31.703],[0,0],[-0.012,10.455],[-0.008,44.216],[0.01,24.355]],"o":[[0,0],[0.013,75.19],[-0.004,4.213],[0,0],[0,0],[0.012,-10.455],[0.008,-44.216],[-0.01,-24.355]],"v":[[15.416,-220.463],[15.487,-151.703],[15.456,25.165],[26.034,62.603],[26.025,62.501],[15.441,10.338],[15.475,-56.197],[15.47,-174.855]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0.031,-3.921],[-0.017,-97.117],[0.025,-26.361],[-0.818,-27.074],[0,0],[-0.012,10.455],[-0.008,44.216],[0.01,24.355]],"o":[[0,0],[0.013,75.19],[-0.004,4.213],[0,0],[0,0],[0.012,-10.455],[0.008,-44.216],[-0.01,-24.355]],"v":[[15.416,-220.463],[15.487,-151.703],[15.456,25.165],[26.564,62.599],[26.556,62.497],[15.441,10.338],[15.475,-56.197],[15.47,-174.855]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0.031,-3.921],[-0.017,-97.117],[0.025,-26.361],[-0.818,-27.074],[0,0],[-0.012,10.455],[-0.008,44.216],[0.01,24.355]],"o":[[0,0],[0.013,75.19],[-0.004,4.213],[0,0],[0,0],[0.012,-10.455],[0.008,-44.216],[-0.01,-24.355]],"v":[[15.416,-220.463],[15.487,-151.703],[15.456,25.165],[26.564,62.599],[26.556,62.497],[15.441,10.338],[15.475,-56.197],[15.47,-174.855]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.031,-3.921],[-0.017,-97.117],[0.025,-26.361],[0,-31.703],[0,0],[-0.012,10.455],[-0.008,44.216],[0.01,24.355]],"o":[[0,0],[0.013,75.19],[-0.004,4.213],[0,0],[0,0],[0.012,-10.455],[0.008,-44.216],[-0.01,-24.355]],"v":[[15.416,-220.463],[15.487,-151.703],[15.456,25.165],[26.034,62.603],[26.025,62.501],[15.441,10.338],[15.475,-56.197],[15.47,-174.855]],"c":true}]},{"t":160,"s":[{"i":[[68.948,-3.921],[-37.061,-97.117],[55.005,-26.361],[-0.455,-31.703],[0,0],[-25.777,10.455],[-18.086,44.216],[21.507,24.355]],"o":[[0,0],[28.693,75.19],[-8.792,4.213],[0,0],[0,0],[25.777,-10.455],[18.086,-44.216],[-21.507,-24.355]],"v":[[-26.688,-220.424],[130.635,-151.664],[62.531,25.204],[28.32,64.49],[9.363,64.388],[28.611,10.377],[103.379,-56.158],[92.574,-174.816]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.702,0.647,0.6,0.499,0.702,0.647,0.6,0.999,0.702,0.647,0.6,0,1,0.499,0.5,0.999,0]}},"s":{"a":0,"k":[108.028,-143.79]},"e":{"a":0,"k":[46.613,-124.447]},"t":1,"nm":"Gradient Fill 2","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":60},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 10","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-15.862,33.164],[33.071,-31.44],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[137.464,-60.382],[96.615,5.732],[90.996,0.052]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.007,33.164],[0.015,-31.44],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.49,-60.421],[15.472,5.693],[15.469,0.013]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-0.007,33.164],[0.015,-31.44],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.49,-60.421],[15.472,5.693],[15.469,0.013]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-0.007,33.164],[0.015,-31.44],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.49,-60.421],[15.472,5.693],[15.469,0.013]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.007,33.164],[0.015,-31.44],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[15.49,-60.421],[15.472,5.693],[15.469,0.013]],"c":true}]},{"t":160,"s":[{"i":[[-15.862,33.164],[33.071,-31.44],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[137.464,-60.382],[96.615,5.732],[90.996,0.052]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.29411765933,0.301960796118,0.309803932905,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 11","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[12.946,26.091],[-26.672,-25.373],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-143.236,-50.684],[-106.926,4.636],[-104.018,-3.724]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[2.736,22.317],[-0.324,-8.162],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-25.986,-53.067],[-28.176,0.162],[-20.393,-0.324]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[2.736,22.317],[-0.324,-8.162],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-25.986,-53.067],[-28.176,0.162],[-20.393,-0.324]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[2.736,22.317],[-0.324,-8.162],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-25.986,-53.067],[-28.176,0.162],[-20.393,-0.324]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[2.736,22.317],[-0.324,-8.162],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-25.986,-53.067],[-28.176,0.162],[-20.393,-0.324]],"c":true}]},{"t":160,"s":[{"i":[[12.946,26.091],[-26.672,-25.373],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-143.236,-50.684],[-106.926,4.636],[-104.018,-3.724]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.29411765933,0.301960796118,0.309803932905,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 12","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-28.158,-93.848],[-37.446,11.739],[34.763,71.472]],"o":[[0,0],[19.552,65.165],[0,0],[-45.514,-87.493]],"v":[[-94.063,-210.164],[-139.019,-61.937],[1.958,22.829],[-118.76,-49.273]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.13,-93.848],[-0.173,11.739],[0.16,71.472]],"o":[[0,0],[0.09,65.165],[0,0],[-0.21,-87.493]],"v":[[14.837,-210.164],[14.63,-61.937],[15.28,22.829],[14.763,-44.023]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-0.13,-93.848],[-0.173,11.739],[0.16,71.472]],"o":[[0,0],[0.09,65.165],[0,0],[-0.21,-87.493]],"v":[[14.837,-210.164],[14.63,-61.937],[15.28,22.829],[14.763,-44.023]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-0.13,-93.848],[-0.173,11.739],[0.16,71.472]],"o":[[0,0],[0.09,65.165],[0,0],[-0.21,-87.493]],"v":[[14.837,-210.164],[14.63,-61.937],[15.28,22.829],[14.763,-44.023]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.13,-93.848],[-0.173,11.739],[0.16,71.472]],"o":[[0,0],[0.09,65.165],[0,0],[-0.21,-87.493]],"v":[[14.837,-210.164],[14.63,-61.937],[15.28,22.829],[14.763,-44.023]],"c":true}]},{"t":160,"s":[{"i":[[0,0],[-28.158,-93.848],[-37.446,11.739],[34.763,71.472]],"o":[[0,0],[19.552,65.165],[0,0],[-45.514,-87.493]],"v":[[-94.063,-210.164],[-139.019,-61.937],[1.958,22.829],[-118.76,-49.273]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":40},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 13","bm":0,"hd":false},{"ty":"tr","p":{"a":0,"k":[-6.301,-79.894]},"a":{"a":0,"k":[-6.301,-79.894]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":7,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":153,"s":[0]},{"t":160,"s":[100]}]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"hide","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-4.148,1.682],[-15.839,15.68]],"o":[[-1.614,-16.089],[19.748,-6.813],[0,0]],"v":[[28.52,59.211],[42.503,33.884],[96.665,0.149]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.002,1.682],[-0.007,15.68]],"o":[[-0.001,-16.089],[0.009,-6.813],[0,0]],"v":[[26.034,57.324],[15.094,33.847],[15.472,0.11]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-4.148,1.682],[-15.839,15.68]],"o":[[-1.614,-16.089],[19.748,-6.813],[0,0]],"v":[[28.52,59.211],[42.503,33.884],[96.665,0.149]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-4.148,1.682],[-15.839,15.68]],"o":[[-1.614,-16.089],[19.748,-6.813],[0,0]],"v":[[28.52,59.211],[42.503,33.884],[96.665,0.149]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.002,1.682],[-0.007,15.68]],"o":[[-0.001,-16.089],[0.009,-6.813],[0,0]],"v":[[26.034,57.324],[15.094,33.847],[15.472,0.11]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-4.148,1.682],[-15.839,15.68]],"o":[[-1.614,-16.089],[19.748,-6.813],[0,0]],"v":[[28.52,59.211],[42.503,33.884],[96.665,0.149]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.29411765933,0.301960796118,0.309803932905,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 9","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-19.684,-7.025],[1.677,-16.475]],"o":[[15.68,15.849],[4.13,1.645],[0,0]],"v":[[-106.896,-0.946],[-53.089,33.369],[-39.39,58.846]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.009,-7.025],[0.001,-16.475]],"o":[[0.007,15.849],[0.002,1.645],[0,0]],"v":[[-24.87,-0.97],[-24.845,33.345],[-35.613,60.141]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-19.684,-7.025],[1.677,-16.475]],"o":[[15.68,15.849],[4.13,1.645],[0,0]],"v":[[-106.896,-0.946],[-53.089,33.369],[-39.39,58.846]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-19.684,-7.025],[1.677,-16.475]],"o":[[15.68,15.849],[4.13,1.645],[0,0]],"v":[[-106.896,-0.946],[-53.089,33.369],[-39.39,58.846]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.009,-7.025],[0.001,-16.475]],"o":[[0.007,15.849],[0.002,1.645],[0,0]],"v":[[-24.87,-0.97],[-24.845,33.345],[-35.613,60.141]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-19.684,-7.025],[1.677,-16.475]],"o":[[15.68,15.849],[4.13,1.645],[0,0]],"v":[[-106.896,-0.946],[-53.089,33.369],[-39.39,58.846]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.29411765933,0.301960796118,0.309803932905,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 13","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[1.665,-14.166]],"o":[[8.627,1.385],[0,0]],"v":[[-45.118,38.691],[-31.391,58.889]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.001,-14.166]],"o":[[0.004,1.385],[0,0]],"v":[[-29.074,40.113],[-35.609,60.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[1.665,-14.166]],"o":[[8.627,1.385],[0,0]],"v":[[-45.118,38.691],[-31.391,58.889]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[1.665,-14.166]],"o":[[8.627,1.385],[0,0]],"v":[[-45.118,38.691],[-31.391,58.889]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.001,-14.166]],"o":[[0.004,1.385],[0,0]],"v":[[-29.074,40.113],[-35.609,60.184]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[1.665,-14.166]],"o":[[8.627,1.385],[0,0]],"v":[[-45.118,38.691],[-31.391,58.889]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.886274516582,0.913725495338,0.92549020052,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":70},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0.029,-5.319],[0,0],[5.319,0.029],[0,0],[0.781,4.592],[3.399,1.359],[1.527,0.608],[0,0]],"o":[[0,0],[-0.029,5.319],[0,0],[-4.658,-0.025],[-1.869,-10.986],[-1.547,-0.548],[0,0],[5.319,0.029]],"v":[[1.306,40.58],[1.263,48.437],[-8.42,58.016],[-28.173,57.91],[-37.603,49.938],[-51.082,32.376],[-55.683,30.642],[-8.274,30.897]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,-5.319],[0,0],[0.002,0.029],[0,0],[0,4.592],[0.002,1.359],[0.001,0.608],[0,0]],"o":[[0,0],[0,5.319],[0,0],[-0.002,-0.025],[-0.001,-10.986],[-0.001,-0.548],[0,0],[0.002,0.029]],"v":[[7.054,40.612],[7.054,48.469],[-2.95,57.992],[-35.608,59.206],[-35.612,51.234],[-24.845,32.352],[-24.847,30.618],[-15.325,30.87]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0.029,-5.319],[0,0],[5.319,0.029],[0,0],[0.781,4.592],[3.399,1.359],[1.527,0.608],[0,0]],"o":[[0,0],[-0.029,5.319],[0,0],[-4.658,-0.025],[-1.869,-10.986],[-1.547,-0.548],[0,0],[5.319,0.029]],"v":[[1.306,40.58],[1.263,48.437],[-8.42,58.016],[-28.173,57.91],[-37.603,49.938],[-51.082,32.376],[-55.683,30.642],[-8.274,30.897]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0.029,-5.319],[0,0],[5.319,0.029],[0,0],[0.781,4.592],[3.399,1.359],[1.527,0.608],[0,0]],"o":[[0,0],[-0.029,5.319],[0,0],[-4.658,-0.025],[-1.869,-10.986],[-1.547,-0.548],[0,0],[5.319,0.029]],"v":[[1.306,40.58],[1.263,48.437],[-8.42,58.016],[-28.173,57.91],[-37.603,49.938],[-51.082,32.376],[-55.683,30.642],[-8.274,30.897]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,-5.319],[0,0],[0.002,0.029],[0,0],[0,4.592],[0.002,1.359],[0.001,0.608],[0,0]],"o":[[0,0],[0,5.319],[0,0],[-0.002,-0.025],[-0.001,-10.986],[-0.001,-0.548],[0,0],[0.002,0.029]],"v":[[7.054,40.612],[7.054,48.469],[-2.95,57.992],[-35.608,59.206],[-35.612,51.234],[-24.845,32.352],[-24.847,30.618],[-15.325,30.87]],"c":true}]},{"t":160,"s":[{"i":[[0.029,-5.319],[0,0],[5.319,0.029],[0,0],[0.781,4.592],[3.399,1.359],[1.527,0.608],[0,0]],"o":[[0,0],[-0.029,5.319],[0,0],[-4.658,-0.025],[-1.869,-10.986],[-1.547,-0.548],[0,0],[5.319,0.029]],"v":[[1.306,40.58],[1.263,48.437],[-8.42,58.016],[-28.173,57.91],[-37.603,49.938],[-51.082,32.376],[-55.683,30.642],[-8.274,30.897]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,0.641,0.647,0.653,1,0.282,0.294,0.306]}},"s":{"a":0,"k":[-25.068,57.011]},"e":{"a":0,"k":[-24.245,37.72]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"base-round 2","sr":1,"ks":{"r":{"a":0,"k":45.436},"p":{"a":0,"k":[290.875,212.356,0]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-4.148,1.682]],"o":[[-1.614,-16.089],[19.748,-6.813]],"v":[[28.52,59.211],[42.503,33.884]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.006,1.682]],"o":[[0.002,-16.089],[-0.03,-6.813]],"v":[[27.295,59.537],[15.78,33.767]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-4.148,1.682]],"o":[[-1.614,-16.089],[19.748,-6.813]],"v":[[28.52,59.211],[42.503,33.884]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-4.148,1.682]],"o":[[-1.614,-16.089],[19.748,-6.813]],"v":[[28.52,59.211],[42.503,33.884]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.006,1.682]],"o":[[0.002,-16.089],[-0.03,-6.813]],"v":[[27.295,59.537],[15.78,33.767]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-4.148,1.682]],"o":[[-1.614,-16.089],[19.748,-6.813]],"v":[[28.52,59.211],[42.503,33.884]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[0.603921592236,0.556862771511,0.501960813999,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.001]},"t":10,"s":[0.443137288094,0.462745130062,0.486274540424,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0.603921592236,0.556862771511,0.501960813999,1]},{"i":{"x":[0.833],"y":[1.001]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0.603921592236,0.556862771511,0.501960813999,1]},{"i":{"x":[0.833],"y":[0.999]},"o":{"x":[0.167],"y":[0.001]},"t":150,"s":[0.443137288094,0.462745130062,0.486274540424,1]},{"t":160,"s":[0.603921592236,0.556862771511,0.501960813999,1]}]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475]],"o":[[4.13,1.645],[0,0]],"v":[[-53.089,33.369],[-39.39,58.846]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.131,-7.025],[-0.011,-16.475]],"o":[[-0.027,1.645],[0,0]],"v":[[-24.398,33.489],[-35.805,58.698]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475]],"o":[[4.13,1.645],[0,0]],"v":[[-53.089,33.369],[-39.39,58.846]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475]],"o":[[4.13,1.645],[0,0]],"v":[[-53.089,33.369],[-39.39,58.846]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.131,-7.025],[-0.011,-16.475]],"o":[[-0.027,1.645],[0,0]],"v":[[-24.398,33.489],[-35.805,58.698]],"c":false}]},{"t":160,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475]],"o":[[4.13,1.645],[0,0]],"v":[[-53.089,33.369],[-39.39,58.846]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[0.57647061348,0.564705908298,0.596078455448,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.001]},"t":10,"s":[0.443137288094,0.462745130062,0.486274540424,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0.57647061348,0.564705908298,0.596078455448,1]},{"i":{"x":[0.833],"y":[1.001]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0.57647061348,0.564705908298,0.596078455448,1]},{"i":{"x":[0.833],"y":[0.999]},"o":{"x":[0.167],"y":[0.001]},"t":150,"s":[0.443137288094,0.462745130062,0.486274540424,1]},{"t":160,"s":[0.57647061348,0.564705908298,0.596078455448,1]}]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475],[0,0],[-4.148,1.682]],"o":[[4.13,1.645],[0,0],[-1.614,-16.089],[19.748,-6.813]],"v":[[-53.089,33.369],[-39.39,58.846],[28.52,59.211],[42.503,33.884]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.131,-7.025],[-0.011,-16.475],[0,0],[0.006,1.682]],"o":[[-0.027,1.645],[0,0],[0.002,-16.089],[-0.03,-6.813]],"v":[[-24.398,33.489],[-35.805,58.697],[27.295,59.537],[15.78,33.767]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475],[0,0],[-4.148,1.682]],"o":[[4.13,1.645],[0,0],[-1.614,-16.089],[19.748,-6.813]],"v":[[-53.089,33.369],[-39.39,58.846],[28.52,59.211],[42.503,33.884]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475],[0,0],[-4.148,1.682]],"o":[[4.13,1.645],[0,0],[-1.614,-16.089],[19.748,-6.813]],"v":[[-53.089,33.369],[-39.39,58.846],[28.52,59.211],[42.503,33.884]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.131,-7.025],[-0.011,-16.475],[0,0],[0.006,1.682]],"o":[[-0.027,1.645],[0,0],[0.002,-16.089],[-0.03,-6.813]],"v":[[-24.398,33.489],[-35.805,58.697],[27.295,59.537],[15.78,33.767]],"c":true}]},{"t":160,"s":[{"i":[[-19.684,-7.025],[1.677,-16.475],[0,0],[-4.148,1.682]],"o":[[4.13,1.645],[0,0],[-1.614,-16.089],[19.748,-6.813]],"v":[[-53.089,33.369],[-39.39,58.846],[28.52,59.211],[42.503,33.884]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.282,0.294,0.306,0.5,0.283,0.294,0.306,1,0.284,0.293,0.306]}},"s":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"t":160,"s":[-22.476,-223.466]}]},"e":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"t":160,"s":[48.472,31.505]}]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"base-side8","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":4,"s":[100]},{"i":{"x":[1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[100]},{"t":19,"s":[25.75],"h":1},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":20,"s":[1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[1]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":141,"s":[25.75]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":144,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":156,"s":[100]},{"t":160,"s":[1]}]},"r":{"a":0,"k":45.436},"p":{"a":0,"k":[290.875,212.356,0]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":5,"s":[{"i":[[-132.091,0],[-0.122,0.338],[-122.04,0],[0.316,-0.232]],"o":[[-0.319,0],[-123.315,0],[-0.122,-0.035],[-97.39,0]],"v":[[2.716,-245.657],[-11.603,-245.654],[-11.593,41.243],[2.39,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[15.382,-245.657],[-24.189,-245.652],[-24.161,41.246],[14.476,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":12,"s":[{"i":[[47.224,0],[0.042,0.115],[48.434,0],[-0.107,-0.079]],"o":[[0.108,0],[44.956,0],[0.042,-0.012],[51.434,-2.364]],"v":[[11.276,-245.657],[-19.706,-245.653],[-19.684,41.245],[10.566,40.864]],"c":true}]},{"i":{"x":1,"y":1},"o":{"x":0.167,"y":0},"t":16,"s":[{"i":[[140.935,0],[0.125,0.346],[124.502,0],[-0.322,-0.237]],"o":[[0.324,0],[125.807,0],[0.125,-0.035],[143.253,0]],"v":[[3.065,-245.657],[-10.74,-245.654],[-10.73,41.243],[2.747,40.864]],"c":true}]},{"t":19,"s":[{"i":[[187.362,0],[0.187,0.519],[181.553,0],[-0.482,-0.356]],"o":[[0.487,0],[186.444,0],[0.187,-0.053],[178.556,0]],"v":[[-3.094,-245.657],[-4.016,-245.656],[-4.015,41.242],[-3.118,40.864]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":141,"s":[{"i":[[187.362,0],[0.187,0.519],[181.553,0],[-0.482,-0.356]],"o":[[0.487,0],[186.444,0],[0.187,-0.053],[178.556,0]],"v":[[-3.094,-245.657],[-4.016,-245.656],[-4.015,41.242],[-3.118,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":144,"s":[{"i":[[140.935,0],[0.125,0.346],[124.502,0],[-0.322,-0.237]],"o":[[0.324,0],[125.807,0],[0.125,-0.035],[143.253,0]],"v":[[3.065,-245.657],[-10.74,-245.654],[-10.73,41.243],[2.747,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":148,"s":[{"i":[[47.224,0],[0.042,0.115],[48.434,0],[-0.107,-0.079]],"o":[[0.108,0],[44.956,0],[0.042,-0.012],[51.434,-2.364]],"v":[[11.276,-245.657],[-19.706,-245.653],[-19.684,41.245],[10.566,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[15.382,-245.657],[-24.189,-245.652],[-24.161,41.246],[14.476,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[-132.091,0],[-0.122,0.338],[-122.04,0],[0.316,-0.232]],"o":[[-0.319,0],[-123.315,0],[-0.122,-0.035],[-97.39,0]],"v":[[2.716,-245.657],[-11.603,-245.654],[-11.593,41.243],[2.39,40.864]],"c":true}]},{"t":160,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.4392157197,0.458823561668,0.482352972031,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[0]},{"i":{"x":[1],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":8,"s":[0]},{"t":10,"s":[0],"h":1},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":12,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":148,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":150,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":152,"s":[0]},{"t":160,"s":[0]}]},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[57]},{"i":{"x":[1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[57]},{"t":10,"s":[100],"h":1},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[57]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":12,"s":[57]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[57]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[57]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":148,"s":[57]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":149,"s":[57]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":151,"s":[57]},{"t":160,"s":[57]}]},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[-4]},{"i":{"x":[1],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":8,"s":[-4]},{"t":10,"s":[-4],"h":1},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[177]},{"i":{"x":[1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":12,"s":[171]},{"t":16,"s":[166],"h":1},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":20,"s":[-4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[-4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":144,"s":[166]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":148,"s":[171]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":149,"s":[177]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":150,"s":[-4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":152,"s":[-4]},{"t":160,"s":[-4]}]},"m":1,"nm":"Trim Paths 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":5,"s":[{"i":[[-103.966,24.032],[-0.122,0.338],[-122.04,0],[0.316,-0.232]],"o":[[-0.319,0],[-123.315,0],[-0.122,-0.035],[-111.39,-41.114]],"v":[[2.716,-245.657],[-11.603,-245.654],[-11.593,41.243],[2.39,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":8,"s":[{"i":[[-51.315,61.657],[-0.049,0.135],[-48.816,0],[0.126,-0.093]],"o":[[-0.127,0],[-49.326,0],[-0.049,-0.014],[-41.641,-51.364]],"v":[[10.315,-245.657],[-19.155,-245.653],[-19.134,41.245],[9.641,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[15.382,-245.657],[-24.189,-245.652],[-24.161,41.246],[14.476,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":12,"s":[{"i":[[41.636,0],[0.042,0.115],[47.934,-36.745],[-0.107,-0.079]],"o":[[0.108,0],[42.706,32.903],[0.042,-0.012],[39.679,0]],"v":[[11.276,-245.657],[-19.706,-245.653],[-19.684,41.245],[10.566,40.864]],"c":true}]},{"i":{"x":1,"y":1},"o":{"x":0.167,"y":0},"t":16,"s":[{"i":[[152.935,0],[0.125,0.346],[124.288,-15.748],[-0.322,-0.237]],"o":[[0.324,0],[124.842,14.101],[0.125,-0.035],[139.253,0]],"v":[[3.065,-245.657],[-10.74,-245.654],[-10.73,41.243],[2.747,40.864]],"c":true}]},{"t":19,"s":[{"i":[[187.362,0],[0.187,0.519],[181.553,0],[-0.482,-0.356]],"o":[[0.487,0],[186.444,0],[0.187,-0.053],[178.556,0]],"v":[[-3.094,-245.657],[-4.016,-245.656],[-4.015,41.242],[-3.118,40.864]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":141,"s":[{"i":[[187.362,0],[0.187,0.519],[181.553,0],[-0.482,-0.356]],"o":[[0.487,0],[186.444,0],[0.187,-0.053],[178.556,0]],"v":[[-3.094,-245.657],[-4.016,-245.656],[-4.015,41.242],[-3.118,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":144,"s":[{"i":[[152.935,0],[0.125,0.346],[124.288,-15.748],[-0.322,-0.237]],"o":[[0.324,0],[124.842,14.101],[0.125,-0.035],[139.253,0]],"v":[[3.065,-245.657],[-10.74,-245.654],[-10.73,41.243],[2.747,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":148,"s":[{"i":[[41.636,0],[0.042,0.115],[47.934,-36.745],[-0.107,-0.079]],"o":[[0.108,0],[42.706,32.903],[0.042,-0.012],[39.679,0]],"v":[[11.276,-245.657],[-19.706,-245.653],[-19.684,41.245],[10.566,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[15.382,-245.657],[-24.189,-245.652],[-24.161,41.246],[14.476,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":152,"s":[{"i":[[-51.315,61.657],[-0.049,0.135],[-48.816,0],[0.126,-0.093]],"o":[[-0.127,0],[-49.326,0],[-0.049,-0.014],[-41.641,-51.364]],"v":[[10.315,-245.657],[-19.155,-245.653],[-19.134,41.245],[9.641,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":155,"s":[{"i":[[-103.966,24.032],[-0.122,0.338],[-122.04,0],[0.316,-0.232]],"o":[[-0.319,0],[-123.315,0],[-0.122,-0.035],[-111.39,-41.114]],"v":[[2.716,-245.657],[-11.603,-245.654],[-11.593,41.243],[2.39,40.864]],"c":true}]},{"t":160,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":2,"k":{"a":0,"k":[0,1,1,1,1,0,0,0]}},"s":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"t":160,"s":[-22.476,-223.466]}]},"e":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"t":160,"s":[48.472,31.505]}]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"base-glass 7","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.318],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":149,"s":[0]},{"i":{"x":[0.613],"y":[0.579]},"o":{"x":[0.276],"y":[0.237]},"t":150,"s":[100]},{"t":160,"s":[92.25]}]},"r":{"a":0,"k":45.436},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":0,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[304.909,226.606,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":140,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[304.909,226.606,0],"to":[0,0,0],"ti":[0,0,0]},{"t":160,"s":[290.875,212.356,0]}]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.11,-14.025],[-0.022,4.851],[0.18,27.857],[0.007,-10.446]],"o":[[0.147,18.696],[0.024,-5.375],[-0.196,-30.409],[-0.007,10.551]],"v":[[-4.504,-143.551],[-4.207,-114.018],[-4.386,-193.84],[-4.772,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.11,-14.025],[-0.022,4.851],[0.18,27.857],[0.007,-10.446]],"o":[[0.147,18.696],[0.024,-5.375],[-0.196,-30.409],[-0.007,10.551]],"v":[[-4.504,-143.551],[-4.207,-114.018],[-4.386,-193.84],[-4.772,-186.825]],"c":true}]},{"t":160,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":6,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[10]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[10]},{"t":160,"s":[0]}]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[-0.183,-0.634],[-0.167,-46.376],[0,0]],"v":[[-4.57,41.384],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[-0.183,-0.634],[-0.167,-46.376],[0,0]],"v":[[-4.57,41.384],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"t":160,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.603921592236,0.556862771511,0.501960813999,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.002,-2.167]],"o":[[0.002,2.191],[0,0]],"v":[[-4.985,-76.54],[-4.979,-70.002]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.002,-2.167]],"o":[[0.002,2.191],[0,0]],"v":[[-4.985,-76.54],[-4.979,-70.002]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.032,-8.828]],"o":[[0.02,10.521],[0,0]],"v":[[-4.944,-45.089],[-4.867,-15.873]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.032,-8.828]],"o":[[0.02,10.521],[0,0]],"v":[[-4.944,-45.089],[-4.867,-15.873]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]}]},"nm":"Контур 2","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[8]},{"t":7,"s":[0],"h":1},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":20,"s":[8]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[8]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":153,"s":[0]},{"t":160,"s":[8]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.155,-43.124],[-0.168,47.754],[-0.019,19.102]],"o":[[-0.126,47.838],[0.17,47.243],[0.053,-15.114],[0,0]],"v":[[-4.91,-174.751],[-4.867,-15.873],[-4.255,-16.799],[-4.146,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.155,-43.124],[-0.168,47.754],[-0.019,19.102]],"o":[[-0.126,47.838],[0.17,47.243],[0.053,-15.114],[0,0]],"v":[[-4.91,-174.751],[-4.867,-15.873],[-4.255,-16.799],[-4.146,-69.057]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.596078455448,0.647058844566,0.729411780834,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.17,-47.254],[-0.168,47.765],[0.17,47.243],[0.168,-47.754]],"o":[[0.17,47.243],[0.168,-47.765],[-0.17,-47.254],[-0.168,47.754]],"v":[[-4.867,-15.873],[-4.255,-16.799],[-4.258,-188.83],[-4.87,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.17,-47.254],[-0.168,47.765],[0.17,47.243],[0.168,-47.754]],"o":[[0.17,47.243],[0.168,-47.765],[-0.17,-47.254],[-0.168,47.754]],"v":[[-4.867,-15.873],[-4.255,-16.799],[-4.258,-188.83],[-4.87,-187.904]],"c":true}]},{"t":160,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.415686279535,0.435294121504,0.46274510026,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.131,-37.169],[0.184,2.131]],"o":[[0.042,47.25],[-0.056,15.849],[-0.015,1.645]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.571,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.131,-37.169],[0.184,2.131]],"o":[[0.042,47.25],[-0.056,15.849],[-0.015,1.645]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.571,41.369]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.57647061348,0.564705908298,0.596078455448,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.131,-37.169],[0.07,-7.025],[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[0.042,47.25],[-0.056,15.849],[-0.139,15.631],[-0.07,-6.813],[-0.167,-46.376],[0,0]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.131,-37.169],[0.07,-7.025],[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[0.042,47.25],[-0.056,15.849],[-0.139,15.631],[-0.07,-6.813],[-0.167,-46.376],[0,0]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.186,15.381],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.186,15.381],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"t":160,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]}]},"nm":"Контур 2","hd":false},{"ty":"st","c":{"a":0,"k":[0.392156869173,0.596078455448,0.749019622803,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.17,-47.26],[-0.168,47.771],[0.17,47.249],[0.168,-47.76]],"o":[[0.17,47.249],[0.168,-47.771],[-0.17,-47.26],[-0.168,47.76]],"v":[[-4.867,-15.689],[-4.255,-16.615],[-4.258,-188.667],[-4.87,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.17,-47.26],[-0.168,47.771],[0.17,47.249],[0.168,-47.76]],"o":[[0.17,47.249],[0.168,-47.771],[-0.17,-47.26],[-0.168,47.76]],"v":[[-4.867,-15.689],[-4.255,-16.615],[-4.258,-188.667],[-4.87,-187.742]],"c":true}]},{"t":160,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.169,14.631],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.169,14.631],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"t":160,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]}]},"nm":"Контур 2","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.627,0.733,0.859,0.25,0.812,0.865,0.927,0.5,0.996,0.996,0.996,0.75,0.635,0.639,0.645,1,0.275,0.282,0.294]}},"s":{"a":0,"k":[-40.657,-257.764]},"e":{"a":0,"k":[-64.94,27.475]},"t":1,"nm":"Gradient Fill 2","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"base-glass 6","sr":1,"ks":{"r":{"a":0,"k":45.436},"p":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[276.841,198.107,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":150,"s":[276.841,198.107,0],"to":[0,0,0],"ti":[0,0,0]},{"t":160,"s":[290.875,212.356,0]}]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[-0.183,-0.634],[-0.167,-46.376],[0,0]],"v":[[-4.57,41.384],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[-0.183,-0.634],[-0.167,-46.376],[0,0]],"v":[[-4.57,41.384],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"t":160,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.603921592236,0.556862771511,0.501960813999,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.155,-43.124],[-0.168,47.754],[-0.019,19.102]],"o":[[-0.126,47.838],[0.17,47.243],[0.053,-15.114],[0,0]],"v":[[-4.91,-174.751],[-4.867,-15.873],[-4.255,-16.799],[-4.146,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.155,-43.124],[-0.168,47.754],[-0.019,19.102]],"o":[[-0.126,47.838],[0.17,47.243],[0.053,-15.114],[0,0]],"v":[[-4.91,-174.751],[-4.867,-15.873],[-4.255,-16.799],[-4.146,-69.057]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.596078455448,0.647058844566,0.729411780834,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false},{"ty":"tr","p":{"a":0,"k":[-3.855,-104.374]},"a":{"a":0,"k":[-3.855,-104.374]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":-0.036},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":149,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":150,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":159,"s":[0]},{"t":160,"s":[100]}]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"vischeck","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.11,-14.025],[-0.022,4.851],[0.18,27.857],[0.007,-10.446]],"o":[[0.147,18.696],[0.024,-5.375],[-0.196,-30.409],[-0.007,10.551]],"v":[[-4.504,-143.551],[-4.207,-114.018],[-4.386,-193.84],[-4.772,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.11,-14.025],[-0.022,4.851],[0.18,27.857],[0.007,-10.446]],"o":[[0.147,18.696],[0.024,-5.375],[-0.196,-30.409],[-0.007,10.551]],"v":[[-4.504,-143.551],[-4.207,-114.018],[-4.386,-193.84],[-4.772,-186.825]],"c":true}]},{"t":160,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":10},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.17,-47.254],[-0.168,47.765],[0.17,47.243],[0.168,-47.754]],"o":[[0.17,47.243],[0.168,-47.765],[-0.17,-47.254],[-0.168,47.754]],"v":[[-4.867,-15.873],[-4.255,-16.799],[-4.258,-188.83],[-4.87,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.17,-47.254],[-0.168,47.765],[0.17,47.243],[0.168,-47.754]],"o":[[0.17,47.243],[0.168,-47.765],[-0.17,-47.254],[-0.168,47.754]],"v":[[-4.867,-15.873],[-4.255,-16.799],[-4.258,-188.83],[-4.87,-187.904]],"c":true}]},{"t":160,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.415686279535,0.435294121504,0.46274510026,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.131,-37.169],[0.184,2.131]],"o":[[0.042,47.25],[-0.056,15.849],[-0.015,1.645]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.571,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.131,-37.169],[0.184,2.131]],"o":[[0.042,47.25],[-0.056,15.849],[-0.015,1.645]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.571,41.369]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.57647061348,0.564705908298,0.596078455448,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.131,-37.169],[0.07,-7.025],[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[0.042,47.25],[-0.056,15.849],[-0.139,15.631],[-0.07,-6.813],[-0.167,-46.376],[0,0]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.131,-37.169],[0.07,-7.025],[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[0.042,47.25],[-0.056,15.849],[-0.139,15.631],[-0.07,-6.813],[-0.167,-46.376],[0,0]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.186,15.381],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.186,15.381],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"t":160,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]}]},"nm":"Контур 2","hd":false},{"ty":"st","c":{"a":0,"k":[0.392156869173,0.596078455448,0.749019622803,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":149,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":150,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":159,"s":[0]},{"t":160,"s":[100]}]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.17,-47.26],[-0.168,47.771],[0.17,47.249],[0.168,-47.76]],"o":[[0.17,47.249],[0.168,-47.771],[-0.17,-47.26],[-0.168,47.76]],"v":[[-4.867,-15.689],[-4.255,-16.615],[-4.258,-188.667],[-4.87,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.17,-47.26],[-0.168,47.771],[0.17,47.249],[0.168,-47.76]],"o":[[0.17,47.249],[0.168,-47.771],[-0.17,-47.26],[-0.168,47.76]],"v":[[-4.867,-15.689],[-4.255,-16.615],[-4.258,-188.667],[-4.87,-187.742]],"c":true}]},{"t":160,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.169,14.631],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.169,14.631],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"t":160,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]}]},"nm":"Контур 2","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.627,0.733,0.859,0.25,0.812,0.865,0.927,0.5,0.996,0.996,0.996,0.75,0.635,0.639,0.645,1,0.275,0.282,0.294]}},"s":{"a":0,"k":[-52.984,-297.977]},"e":{"a":0,"k":[-64.94,27.475]},"t":1,"nm":"Gradient Fill 2","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"base-glass 5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.318],"y":[0]},"t":20,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":149,"s":[100]},{"i":{"x":[0.613],"y":[0.579]},"o":{"x":[0.276],"y":[0.237]},"t":150,"s":[0]},{"t":160,"s":[7.75]}]},"r":{"a":0,"k":45.436},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":0,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[304.909,226.606,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":140,"s":[290.875,212.356,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[304.909,226.606,0],"to":[0,0,0],"ti":[0,0,0]},{"t":160,"s":[290.875,212.356,0]}]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.11,-14.025],[-0.022,4.851],[0.18,27.857],[0.007,-10.446]],"o":[[0.147,18.696],[0.024,-5.375],[-0.196,-30.409],[-0.007,10.551]],"v":[[-4.504,-143.551],[-4.207,-114.018],[-4.386,-193.84],[-4.772,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.11,-14.025],[-0.022,4.851],[0.18,27.857],[0.007,-10.446]],"o":[[0.147,18.696],[0.024,-5.375],[-0.196,-30.409],[-0.007,10.551]],"v":[[-4.504,-143.551],[-4.207,-114.018],[-4.386,-193.84],[-4.772,-186.825]],"c":true}]},{"t":160,"s":[{"i":[[31.028,-14.025],[6.197,4.851],[-50.572,27.857],[-2.083,-10.446]],"o":[[-41.362,18.696],[-6.866,-5.375],[55.205,-30.409],[2.104,10.551]],"v":[[-21.078,-143.551],[-104.67,-114.018],[-54.391,-193.84],[54.341,-186.825]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[10]},{"t":160,"s":[10]}]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[-0.183,-0.634],[-0.167,-46.376],[0,0]],"v":[[-4.57,41.384],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[-0.183,-0.634],[-0.167,-46.376],[0,0]],"v":[[-4.57,41.384],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"t":160,"s":[{"i":[[-4.148,1.682],[-15.839,15.68],[30.438,54.988]],"o":[[51.497,-0.634],[46.887,-46.376],[0,0]],"v":[[-2.497,41.384],[96.665,0.149],[121.444,-171.832]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.603921592236,0.556862771511,0.501960813999,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.002,-2.167]],"o":[[0.002,2.191],[0,0]],"v":[[-4.985,-76.54],[-4.979,-70.002]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.002,-2.167]],"o":[[0.002,2.191],[0,0]],"v":[[-4.985,-76.54],[-4.979,-70.002]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[0.596,-2.167]],"o":[[-0.474,2.191],[0,0]],"v":[[114.179,-76.54],[112.575,-70.002]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.032,-8.828]],"o":[[0.02,10.521],[0,0]],"v":[[-4.944,-45.089],[-4.867,-15.873]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.032,-8.828]],"o":[[0.02,10.521],[0,0]],"v":[[-4.944,-45.089],[-4.867,-15.873]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[8.923,-8.828]],"o":[[-5.616,10.521],[0,0]],"v":[[102.649,-45.089],[80.839,-15.873]],"c":false}]}]},"nm":"Контур 2","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[-0.155,-43.124],[-0.168,47.754],[-0.019,19.102]],"o":[[-0.126,47.838],[0.17,47.243],[0.053,-15.114],[0,0]],"v":[[-4.91,-174.751],[-4.867,-15.873],[-4.255,-16.799],[-4.146,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[-0.155,-43.124],[-0.168,47.754],[-0.019,19.102]],"o":[[-0.126,47.838],[0.17,47.243],[0.053,-15.114],[0,0]],"v":[[-4.91,-174.751],[-4.867,-15.873],[-4.255,-16.799],[-4.146,-69.057]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[43.59,-43.124],[47.254,47.754],[5.416,19.102]],"o":[[35.521,47.838],[-47.754,47.243],[-14.949,-15.114],[0,0]],"v":[[93.062,-174.751],[80.839,-15.873],[-91.192,-16.799],[-121.734,-69.057]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.596078455448,0.647058844566,0.729411780834,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false},{"ty":"tr","p":{"a":0,"k":[-1.2,-66.684]},"a":{"a":0,"k":[-1.2,-66.684]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.318],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":149,"s":[0]},{"i":{"x":[0.613],"y":[0.579]},"o":{"x":[0.276],"y":[0.237]},"t":150,"s":[100]},{"t":160,"s":[92.25]}]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"vis1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.17,-47.254],[-0.168,47.765],[0.17,47.243],[0.168,-47.754]],"o":[[0.17,47.243],[0.168,-47.765],[-0.17,-47.254],[-0.168,47.754]],"v":[[-4.867,-15.873],[-4.255,-16.799],[-4.258,-188.83],[-4.87,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.17,-47.254],[-0.168,47.765],[0.17,47.243],[0.168,-47.754]],"o":[[0.17,47.243],[0.168,-47.765],[-0.17,-47.254],[-0.168,47.754]],"v":[[-4.867,-15.873],[-4.255,-16.799],[-4.258,-188.83],[-4.87,-187.904]],"c":true}]},{"t":160,"s":[{"i":[[47.765,-47.254],[47.254,47.754],[-47.754,47.243],[-47.243,-47.765]],"o":[[-47.754,47.243],[-47.243,-47.765],[47.765,-47.254],[47.254,47.754]],"v":[[80.838,-15.873],[-91.192,-16.799],[-90.267,-188.83],[81.764,-187.904]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.415686279535,0.435294121504,0.46274510026,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.131,-37.169],[0.184,2.131]],"o":[[0.042,47.25],[-0.056,15.849],[-0.015,1.645]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.571,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.131,-37.169],[0.184,2.131]],"o":[[0.042,47.25],[-0.056,15.849],[-0.015,1.645]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.571,41.369]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-36.771,-37.169],[-51.661,2.131]],"o":[[-11.915,47.25],[15.68,15.849],[4.13,1.645]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-2.339,41.369]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.57647061348,0.564705908298,0.596078455448,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0.131,-37.169],[0.07,-7.025],[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[0.042,47.25],[-0.056,15.849],[-0.139,15.631],[-0.07,-6.813],[-0.167,-46.376],[0,0]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0.131,-37.169],[0.07,-7.025],[0.015,1.682],[0.056,15.68],[-0.108,54.988]],"o":[[0.042,47.25],[-0.056,15.849],[-0.139,15.631],[-0.07,-6.813],[-0.167,-46.376],[0,0]],"v":[[-4.066,-137.511],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149],[-5.011,-171.832]],"c":false}]},{"t":160,"s":[{"i":[[0,0],[-36.771,-37.169],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68],[30.439,54.988]],"o":[[-11.915,47.25],[15.68,15.849],[39.089,15.631],[19.748,-6.813],[46.887,-46.376],[0,0]],"v":[[-144.126,-137.511],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149],[121.444,-171.832]],"c":false}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.186,15.381],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.186,15.381],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"t":160,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[52.339,15.381],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]}]},"nm":"Контур 2","hd":false},{"ty":"st","c":{"a":0,"k":[0.392156869173,0.596078455448,0.749019622803,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false},{"ty":"tr","p":{"a":0,"k":[-4.563,-102.322]},"a":{"a":0,"k":[-4.563,-102.322]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.318],"y":[0]},"t":20,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":149,"s":[0]},{"i":{"x":[0.613],"y":[0.579]},"o":{"x":[0.276],"y":[0.237]},"t":150,"s":[100]},{"t":160,"s":[92.25]}]},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"vis2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.17,-47.26],[-0.168,47.771],[0.17,47.249],[0.168,-47.76]],"o":[[0.17,47.249],[0.168,-47.771],[-0.17,-47.26],[-0.168,47.76]],"v":[[-4.867,-15.689],[-4.255,-16.615],[-4.258,-188.667],[-4.87,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.17,-47.26],[-0.168,47.771],[0.17,47.249],[0.168,-47.76]],"o":[[0.17,47.249],[0.168,-47.771],[-0.17,-47.26],[-0.168,47.76]],"v":[[-4.867,-15.689],[-4.255,-16.615],[-4.258,-188.667],[-4.87,-187.742]],"c":true}]},{"t":160,"s":[{"i":[[47.771,-47.26],[47.26,47.76],[-47.76,47.249],[-47.249,-47.771]],"o":[[-47.76,47.249],[-47.249,-47.771],[47.771,-47.26],[47.26,47.76]],"v":[[80.995,-15.689],[-91.057,-16.615],[-90.131,-188.667],[81.921,-187.742]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.169,14.631],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-0.199,56.523],[-0.201,-55.919],[0.199,-56.513],[0.07,-7.025],[0.015,1.682],[0.056,15.68]],"o":[[0.199,-56.523],[0.201,55.908],[-0.056,15.849],[-0.169,14.631],[-0.07,-6.813],[-0.201,-55.908]],"v":[[-4.927,-203.411],[-4.203,-204.506],[-4.199,-0.946],[-4.39,33.369],[-4.73,33.884],[-4.923,0.149]],"c":true}]},{"t":160,"s":[{"i":[[55.919,56.513],[56.513,-55.919],[-55.908,-56.513],[-19.684,-7.025],[-4.148,1.682],[-15.839,15.68]],"o":[[-55.908,-56.523],[-56.513,55.908],[15.68,15.849],[47.589,14.631],[19.748,-6.813],[56.523,-55.908]],"v":[[97.76,-203.411],[-105.8,-204.506],[-106.896,-0.946],[-53.089,33.369],[42.503,33.884],[96.665,0.149]],"c":true}]}]},"nm":"Контур 2","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.553,0.592,0.635,0.139,0.557,0.596,0.637,0.492,0.561,0.6,0.639,0.839,0.551,0.59,0.633,0.999,0.541,0.58,0.627,0,0,0.139,0.5,0.492,1,0.839,0.5,0.999,0]}},"s":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"t":160,"s":[-22.476,-223.466]}]},"e":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"t":160,"s":[48.472,31.505]}]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":10,"op":150,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"base-side7","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":19,"s":[1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.31],"y":[0]},"t":20,"s":[16.97]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[16.97]},{"i":{"x":[0.593],"y":[0.559]},"o":{"x":[0.251],"y":[0.205]},"t":141,"s":[1]},{"t":160,"s":[3.333]}]},"r":{"a":0,"k":45.436},"p":{"a":0,"k":[290.875,212.356,0]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":19,"s":[{"i":[[191.508,0],[0.191,0.531],[185.569,0],[-0.493,-0.364]],"o":[[0.497,0],[190.569,0],[0.191,-0.054],[182.507,0]],"v":[[-6.503,-245.657],[-6.569,-245.656],[-6.569,41.242],[-6.507,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[188.041,0],[0.188,0.521],[182.21,0],[-0.484,-0.357]],"o":[[0.488,0],[187.119,0],[0.188,-0.053],[179.203,0]],"v":[[-6.113,-245.657],[-6.882,-245.656],[-6.881,41.242],[-6.134,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[188.041,0],[0.188,0.521],[182.21,0],[-0.484,-0.357]],"o":[[0.488,0],[187.119,0],[0.188,-0.053],[179.203,0]],"v":[[-6.113,-245.657],[-6.882,-245.656],[-6.881,41.242],[-6.134,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":141,"s":[{"i":[[191.508,0],[0.191,0.531],[185.569,0],[-0.493,-0.364]],"o":[[0.497,0],[190.569,0],[0.191,-0.054],[182.507,0]],"v":[[-6.503,-245.657],[-6.569,-245.656],[-6.569,41.242],[-6.507,40.864]],"c":true}]},{"t":160,"s":[{"i":[[191.371,0],[0.191,0.53],[185.437,0],[-0.493,-0.363]],"o":[[0.497,0],[190.433,0],[0.191,-0.054],[182.377,0]],"v":[[-6.487,-245.657],[-6.582,-245.656],[-6.582,41.242],[-6.492,40.864]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.553,0.592,0.635,0.139,0.557,0.596,0.637,0.492,0.561,0.6,0.639,0.839,0.551,0.59,0.633,0.999,0.541,0.58,0.627,0,0,0.139,0.5,0.492,1,0.839,0.5,0.999,0]}},"s":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"t":160,"s":[-22.476,-223.466]}]},"e":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":20,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":140,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"t":160,"s":[48.472,31.505]}]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false}],"ip":19,"op":141,"st":19,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"base-side6","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":124,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":136,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":140,"s":[1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":144,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":156,"s":[100]},{"t":160,"s":[1]}]},"r":{"a":0,"k":45.436},"p":{"a":0,"k":[290.875,212.356,0]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":127,"s":[{"i":[[-57.979,0],[-0.074,0.206],[-74.201,0],[0.192,-0.141]],"o":[[-0.194,0],[-74.975,0],[-0.074,-0.021],[-74.176,0]],"v":[[8.979,-245.657],[-17.835,-245.653],[-17.816,41.244],[8.366,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":130,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[17.5,-245.657],[-26.308,-245.652],[-26.276,41.246],[16.497,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[{"i":[[191.508,0],[0.191,0.531],[185.569,0],[-0.493,-0.364]],"o":[[0.497,0],[190.569,0],[0.191,-0.054],[182.507,0]],"v":[[-7.503,-245.657],[-7.569,-245.656],[-7.569,41.242],[-7.507,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[15.382,-245.657],[-24.189,-245.652],[-24.161,41.246],[14.476,40.864]],"c":true}]},{"t":160,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.553,0.592,0.635,0.139,0.557,0.596,0.637,0.492,0.561,0.6,0.639,0.839,0.551,0.59,0.633,0.999,0.541,0.58,0.627,0,0,0.139,0.5,0.492,1,0.839,0.5,0.999,0]}},"s":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":120,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":140,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"t":160,"s":[-22.476,-223.466]}]},"e":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":120,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":140,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"t":160,"s":[48.472,31.505]}]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false}],"ip":141,"op":180,"st":160,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"base-side5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-20,"s":[1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-16,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-4,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":4,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[100]},{"t":20,"s":[1]}]},"r":{"a":0,"k":45.436},"p":{"a":0,"k":[290.875,212.356,0]},"a":{"a":0,"k":[-4.564,-93.458,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":-20,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":-10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[15.382,-245.657],[-24.189,-245.652],[-24.161,41.246],[14.476,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[191.508,0],[0.191,0.531],[185.569,0],[-0.493,-0.364]],"o":[[0.497,0],[190.569,0],[0.191,-0.054],[182.507,0]],"v":[[-7.503,-245.657],[-7.569,-245.656],[-7.569,41.242],[-7.507,40.864]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[17.5,-245.657],[-26.308,-245.652],[-26.276,41.246],[16.497,40.864]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":13,"s":[{"i":[[-57.979,0],[-0.074,0.206],[-74.201,0],[0.192,-0.141]],"o":[[-0.194,0],[-74.975,0],[-0.074,-0.021],[-74.176,0]],"v":[[8.979,-245.657],[-17.835,-245.653],[-17.816,41.244],[8.366,40.864]],"c":true}]},{"t":20,"s":[{"i":[[-192.5,0],[-0.192,0.531],[-191.567,0],[0.496,-0.364]],"o":[[-0.5,0],[-193.567,0],[-0.192,-0.054],[-191.504,0]],"v":[[-4.5,-245.657],[-4.433,-245.656],[-4.433,41.242],[-4.496,40.864]],"c":true}]}]},"nm":"Контур 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":5,"k":{"a":0,"k":[0,0.553,0.592,0.635,0.139,0.557,0.596,0.637,0.492,0.561,0.6,0.639,0.839,0.551,0.59,0.633,0.999,0.541,0.58,0.627,0,0,0.139,0.5,0.492,1,0.839,0.5,0.999,0]}},"s":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[-22.476,-223.466],"to":[0,0],"ti":[0,0]},{"t":20,"s":[-22.476,-223.466]}]},"e":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"t":0,"s":[48.472,31.505],"to":[0,0],"ti":[0,0]},{"t":20,"s":[48.472,31.505]}]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false}],"ip":0,"op":20,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"NULL_OBJECT","sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0]},"a":{"a":0,"k":[9,0,0]},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":47,"s":[96,96,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":149,"s":[96,96,100]},{"t":179,"s":[100,100,100]}]}},"ao":0,"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 1","parent":1,"sr":1,"ks":{},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0]],"o":[[0,0]],"v":[[750,266]],"c":false}},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.674510002136,0.617175996304,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8.2},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":2,"k":{"a":0,"k":[0,1,1,1,1,0,0,0]}},"s":{"a":0,"k":[0,0]},"e":{"a":0,"k":[100,0]},"t":1,"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"mover1","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.34,"y":1},"o":{"x":0.33,"y":0},"t":0,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.34,"y":1},"o":{"x":0.33,"y":0},"t":28,"s":[-165,19,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.18,"y":1},"o":{"x":0.167,"y":0},"t":139,"s":[-208,-109,0],"to":[0,0,0],"ti":[0,0,0]},{"t":179,"s":[0,0,0]}]},"s":{"a":0,"k":[-100,100,100]}},"ao":0,"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":3,"nm":"masterctrl","parent":4,"sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.33],"y":[0]},"t":0,"s":[45.436]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":47,"s":[-79.417]},{"i":{"x":[0.18],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":139,"s":[-45.691]},{"t":179,"s":[45.436]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":139,"s":[-99,89,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[-99,105,0],"to":[0,0,0],"ti":[0,0,0]},{"t":179,"s":[-99,89,0]}]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.33,0.33,0.33],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.33,0.33,0.33],"y":[0,0,0]},"t":18,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":47,"s":[80,80,100]},{"i":{"x":[0.18,0.18,0.18],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":139,"s":[80,80,100]},{"t":179,"s":[100,100,100]}]}},"ao":0,"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"spinlens2","parent":5,"refId":"comp_0","sr":1,"ks":{"r":{"a":0,"k":-45.436},"p":{"a":0,"k":[6.059,-132.986,0]},"a":{"a":0,"k":[256,256,0]},"s":{"a":0,"k":[105,105,100]}},"ao":0,"w":512,"h":512,"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"paw6","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.18],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":122,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.58],"y":[0]},"t":124,"s":[100]},{"t":143,"s":[0]}]},"r":{"a":0,"k":-9.512},"p":{"a":0,"k":[3.324,-179.817,0]},"a":{"a":0,"k":[-194.676,10.183,0]},"s":{"a":0,"k":[96.65,96.65,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.5,-0.375],[0.125,-4.625],[-3.5,0.75],[1.125,3.5]],"o":[[-3.5,0.375],[-0.125,4.625],[3.5,-0.75],[-0.925,-2.878]],"v":[[-173.25,-5.625],[-177.625,0.75],[-169.625,7.625],[-165.125,0.375]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4,0.25],[0.125,-4.875],[-3.25,0.125],[-0.625,4.25]],"o":[[-4,-0.25],[-0.125,4.875],[3.25,-0.125],[0.625,-4.25]],"v":[[-186.875,-16.625],[-193.25,-9],[-184.875,2.25],[-179.625,-7.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.25,-3.5],[-1.625,-4],[-4,3.625],[2.163,1.822]],"o":[[-3.25,3.5],[1.625,4],[4,-3.625],[-2.375,-2]],"v":[[-222.5,2],[-222.875,12.75],[-213.625,17.125],[-213.25,4]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3,-0.375],[-1.411,-8.289],[-3.625,0.125],[1,7.875]],"o":[[-3,0.375],[1,5.875],[3.625,-0.125],[-1,-7.875]],"v":[[-205.125,-17.875],[-211.375,-6],[-203.625,2.625],[-198.375,-7.25]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.25,1.375],[3,-7.375],[1.75,-4.625],[-6.156,-1.067],[-7.625,1.75],[-3.75,6.75],[5.875,2.75]],"o":[[-4.25,-1.375],[-3,7.375],[-1.75,4.625],[9.375,1.625],[7.625,-1.75],[3.75,-6.75],[-5.875,-2.75]],"v":[[-187.875,5.25],[-204.75,10],[-208.25,24.375],[-203.625,38],[-186.625,31.75],[-169.75,26.5],[-174.125,13.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":47,"op":180,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"paw5","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.18],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":100,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.58],"y":[0]},"t":102,"s":[100]},{"t":140,"s":[0]}]},"r":{"a":0,"k":-48.141},"p":{"a":0,"k":[-42.676,-96.817,0]},"a":{"a":0,"k":[-194.676,10.183,0]},"s":{"a":0,"k":[-100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.5,-0.375],[0.125,-4.625],[-3.5,0.75],[1.125,3.5]],"o":[[-3.5,0.375],[-0.125,4.625],[3.5,-0.75],[-0.925,-2.878]],"v":[[-173.25,-5.625],[-177.625,0.75],[-169.625,7.625],[-165.125,0.375]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4,0.25],[0.125,-4.875],[-3.25,0.125],[-0.625,4.25]],"o":[[-4,-0.25],[-0.125,4.875],[3.25,-0.125],[0.625,-4.25]],"v":[[-186.875,-16.625],[-193.25,-9],[-184.875,2.25],[-179.625,-7.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.25,-3.5],[-1.625,-4],[-4,3.625],[2.163,1.822]],"o":[[-3.25,3.5],[1.625,4],[4,-3.625],[-2.375,-2]],"v":[[-222.5,2],[-222.875,12.75],[-213.625,17.125],[-213.25,4]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3,-0.375],[-1.411,-8.289],[-3.625,0.125],[1,7.875]],"o":[[-3,0.375],[1,5.875],[3.625,-0.125],[-1,-7.875]],"v":[[-205.125,-17.875],[-211.375,-6],[-203.625,2.625],[-198.375,-7.25]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.25,1.375],[3,-7.375],[1.75,-4.625],[-6.156,-1.067],[-7.625,1.75],[-3.75,6.75],[5.875,2.75]],"o":[[-4.25,-1.375],[-3,7.375],[-1.75,4.625],[9.375,1.625],[7.625,-1.75],[3.75,-6.75],[-5.875,-2.75]],"v":[[-187.875,5.25],[-204.75,10],[-208.25,24.375],[-203.625,38],[-186.625,31.75],[-169.75,26.5],[-174.125,13.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":47,"op":180,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"paw4","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.18],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":80,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.58],"y":[0]},"t":82,"s":[100]},{"t":129,"s":[0]}]},"r":{"a":0,"k":-9.512},"p":{"a":0,"k":[58.324,-88.817,0]},"a":{"a":0,"k":[-194.676,10.183,0]},"s":{"a":0,"k":[96.65,96.65,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.5,-0.375],[0.125,-4.625],[-3.5,0.75],[1.125,3.5]],"o":[[-3.5,0.375],[-0.125,4.625],[3.5,-0.75],[-0.925,-2.878]],"v":[[-173.25,-5.625],[-177.625,0.75],[-169.625,7.625],[-165.125,0.375]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4,0.25],[0.125,-4.875],[-3.25,0.125],[-0.625,4.25]],"o":[[-4,-0.25],[-0.125,4.875],[3.25,-0.125],[0.625,-4.25]],"v":[[-186.875,-16.625],[-193.25,-9],[-184.875,2.25],[-179.625,-7.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.25,-3.5],[-1.625,-4],[-4,3.625],[2.163,1.822]],"o":[[-3.25,3.5],[1.625,4],[4,-3.625],[-2.375,-2]],"v":[[-222.5,2],[-222.875,12.75],[-213.625,17.125],[-213.25,4]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3,-0.375],[-1.411,-8.289],[-3.625,0.125],[1,7.875]],"o":[[-3,0.375],[1,5.875],[3.625,-0.125],[-1,-7.875]],"v":[[-205.125,-17.875],[-211.375,-6],[-203.625,2.625],[-198.375,-7.25]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.25,1.375],[3,-7.375],[1.75,-4.625],[-6.156,-1.067],[-7.625,1.75],[-3.75,6.75],[5.875,2.75]],"o":[[-4.25,-1.375],[-3,7.375],[-1.75,4.625],[9.375,1.625],[7.625,-1.75],[3.75,-6.75],[-5.875,-2.75]],"v":[[-187.875,5.25],[-204.75,10],[-208.25,24.375],[-203.625,38],[-186.625,31.75],[-169.75,26.5],[-174.125,13.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":47,"op":180,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"paw3","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.18],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":67,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.58],"y":[0]},"t":69,"s":[100]},{"t":102,"s":[0]}]},"r":{"a":0,"k":-32.039},"p":{"a":0,"k":[22.324,-0.817,0]},"a":{"a":0,"k":[-194.676,10.183,0]},"s":{"a":0,"k":[-100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.5,-0.375],[0.125,-4.625],[-3.5,0.75],[1.125,3.5]],"o":[[-3.5,0.375],[-0.125,4.625],[3.5,-0.75],[-0.925,-2.878]],"v":[[-173.25,-5.625],[-177.625,0.75],[-169.625,7.625],[-165.125,0.375]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4,0.25],[0.125,-4.875],[-3.25,0.125],[-0.625,4.25]],"o":[[-4,-0.25],[-0.125,4.875],[3.25,-0.125],[0.625,-4.25]],"v":[[-186.875,-16.625],[-193.25,-9],[-184.875,2.25],[-179.625,-7.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.25,-3.5],[-1.625,-4],[-4,3.625],[2.163,1.822]],"o":[[-3.25,3.5],[1.625,4],[4,-3.625],[-2.375,-2]],"v":[[-222.5,2],[-222.875,12.75],[-213.625,17.125],[-213.25,4]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3,-0.375],[-1.411,-8.289],[-3.625,0.125],[1,7.875]],"o":[[-3,0.375],[1,5.875],[3.625,-0.125],[-1,-7.875]],"v":[[-205.125,-17.875],[-211.375,-6],[-203.625,2.625],[-198.375,-7.25]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.25,1.375],[3,-7.375],[1.75,-4.625],[-6.156,-1.067],[-7.625,1.75],[-3.75,6.75],[5.875,2.75]],"o":[[-4.25,-1.375],[-3,7.375],[-1.75,4.625],[9.375,1.625],[7.625,-1.75],[3.75,-6.75],[-5.875,-2.75]],"v":[[-187.875,5.25],[-204.75,10],[-208.25,24.375],[-203.625,38],[-186.625,31.75],[-169.75,26.5],[-174.125,13.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":47,"op":180,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"paw1","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.18],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.58],"y":[0]},"t":55,"s":[100]},{"t":80,"s":[0]}]},"r":{"a":0,"k":7.116},"p":{"a":0,"k":[117.324,31.183,0]},"a":{"a":0,"k":[-194.676,10.183,0]},"s":{"a":0,"k":[96.65,96.65,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.5,-0.375],[0.125,-4.625],[-3.5,0.75],[1.125,3.5]],"o":[[-3.5,0.375],[-0.125,4.625],[3.5,-0.75],[-0.925,-2.878]],"v":[[-173.25,-5.625],[-177.625,0.75],[-169.625,7.625],[-165.125,0.375]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4,0.25],[0.125,-4.875],[-3.25,0.125],[-0.625,4.25]],"o":[[-4,-0.25],[-0.125,4.875],[3.25,-0.125],[0.625,-4.25]],"v":[[-186.875,-16.625],[-193.25,-9],[-184.875,2.25],[-179.625,-7.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.25,-3.5],[-1.625,-4],[-4,3.625],[2.163,1.822]],"o":[[-3.25,3.5],[1.625,4],[4,-3.625],[-2.375,-2]],"v":[[-222.5,2],[-222.875,12.75],[-213.625,17.125],[-213.25,4]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3,-0.375],[-1.411,-8.289],[-3.625,0.125],[1,7.875]],"o":[[-3,0.375],[1,5.875],[3.625,-0.125],[-1,-7.875]],"v":[[-205.125,-17.875],[-211.375,-6],[-203.625,2.625],[-198.375,-7.25]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.25,1.375],[3,-7.375],[1.75,-4.625],[-6.156,-1.067],[-7.625,1.75],[-3.75,6.75],[5.875,2.75]],"o":[[-4.25,-1.375],[-3,7.375],[-1.75,4.625],[9.375,1.625],[7.625,-1.75],[3.75,-6.75],[-5.875,-2.75]],"v":[[-187.875,5.25],[-204.75,10],[-208.25,24.375],[-203.625,38],[-186.625,31.75],[-169.75,26.5],[-174.125,13.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":47,"op":180,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"paw2","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.18],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.58],"y":[0]},"t":42,"s":[100]},{"t":69,"s":[0]}]},"r":{"a":0,"k":-32.039},"p":{"a":0,"k":[75.324,109.183,0]},"a":{"a":0,"k":[-194.676,10.183,0]},"s":{"a":0,"k":[-100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.5,-0.375],[0.125,-4.625],[-3.5,0.75],[1.125,3.5]],"o":[[-3.5,0.375],[-0.125,4.625],[3.5,-0.75],[-0.925,-2.878]],"v":[[-173.25,-5.625],[-177.625,0.75],[-169.625,7.625],[-165.125,0.375]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4,0.25],[0.125,-4.875],[-3.25,0.125],[-0.625,4.25]],"o":[[-4,-0.25],[-0.125,4.875],[3.25,-0.125],[0.625,-4.25]],"v":[[-186.875,-16.625],[-193.25,-9],[-184.875,2.25],[-179.625,-7.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.25,-3.5],[-1.625,-4],[-4,3.625],[2.163,1.822]],"o":[[-3.25,3.5],[1.625,4],[4,-3.625],[-2.375,-2]],"v":[[-222.5,2],[-222.875,12.75],[-213.625,17.125],[-213.25,4]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3,-0.375],[-1.411,-8.289],[-3.625,0.125],[1,7.875]],"o":[[-3,0.375],[1,5.875],[3.625,-0.125],[-1,-7.875]],"v":[[-205.125,-17.875],[-211.375,-6],[-203.625,2.625],[-198.375,-7.25]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.25,1.375],[3,-7.375],[1.75,-4.625],[-6.156,-1.067],[-7.625,1.75],[-3.75,6.75],[5.875,2.75]],"o":[[-4.25,-1.375],[-3,7.375],[-1.75,4.625],[9.375,1.625],[7.625,-1.75],[3.75,-6.75],[-5.875,-2.75]],"v":[[-187.875,5.25],[-204.75,10],[-208.25,24.375],[-203.625,38],[-186.625,31.75],[-169.75,26.5],[-174.125,13.125]],"c":true}},"nm":"Контур 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509817362,0.274509817362,0.274509817362,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":40,"op":180,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"shadde","parent":5,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":57,"s":[25]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":122,"s":[25]},{"t":143,"s":[0]}]},"r":{"a":0,"k":74.079},"p":{"a":1,"k":[{"i":{"x":0.18,"y":1},"o":{"x":0.33,"y":0},"t":21,"s":[-7.271,-190.721,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.965},"o":{"x":0.33,"y":0},"t":48,"s":[-26.46,-199.272,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.126},"t":91,"s":[-24.339,-189.499,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.18,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[-15.816,-182.05,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[12.184,-196.229,0]}]},"a":{"a":0,"k":[-107,68,0]},"s":{"a":0,"k":[125,125,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0]],"o":[[0,0]],"v":[[-412.477,611.481]],"c":false}},"nm":"Контур 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.674510002136,0.617175996304,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8.2},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[57.343,13.107],[19,-51],[-85.5,-22.5],[-7.375,9.25],[0,0],[-4.062,-5.75],[-28,-8],[0,0],[30.5,9.5],[9.5,2],[3.25,-1.75],[0,8.25]],"o":[[-70,-16],[-18.582,49.877],[76.469,20.124],[5.051,-6.335],[0,0],[7.617,10.781],[28,8],[0,0],[-11.706,-3.646],[-9.14,-1.924],[-4.457,2.4],[0,-41]],"v":[[-73,-50],[-213,23],[-133.5,178.5],[-5.125,129.25],[6.75,126.937],[11.5,135],[116.5,168],[151.5,137],[133.25,90],[42.5,65],[25,68],[14,56]],"c":true}},"nm":"Контур 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":0,"k":{"i":[[-42.5,-13],[15,-57],[45,11],[-15,49.5]],"o":[[40.132,12.276],[-13.858,52.661],[-58.826,-14.38],[15,-49.5]],"v":[[-77,-27.5],[-10.5,85.5],[-126.5,155.5],[-192.5,34.5]],"c":true}},"nm":"Контур 2","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Shape 1","bm":0,"hd":false}],"ip":21,"op":180,"st":0,"bm":0}]} \ No newline at end of file diff --git a/Rosetta/RosettaApp.swift b/Rosetta/RosettaApp.swift index d96bc2d..0a7397e 100644 --- a/Rosetta/RosettaApp.swift +++ b/Rosetta/RosettaApp.swift @@ -17,6 +17,14 @@ struct RosettaApp: App { init() { UIWindow.appearance().backgroundColor = .systemBackground + + // Detect fresh install: UserDefaults are wiped on uninstall, Keychain is not. + // If this is the first launch after install, clear any stale Keychain data. + if !UserDefaults.standard.bool(forKey: "hasLaunchedBefore") { + try? AccountManager.shared.deleteAccount() + UserDefaults.standard.set(true, forKey: "hasLaunchedBefore") + } + // Preload Lottie animations early Task.detached(priority: .userInitiated) { LottieAnimationCache.shared.preload(OnboardingPages.all.map(\.animationName)) @@ -25,6 +33,7 @@ struct RosettaApp: App { @AppStorage("hasCompletedOnboarding") private var hasCompletedOnboarding = false @AppStorage("isLoggedIn") private var isLoggedIn = false + @AppStorage("hasLaunchedBefore") private var hasLaunchedBefore = false @State private var appState: AppState = .splash var body: some Scene { @@ -35,6 +44,7 @@ struct RosettaApp: App { rootView } + .preferredColorScheme(.dark) } } @@ -57,21 +67,37 @@ struct RosettaApp: App { } case .auth: - AuthCoordinator { - withAnimation(.easeInOut(duration: 0.4)) { - isLoggedIn = true - // Start session automatically with the password from auth flow - appState = .main - } - } + AuthCoordinator( + onAuthComplete: { + withAnimation(.easeInOut(duration: 0.4)) { + isLoggedIn = true + appState = .main + } + }, + onBackToUnlock: AccountManager.shared.hasAccount ? { + // Go back to unlock screen if an account exists + withAnimation(.easeInOut(duration: 0.4)) { + appState = .unlock + } + } : nil + ) case .unlock: - UnlockView { - withAnimation(.easeInOut(duration: 0.4)) { - isLoggedIn = true - appState = .main + UnlockView( + onUnlocked: { + withAnimation(.easeInOut(duration: 0.4)) { + isLoggedIn = true + appState = .main + } + }, + onCreateNewAccount: { + // Go to auth flow (Welcome screen with back button) + // Does NOT delete the old account — Android keeps multiple accounts + withAnimation(.easeInOut(duration: 0.4)) { + appState = .auth + } } - } + ) case .main: MainTabView(onLogout: { @@ -84,12 +110,12 @@ struct RosettaApp: App { } private func determineNextState() { - if AccountManager.shared.hasAccount { + if !hasCompletedOnboarding { + // New install or fresh user — show onboarding first + appState = .onboarding + } else if AccountManager.shared.hasAccount { // Existing user — unlock with password appState = .unlock - } else if !hasCompletedOnboarding { - // New user — show onboarding first - appState = .onboarding } else { // Onboarding done but no account — go to auth appState = .auth