refactor(mobile): Remove i18n, expand core screens, update plan

BREAKING: Removed multi-language support (i18n) - will be re-added later

Changes:
- Removed i18n system (6 language files, LanguageContext)
- Expanded WalletScreen, SettingsScreen, SwapScreen with more features
- Added KurdistanSun component, HEZ/PEZ token icons
- Added EditProfileScreen, WalletSetupScreen
- Added button e2e tests (Profile, Settings, Wallet)
- Updated plan: honest assessment - 42 nav buttons with mock data
- Fixed terminology: Polkadot→Pezkuwi, Substrate→Bizinikiwi

Reality check: UI complete with mock data, converting to production one-by-one
This commit is contained in:
2026-01-15 05:08:21 +03:00
parent 5d293cc954
commit f2e70a8150
110 changed files with 11157 additions and 3260 deletions
+5 -50
View File
@@ -1,70 +1,25 @@
import React, { useEffect, useState } from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import { initializeI18n } from './src/i18n';
import { ErrorBoundary } from './src/components/ErrorBoundary';
import { LanguageProvider } from './src/contexts/LanguageContext';
import { AuthProvider } from './src/contexts/AuthContext';
import { PezkuwiProvider } from './src/contexts/PezkuwiContext';
import { BiometricAuthProvider } from './src/contexts/BiometricAuthContext';
import { ThemeProvider } from './src/contexts/ThemeContext';
import AppNavigator from './src/navigation/AppNavigator';
import { KurdistanColors } from './src/theme/colors';
export default function App() {
const [isI18nInitialized, setIsI18nInitialized] = useState(false);
useEffect(() => {
// Initialize i18n on app start
const initApp = async () => {
try {
console.log('🚀 App starting...');
console.log('🔧 Initializing i18n...');
await initializeI18n();
console.log('✅ i18n initialized');
setIsI18nInitialized(true);
} catch (error) {
console.error('❌ Failed to initialize i18n:', error);
// Fallback: Still show app but with default language
setIsI18nInitialized(true);
}
};
initApp();
}, []);
if (!isI18nInitialized) {
return (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={KurdistanColors.kesk} />
</View>
);
}
return (
<ErrorBoundary>
<ThemeProvider>
<AuthProvider>
<PezkuwiProvider>
<LanguageProvider>
<BiometricAuthProvider>
<StatusBar style="auto" />
<AppNavigator />
</BiometricAuthProvider>
</LanguageProvider>
<BiometricAuthProvider>
<StatusBar style="auto" />
<AppNavigator />
</BiometricAuthProvider>
</PezkuwiProvider>
</AuthProvider>
</ThemeProvider>
</ErrorBoundary>
);
}
const styles = StyleSheet.create({
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: KurdistanColors.spi,
},
});
-408
View File
@@ -1,408 +0,0 @@
# ✅ PHASE 1 COMPLETE - Settings Screen Full Implementation
**Date:** 2026-01-14
**Duration:** ~3 hours
**Status:** COMPLETE
---
## Objective
Make ALL features in Settings screen fully functional - no "Coming Soon" alerts.
---
## Changes Made
### 1. Dark Mode ✅
**Files:**
- `/home/mamostehp/pwap/shared/theme/colors.ts` - Added LightColors & DarkColors
- `/home/mamostehp/pwap/mobile/src/contexts/ThemeContext.tsx` - Added colors export
- `/home/mamostehp/pwap/mobile/src/screens/SettingsScreen.tsx` - Connected theme
**Features:**
- Toggle switches between light/dark theme
- Theme persists in AsyncStorage (`@pezkuwi/theme`)
- All screens use dynamic colors from `useTheme().colors`
- StatusBar adapts to theme (light-content / dark-content)
**Colors:**
```typescript
LightColors: {
background: '#F5F5F5',
surface: '#FFFFFF',
text: '#000000',
textSecondary: '#666666',
border: '#E0E0E0',
}
DarkColors: {
background: '#121212',
surface: '#1E1E1E',
text: '#FFFFFF',
textSecondary: '#B0B0B0',
border: '#333333',
}
```
---
### 2. Font Size ✅
**Files:**
- `/home/mamostehp/pwap/mobile/src/contexts/ThemeContext.tsx` - Added fontSize state
**Features:**
- 3 sizes: Small (87.5%), Medium (100%), Large (112.5%)
- Persists in AsyncStorage (`@pezkuwi/font_size`)
- Exposes `fontScale` multiplier for responsive text
- Alert dialog for selection
**Usage:**
```typescript
const { fontSize, setFontSize, fontScale } = useTheme();
// fontScale: 0.875 | 1 | 1.125
```
---
### 3. Biometric Authentication ✅
**Files:**
- `/home/mamostehp/pwap/mobile/src/screens/SettingsScreen.tsx` - Connected BiometricAuthContext
**Features:**
- Fingerprint / Face ID support via `expo-local-authentication`
- Checks hardware availability
- Verifies enrollment before enabling
- Displays biometric type in subtitle (fingerprint/facial/iris)
- Full context already existed in BiometricAuthContext.tsx
**Flow:**
1. User toggles ON → Check if biometric available → Prompt for authentication
2. If success → Save to AsyncStorage → Show "Enabled (fingerprint)"
3. User toggles OFF → Disable → Show "Disabled"
---
### 4. Change Password ✅
**Files:**
- `/home/mamostehp/pwap/mobile/src/contexts/AuthContext.tsx` - Updated changePassword signature
- `/home/mamostehp/pwap/mobile/src/components/ChangePasswordModal.tsx` - NEW
**Features:**
- **Current Password verification** - Re-authenticates with Supabase before changing
- **New Password** - Minimum 6 characters
- **Confirm Password** - Must match new password
- **Forgot Password link** - Sends reset email via Supabase
- Full validation with error messages
**Implementation:**
```typescript
// AuthContext
changePassword(newPassword, currentPassword) {
// 1. Verify current password by sign in
// 2. If correct, update to new password
// 3. Return error or success
}
resetPassword(email) {
// Send password reset email
}
```
---
### 5. Email Notifications ✅
**Files:**
- `/home/mamostehp/pwap/mobile/src/components/EmailNotificationsModal.tsx` - NEW
**Features:**
- 4 categories with toggle switches:
- 💸 Transaction Updates
- 🗳️ Governance Alerts
- 🔒 Security Alerts
- 📢 Marketing & Updates
- Persists preferences in AsyncStorage (`@pezkuwi/email_notifications`)
- Professional modal design with save/cancel
---
### 6. Push Notifications ✅
**Features:**
- Toggle switch (state only, no actual push setup yet)
- Ready for expo-notifications integration
---
### 7. Terms & Privacy ✅
**Files:**
- `/home/mamostehp/pwap/mobile/src/components/TermsOfServiceModal.tsx` - EXISTING
- `/home/mamostehp/pwap/mobile/src/components/PrivacyPolicyModal.tsx` - EXISTING
**Features:**
- Both modals already existed from Phase 0
- Connected to Settings buttons
- Full legal text with Accept button
---
### 8. About & Help ✅
**Features:**
- **About** - Shows app name + version 1.0.0
- **Help** - Shows support email: support@pezkuwichain.io
- Simple Alert dialogs
---
### 9. Removed Features
**Two-Factor Auth** - Removed (too complex for current scope)
---
## Code Quality Improvements
### Fixed Deprecation Warnings
**Issue:** `shadow*" style props are deprecated. Use "boxShadow"`
**Fix:**
```typescript
// BEFORE
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.05,
shadowRadius: 4,
// AFTER
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.05)',
```
**Files Fixed:**
- SettingsScreen.tsx
### Fixed React Native Web Compatibility
**Issue:** Alert.alert() with button arrays doesn't work properly on React Native Web
**Fix:**
- Created FontSizeModal.tsx to replace Alert-based font size selector
- Simplified biometric toggle to avoid button arrays
- Now all interactive elements use proper modals or simple alerts
**Files Fixed:**
- SettingsScreen.tsx - Replaced Alert.alert() with modal
- FontSizeModal.tsx - NEW professional font size selector
### Fixed TypeScript Errors
**Issue:** TermsOfServiceModal and PrivacyPolicyModal don't accept `onAccept` prop
**Fix:**
- Removed `onAccept` prop from modal calls in SettingsScreen
- Modals now only use `visible` and `onClose` props
**Files Fixed:**
- SettingsScreen.tsx
---
## Files Created
1. `/home/mamostehp/pwap/mobile/src/components/EmailNotificationsModal.tsx` - 350 lines
2. `/home/mamostehp/pwap/mobile/src/components/ChangePasswordModal.tsx` - 350 lines
3. `/home/mamostehp/pwap/mobile/src/components/FontSizeModal.tsx` - 200 lines
**Total:** 3 new files, 900 lines of code
---
## Files Modified
1. `/home/mamostehp/pwap/shared/theme/colors.ts` - Added DarkColors
2. `/home/mamostehp/pwap/mobile/src/contexts/ThemeContext.tsx` - Added fontSize + colors
3. `/home/mamostehp/pwap/mobile/src/contexts/AuthContext.tsx` - Added changePassword + resetPassword
4. `/home/mamostehp/pwap/mobile/src/screens/SettingsScreen.tsx` - Connected all features
5. `/home/mamostehp/pwap/mobile/App.tsx` - Added ThemeProvider
**Total:** 5 files modified
---
## Settings Screen - Complete Feature List
### APPEARANCE ✅
- **Dark Mode** - Light/Dark theme toggle
- **Font Size** - Small/Medium/Large selection
### SECURITY ✅
- **Biometric Auth** - Fingerprint/Face ID
- **Change Password** - With current password verification
### NOTIFICATIONS ✅
- **Push Notifications** - Toggle (ready for implementation)
- **Email Notifications** - 4 category preferences
### ABOUT ✅
- **About** - App version info
- **Terms of Service** - Full legal text modal
- **Privacy Policy** - Full privacy text modal
- **Help & Support** - Support email
---
## User Experience
### Before Phase 1:
❌ Dark Mode - Alert "Coming Soon"
❌ Font Size - Alert with no persistence
❌ Biometric Auth - Partial implementation
❌ Change Password - Alert.prompt (doesn't work on Android)
❌ Email Notifications - Alert "Coming Soon"
❌ Two-Factor Auth - Alert "Coming Soon"
### After Phase 1:
✅ Dark Mode - Fully functional, theme changes entire app
✅ Font Size - 3 sizes, persists, ready for implementation
✅ Biometric Auth - Fully functional with device hardware
✅ Change Password - Professional modal with current password verification
✅ Email Notifications - 4-category modal with persistence
✅ Push Notifications - Toggle ready
✅ Terms/Privacy - Full modals
✅ About/Help - Info displayed
---
## Technical Architecture
### State Management
**ThemeContext:**
```typescript
{
isDarkMode: boolean,
toggleDarkMode: () => Promise<void>,
colors: LightColors | DarkColors,
fontSize: 'small' | 'medium' | 'large',
setFontSize: (size) => Promise<void>,
fontScale: 0.875 | 1 | 1.125,
}
```
**BiometricAuthContext:**
```typescript
{
isBiometricSupported: boolean,
isBiometricEnrolled: boolean,
isBiometricAvailable: boolean,
biometricType: 'fingerprint' | 'facial' | 'iris' | 'none',
isBiometricEnabled: boolean,
authenticate: () => Promise<boolean>,
enableBiometric: () => Promise<boolean>,
disableBiometric: () => Promise<void>,
}
```
**AuthContext:**
```typescript
{
user: User | null,
changePassword: (newPassword, currentPassword) => Promise<{error}>,
resetPassword: (email) => Promise<{error}>,
}
```
### AsyncStorage Keys
- `@pezkuwi/theme` - 'light' | 'dark'
- `@pezkuwi/font_size` - 'small' | 'medium' | 'large'
- `@biometric_enabled` - 'true' | 'false'
- `@pezkuwi/email_notifications` - JSON preferences object
---
## Testing Checklist
### Manual Testing:
1. **Dark Mode:**
- [ ] Toggle ON → Theme changes to dark
- [ ] Restart app → Theme persists
- [ ] Toggle OFF → Theme changes to light
2. **Font Size:**
- [ ] Select Small → Text shrinks
- [ ] Select Large → Text grows
- [ ] Restart app → Font size persists
3. **Biometric Auth:**
- [ ] Toggle ON → Fingerprint prompt appears
- [ ] Authenticate → Enabled
- [ ] Toggle OFF → Disabled
4. **Change Password:**
- [ ] Open modal → 3 inputs visible
- [ ] Enter wrong current password → Error
- [ ] Passwords don't match → Error
- [ ] Valid inputs → Success
- [ ] Click "Forgot Password" → Email sent
5. **Email Notifications:**
- [ ] Open modal → 4 categories visible
- [ ] Toggle switches → State updates
- [ ] Click Save → Preferences persist
- [ ] Reopen modal → Toggles show saved state
6. **Terms/Privacy:**
- [ ] Click Terms → Modal opens with full text
- [ ] Click Privacy → Modal opens with full text
7. **About/Help:**
- [ ] Click About → Shows version 1.0.0
- [ ] Click Help → Shows support email
---
## Success Criteria: MET ✅
- ✅ All Settings features functional
- ✅ No "Coming Soon" alerts
- ✅ Theme system implemented
- ✅ Font size system ready
- ✅ Biometric auth working
- ✅ Password change with verification
- ✅ Email preferences modal
- ✅ Terms/Privacy accessible
- ✅ Code quality (no deprecated props)
---
## Next Steps
**Phase 2:** Finance Features
- Wallet screen implementation
- Transfer/Receive modals
- Transaction history
- Token management
**Ready to proceed with Phase 2!**
---
## Summary
**Phase 1 delivered a FULLY FUNCTIONAL Settings screen.** Every button works, every toggle persists, every modal is professional. No placeholders, no "Coming Soon" alerts.
**Lines of Code Added:** ~700 lines
**Files Created:** 2 modals
**Files Modified:** 5 core files
**Features Delivered:** 10 complete features
**Phase 1: COMPLETE** 🎉
-50
View File
@@ -194,29 +194,6 @@ jest.mock('../shared/lib/p2p-fiat', () => ({
acceptOffer: jest.fn(() => Promise.resolve(true)),
}));
// Mock shared i18n module
jest.mock('../shared/i18n', () => ({
translations: {
en: { welcome: 'Welcome' },
tr: { welcome: 'Hoş geldiniz' },
kmr: { welcome: 'Bi xêr hatî' },
ckb: { welcome: 'بەخێربێن' },
ar: { welcome: 'مرحبا' },
fa: { welcome: 'خوش آمدید' },
},
LANGUAGES: [
{ code: 'en', name: 'English', nativeName: 'English', rtl: false },
{ code: 'tr', name: 'Turkish', nativeName: 'Türkçe', rtl: false },
{ code: 'kmr', name: 'Kurdish Kurmanji', nativeName: 'Kurmancî', rtl: false },
{ code: 'ckb', name: 'Kurdish Sorani', nativeName: 'سۆرانی', rtl: true },
{ code: 'ar', name: 'Arabic', nativeName: 'العربية', rtl: true },
{ code: 'fa', name: 'Persian', nativeName: 'فارسی', rtl: true },
],
DEFAULT_LANGUAGE: 'en',
LANGUAGE_STORAGE_KEY: '@language',
isRTL: jest.fn((code) => ['ckb', 'ar', 'fa'].includes(code)),
}));
// Mock shared wallet utilities (handles import.meta)
jest.mock('../shared/lib/wallet', () => ({
formatBalance: jest.fn((amount, decimals) => '0.00'),
@@ -241,33 +218,6 @@ jest.mock('../shared/lib/citizenship-workflow', () => ({
createCitizenshipRequest: jest.fn(() => Promise.resolve({ id: '123' })),
}));
// Mock react-i18next for i18n initialization
jest.mock('react-i18next', () => ({
...jest.requireActual('react-i18next'),
useTranslation: () => ({
t: (key) => key,
i18n: {
language: 'en',
changeLanguage: jest.fn(() => Promise.resolve()),
isInitialized: true,
},
}),
initReactI18next: {
type: '3rdParty',
init: jest.fn(),
},
}));
// Mock i18next
jest.mock('i18next', () => ({
...jest.requireActual('i18next'),
init: jest.fn(() => Promise.resolve()),
changeLanguage: jest.fn(() => Promise.resolve()),
use: jest.fn(function () { return this; }),
language: 'en',
isInitialized: true,
}));
// Note: Alert is mocked in individual test files where needed
// Silence console warnings in tests
+31
View File
@@ -0,0 +1,31 @@
/**
* Reset Wallet Script
*
* Clears all wallet data from AsyncStorage for testing purposes.
* Run with: node scripts/reset-wallet.js
*
* Note: This only works in development. For the actual app,
* you need to clear the app data or use the in-app reset.
*/
console.log('='.repeat(50));
console.log('WALLET RESET INSTRUCTIONS');
console.log('='.repeat(50));
console.log('');
console.log('To reset wallet data in the app, do ONE of these:');
console.log('');
console.log('1. Clear App Data (Easiest):');
console.log(' - iOS Simulator: Device > Erase All Content and Settings');
console.log(' - Android: Settings > Apps > Pezkuwi > Clear Data');
console.log(' - Expo Go: Shake device > Clear AsyncStorage');
console.log('');
console.log('2. In Expo Go, run this in the console:');
console.log(' AsyncStorage.multiRemove([');
console.log(' "@pezkuwi_wallets",');
console.log(' "@pezkuwi_selected_account",');
console.log(' "@pezkuwi_selected_network"');
console.log(' ])');
console.log('');
console.log('3. Add temp reset button (already added to Settings)');
console.log('');
console.log('='.repeat(50));
@@ -22,7 +22,7 @@ const mockUser: User = {
created_at: new Date().toISOString(),
};
const mockAuthContext: AuthContextType = {
export const mockAuthContext: AuthContextType = {
user: mockUser,
session: null,
loading: false,
@@ -7,20 +7,36 @@ interface BiometricAuthContextType {
isBiometricAvailable: boolean;
biometricType: 'fingerprint' | 'facial' | 'iris' | 'none';
isBiometricEnabled: boolean;
isLocked: boolean;
autoLockTimer: number;
authenticate: () => Promise<boolean>;
enableBiometric: () => Promise<boolean>;
disableBiometric: () => Promise<void>;
setPinCode: (pin: string) => Promise<void>;
verifyPinCode: (pin: string) => Promise<boolean>;
setAutoLockTimer: (minutes: number) => Promise<void>;
lock: () => void;
unlock: () => void;
checkAutoLock: () => Promise<void>;
}
const mockBiometricContext: BiometricAuthContextType = {
export const mockBiometricContext: BiometricAuthContextType = {
isBiometricSupported: true,
isBiometricEnrolled: true,
isBiometricAvailable: true,
biometricType: 'fingerprint',
isBiometricEnabled: false,
isLocked: false,
autoLockTimer: 5,
authenticate: jest.fn().mockResolvedValue(true),
enableBiometric: jest.fn().mockResolvedValue(true),
disableBiometric: jest.fn().mockResolvedValue(undefined),
setPinCode: jest.fn().mockResolvedValue(undefined),
verifyPinCode: jest.fn().mockResolvedValue(true),
setAutoLockTimer: jest.fn().mockResolvedValue(undefined),
lock: jest.fn(),
unlock: jest.fn(),
checkAutoLock: jest.fn().mockResolvedValue(undefined),
};
const BiometricAuthContext = createContext<BiometricAuthContextType>(mockBiometricContext);
@@ -19,7 +19,7 @@ interface ThemeContextType {
fontScale: number;
}
const mockThemeContext: ThemeContextType = {
export const mockThemeContext: ThemeContextType = {
isDarkMode: false,
toggleDarkMode: jest.fn().mockResolvedValue(undefined),
colors: LightColors,
@@ -0,0 +1,634 @@
/**
* ProfileButton E2E Tests
*
* Tests the Profile button in BottomTabNavigator and all features
* within ProfileScreen and EditProfileScreen.
*
* Test Coverage:
* - Profile screen rendering and loading state
* - Profile data display (name, email, avatar)
* - Avatar picker modal
* - Edit Profile navigation
* - About Pezkuwi alert
* - Logout flow
* - Referrals navigation
* - EditProfileScreen rendering
* - EditProfileScreen form interactions
* - EditProfileScreen save/cancel flows
*/
import React from 'react';
import { render, fireEvent, waitFor, act } from '@testing-library/react-native';
import { Alert } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Mock contexts
jest.mock('../../contexts/ThemeContext', () => require('../../__mocks__/contexts/ThemeContext'));
jest.mock('../../contexts/AuthContext', () => require('../../__mocks__/contexts/AuthContext'));
jest.mock('../../contexts/PezkuwiContext', () => ({
usePezkuwi: () => ({
endpoint: 'wss://rpc.pezkuwichain.io:9944',
setEndpoint: jest.fn(),
api: null,
isApiReady: false,
selectedAccount: null,
}),
}));
// Mock navigation - extended from jest.setup.cjs
const mockNavigate = jest.fn();
const mockGoBack = jest.fn();
jest.mock('@react-navigation/native', () => {
const actualNav = jest.requireActual('@react-navigation/native');
const ReactModule = require('react');
return {
...actualNav,
useNavigation: () => ({
navigate: mockNavigate,
goBack: mockGoBack,
setOptions: jest.fn(),
addListener: jest.fn(),
removeListener: jest.fn(),
}),
useFocusEffect: (callback: () => (() => void) | void) => {
// Use useEffect to properly handle the callback lifecycle
ReactModule.useEffect(() => {
const unsubscribe = callback();
return unsubscribe;
}, [callback]);
},
};
});
// Mock Alert
const mockAlert = jest.spyOn(Alert, 'alert');
// Mock Supabase with profile data
const mockSupabaseFrom = jest.fn();
const mockProfileData = {
id: 'test-user-id',
full_name: 'Test User',
avatar_url: 'avatar5',
wallet_address: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
created_at: '2026-01-01T00:00:00.000Z',
referral_code: 'TESTCODE',
referral_count: 5,
};
jest.mock('../../lib/supabase', () => ({
supabase: {
from: (table: string) => {
mockSupabaseFrom(table);
return {
select: jest.fn().mockReturnThis(),
update: jest.fn().mockReturnThis(),
eq: jest.fn().mockReturnThis(),
single: jest.fn().mockResolvedValue({
data: mockProfileData,
error: null,
}),
};
},
storage: {
from: jest.fn().mockReturnValue({
upload: jest.fn().mockResolvedValue({ data: { path: 'test.jpg' }, error: null }),
getPublicUrl: jest.fn().mockReturnValue({ data: { publicUrl: 'https://test.com/avatar.jpg' } }),
}),
},
},
}));
import ProfileScreen from '../../screens/ProfileScreen';
import EditProfileScreen from '../../screens/EditProfileScreen';
import { MockThemeProvider, mockThemeContext } from '../../__mocks__/contexts/ThemeContext';
import { MockAuthProvider, mockAuthContext } from '../../__mocks__/contexts/AuthContext';
// ============================================================
// TEST HELPERS
// ============================================================
const renderProfileScreen = (overrides: {
theme?: Partial<typeof mockThemeContext>;
auth?: Partial<typeof mockAuthContext>;
} = {}) => {
return render(
<MockAuthProvider value={overrides.auth}>
<MockThemeProvider value={overrides.theme}>
<ProfileScreen />
</MockThemeProvider>
</MockAuthProvider>
);
};
const renderEditProfileScreen = (overrides: {
theme?: Partial<typeof mockThemeContext>;
auth?: Partial<typeof mockAuthContext>;
} = {}) => {
return render(
<MockAuthProvider value={overrides.auth}>
<MockThemeProvider value={overrides.theme}>
<EditProfileScreen />
</MockThemeProvider>
</MockAuthProvider>
);
};
// ============================================================
// TESTS
// ============================================================
describe('ProfileButton E2E Tests', () => {
beforeEach(async () => {
jest.clearAllMocks();
await AsyncStorage.clear();
mockAlert.mockClear();
mockNavigate.mockClear();
mockGoBack.mockClear();
});
// ----------------------------------------------------------
// 1. PROFILE SCREEN RENDERING TESTS
// ----------------------------------------------------------
describe('1. ProfileScreen Rendering', () => {
it('renders Profile screen with main container', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-screen')).toBeTruthy();
});
});
it('renders header gradient section', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-header-gradient')).toBeTruthy();
});
});
it('renders profile cards container', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-cards-container')).toBeTruthy();
});
});
it('renders scroll view', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-scroll-view')).toBeTruthy();
});
});
it('renders footer with version info', async () => {
const { getByTestId, getByText } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-footer')).toBeTruthy();
expect(getByText('Version 1.0.0')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 2. PROFILE DATA DISPLAY TESTS
// ----------------------------------------------------------
describe('2. Profile Data Display', () => {
it('displays user name from profile data', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
const nameElement = getByTestId('profile-name');
expect(nameElement).toBeTruthy();
});
});
it('displays user email', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
const emailElement = getByTestId('profile-email');
expect(emailElement).toBeTruthy();
});
});
it('displays email card', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-card-email')).toBeTruthy();
});
});
it('displays member since card', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-card-member-since')).toBeTruthy();
});
});
it('displays referrals card with count', async () => {
const { getByTestId, getByText } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-card-referrals')).toBeTruthy();
expect(getByText('5 people')).toBeTruthy();
});
});
it('displays referral code when available', async () => {
const { getByTestId, getByText } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-card-referral-code')).toBeTruthy();
expect(getByText('TESTCODE')).toBeTruthy();
});
});
it('displays wallet address when available', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-card-wallet')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 3. AVATAR TESTS
// ----------------------------------------------------------
describe('3. Avatar Display and Interaction', () => {
it('renders avatar button', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-avatar-button')).toBeTruthy();
});
});
it('displays emoji avatar when avatar_url is emoji ID', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
// avatar5 = 👩🏻
expect(getByTestId('profile-avatar-emoji-container')).toBeTruthy();
});
});
it('opens avatar picker modal when avatar button is pressed', async () => {
const { getByTestId, getByText } = renderProfileScreen();
await waitFor(() => {
const avatarButton = getByTestId('profile-avatar-button');
fireEvent.press(avatarButton);
});
await waitFor(() => {
// AvatarPickerModal displays "Choose Your Avatar" as title
expect(getByText('Choose Your Avatar')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 4. ACTION BUTTONS TESTS
// ----------------------------------------------------------
describe('4. Action Buttons', () => {
it('renders Edit Profile button', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-edit-button')).toBeTruthy();
});
});
it('renders About Pezkuwi button', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-about-button')).toBeTruthy();
});
});
it('navigates to EditProfile when Edit Profile button is pressed', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
const editButton = getByTestId('profile-edit-button');
fireEvent.press(editButton);
});
expect(mockNavigate).toHaveBeenCalledWith('EditProfile');
});
it('shows About Pezkuwi alert when button is pressed', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
const aboutButton = getByTestId('profile-about-button');
fireEvent.press(aboutButton);
});
await waitFor(() => {
expect(mockAlert).toHaveBeenCalledWith(
'About Pezkuwi',
expect.stringContaining('Pezkuwi is a decentralized blockchain platform'),
expect.any(Array)
);
});
});
});
// ----------------------------------------------------------
// 5. REFERRALS NAVIGATION TEST
// ----------------------------------------------------------
describe('5. Referrals Navigation', () => {
it('navigates to Referral screen when referrals card is pressed', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
const referralsCard = getByTestId('profile-card-referrals');
fireEvent.press(referralsCard);
});
expect(mockNavigate).toHaveBeenCalledWith('Referral');
});
});
// ----------------------------------------------------------
// 6. LOGOUT TESTS
// ----------------------------------------------------------
describe('6. Logout Flow', () => {
it('renders logout button', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-logout-button')).toBeTruthy();
});
});
it('shows confirmation alert when logout button is pressed', async () => {
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
const logoutButton = getByTestId('profile-logout-button');
fireEvent.press(logoutButton);
});
await waitFor(() => {
expect(mockAlert).toHaveBeenCalledWith(
'Logout',
'Are you sure you want to logout?',
expect.arrayContaining([
expect.objectContaining({ text: 'Cancel' }),
expect.objectContaining({ text: 'Logout', style: 'destructive' }),
])
);
});
});
it('calls signOut when logout is confirmed', async () => {
const mockSignOut = jest.fn();
const { getByTestId } = renderProfileScreen({
auth: { signOut: mockSignOut },
});
await waitFor(() => {
const logoutButton = getByTestId('profile-logout-button');
fireEvent.press(logoutButton);
});
await waitFor(() => {
// Get the alert call arguments
const alertCall = mockAlert.mock.calls[0];
const buttons = alertCall[2];
const logoutAction = buttons.find((b: any) => b.text === 'Logout');
// Simulate pressing Logout
if (logoutAction?.onPress) {
logoutAction.onPress();
}
});
await waitFor(() => {
expect(mockSignOut).toHaveBeenCalled();
});
});
});
// ----------------------------------------------------------
// 7. DARK MODE SUPPORT TESTS
// ----------------------------------------------------------
describe('7. Dark Mode Support', () => {
it('applies dark mode colors when enabled', async () => {
const darkColors = {
background: '#1A1A1A',
surface: '#2A2A2A',
text: '#FFFFFF',
textSecondary: '#CCCCCC',
border: '#404040',
};
const { getByTestId } = renderProfileScreen({
theme: { isDarkMode: true, colors: darkColors },
});
await waitFor(() => {
expect(getByTestId('profile-screen')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 8. EDIT PROFILE SCREEN RENDERING
// ----------------------------------------------------------
describe('8. EditProfileScreen Rendering', () => {
it('renders EditProfile screen with main container', async () => {
const { getByTestId } = renderEditProfileScreen();
await waitFor(() => {
expect(getByTestId('edit-profile-screen')).toBeTruthy();
});
});
it('renders header with Cancel and Save buttons', async () => {
const { getByTestId, getByText } = renderEditProfileScreen();
await waitFor(() => {
expect(getByTestId('edit-profile-header')).toBeTruthy();
expect(getByTestId('edit-profile-cancel-button')).toBeTruthy();
expect(getByTestId('edit-profile-save-button')).toBeTruthy();
expect(getByText('Edit Profile')).toBeTruthy();
});
});
it('renders avatar section', async () => {
const { getByTestId, getByText } = renderEditProfileScreen();
await waitFor(() => {
expect(getByTestId('edit-profile-avatar-section')).toBeTruthy();
expect(getByText('Change Avatar')).toBeTruthy();
});
});
it('renders name input field', async () => {
const { getByTestId, getByText } = renderEditProfileScreen();
await waitFor(() => {
expect(getByTestId('edit-profile-name-group')).toBeTruthy();
expect(getByTestId('edit-profile-name-input')).toBeTruthy();
expect(getByText('Display Name')).toBeTruthy();
});
});
it('renders read-only email field', async () => {
const { getByTestId, getByText } = renderEditProfileScreen();
await waitFor(() => {
expect(getByTestId('edit-profile-email-group')).toBeTruthy();
expect(getByText('Email cannot be changed')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 9. EDIT PROFILE FORM INTERACTIONS
// ----------------------------------------------------------
describe('9. EditProfileScreen Form Interactions', () => {
it('allows editing name field', async () => {
const { getByTestId } = renderEditProfileScreen();
await waitFor(() => {
const nameInput = getByTestId('edit-profile-name-input');
fireEvent.changeText(nameInput, 'New Name');
});
});
it('opens avatar modal when avatar button is pressed', async () => {
const { getByTestId, getByText } = renderEditProfileScreen();
await waitFor(() => {
const avatarButton = getByTestId('edit-profile-avatar-button');
fireEvent.press(avatarButton);
});
await waitFor(() => {
expect(getByText('Change Avatar')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 10. EDIT PROFILE CANCEL FLOW
// ----------------------------------------------------------
describe('10. EditProfileScreen Cancel Flow', () => {
it('goes back without alert when no changes made', async () => {
const { getByTestId } = renderEditProfileScreen();
await waitFor(() => {
const cancelButton = getByTestId('edit-profile-cancel-button');
fireEvent.press(cancelButton);
});
// Should navigate back directly without showing alert
await waitFor(() => {
expect(mockGoBack).toHaveBeenCalled();
});
});
it('shows discard alert when changes exist', async () => {
const { getByTestId } = renderEditProfileScreen();
await waitFor(async () => {
// Make a change
const nameInput = getByTestId('edit-profile-name-input');
fireEvent.changeText(nameInput, 'Changed Name');
// Try to cancel
const cancelButton = getByTestId('edit-profile-cancel-button');
fireEvent.press(cancelButton);
});
await waitFor(() => {
expect(mockAlert).toHaveBeenCalledWith(
'Discard Changes?',
'You have unsaved changes. Are you sure you want to go back?',
expect.arrayContaining([
expect.objectContaining({ text: 'Keep Editing' }),
expect.objectContaining({ text: 'Discard', style: 'destructive' }),
])
);
});
});
});
// ----------------------------------------------------------
// 11. EDIT PROFILE SAVE FLOW
// ----------------------------------------------------------
describe('11. EditProfileScreen Save Flow', () => {
it('Save button is disabled when no changes', async () => {
const { getByTestId } = renderEditProfileScreen();
await waitFor(() => {
const saveButton = getByTestId('edit-profile-save-button');
expect(saveButton).toBeTruthy();
// Save button should have disabled styling when no changes
});
});
it('enables Save button when changes are made', async () => {
const { getByTestId } = renderEditProfileScreen();
await waitFor(async () => {
// Make a change
const nameInput = getByTestId('edit-profile-name-input');
fireEvent.changeText(nameInput, 'New Name Here');
// Save button should now be enabled
const saveButton = getByTestId('edit-profile-save-button');
expect(saveButton).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 12. EDGE CASES
// ----------------------------------------------------------
describe('12. Edge Cases', () => {
it('handles user without profile data gracefully', async () => {
// Override mock to return null profile
jest.doMock('../../lib/supabase', () => ({
supabase: {
from: () => ({
select: jest.fn().mockReturnThis(),
eq: jest.fn().mockReturnThis(),
single: jest.fn().mockResolvedValue({
data: null,
error: null,
}),
}),
},
}));
const { getByTestId } = renderProfileScreen();
await waitFor(() => {
expect(getByTestId('profile-screen')).toBeTruthy();
});
});
it('displays fallback for missing user email', async () => {
const { getByTestId } = renderProfileScreen({
auth: { user: null },
});
// Should handle gracefully
await waitFor(() => {
// Loading state or screen should render
});
});
});
});
@@ -0,0 +1,563 @@
/**
* SettingsButton E2E Tests
*
* Tests the Settings button in DashboardScreen header and all features
* within the SettingsScreen. These tests simulate real user interactions.
*
* Test Coverage:
* - Settings screen rendering
* - Dark Mode toggle
* - Font Size selection
* - Push Notifications toggle
* - Email Updates toggle
* - Network Node selection
* - Biometric Security toggle
* - Auto-Lock Timer selection
* - Profile editing
* - Sign Out flow
* - Support links
*/
import React from 'react';
import { render, fireEvent, waitFor, act } from '@testing-library/react-native';
import { Alert, Linking } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Mock contexts
jest.mock('../../contexts/ThemeContext', () => require('../../__mocks__/contexts/ThemeContext'));
jest.mock('../../contexts/BiometricAuthContext', () => require('../../__mocks__/contexts/BiometricAuthContext'));
jest.mock('../../contexts/AuthContext', () => require('../../__mocks__/contexts/AuthContext'));
jest.mock('../../contexts/PezkuwiContext', () => ({
usePezkuwi: () => ({
endpoint: 'wss://rpc.pezkuwichain.io:9944',
setEndpoint: jest.fn(),
api: null,
isApiReady: false,
selectedAccount: null,
}),
}));
// Mock Alert
const mockAlert = jest.spyOn(Alert, 'alert');
// Mock Linking
const mockLinkingOpenURL = jest.spyOn(Linking, 'openURL').mockImplementation(() => Promise.resolve(true));
// Mock Supabase
jest.mock('../../lib/supabase', () => ({
supabase: {
from: jest.fn(() => ({
select: jest.fn().mockReturnThis(),
update: jest.fn().mockReturnThis(),
eq: jest.fn().mockReturnThis(),
maybeSingle: jest.fn().mockResolvedValue({
data: {
id: 'test-user-id',
full_name: 'Test User',
notifications_push: true,
notifications_email: true,
},
error: null,
}),
})),
},
}));
import SettingsScreen from '../../screens/SettingsScreen';
import { MockThemeProvider, mockThemeContext } from '../../__mocks__/contexts/ThemeContext';
import { MockBiometricAuthProvider, mockBiometricContext } from '../../__mocks__/contexts/BiometricAuthContext';
import { MockAuthProvider, mockAuthContext } from '../../__mocks__/contexts/AuthContext';
// ============================================================
// TEST HELPERS
// ============================================================
const renderSettingsScreen = (overrides: {
theme?: Partial<typeof mockThemeContext>;
biometric?: Partial<typeof mockBiometricContext>;
auth?: Partial<typeof mockAuthContext>;
} = {}) => {
return render(
<MockAuthProvider value={overrides.auth}>
<MockBiometricAuthProvider value={overrides.biometric}>
<MockThemeProvider value={overrides.theme}>
<SettingsScreen />
</MockThemeProvider>
</MockBiometricAuthProvider>
</MockAuthProvider>
);
};
// ============================================================
// TESTS
// ============================================================
describe('SettingsButton E2E Tests', () => {
beforeEach(async () => {
jest.clearAllMocks();
await AsyncStorage.clear();
mockAlert.mockClear();
mockLinkingOpenURL.mockClear();
});
// ----------------------------------------------------------
// 1. RENDERING TESTS
// ----------------------------------------------------------
describe('1. Screen Rendering', () => {
it('renders Settings screen with all sections', () => {
const { getByText, getByTestId } = renderSettingsScreen();
// Main container
expect(getByTestId('settings-screen')).toBeTruthy();
// Section headers
expect(getByText('ACCOUNT')).toBeTruthy();
expect(getByText('APP SETTINGS')).toBeTruthy();
expect(getByText('NETWORK & SECURITY')).toBeTruthy();
expect(getByText('SUPPORT')).toBeTruthy();
// Header
expect(getByText('Settings')).toBeTruthy();
});
it('renders all setting items', () => {
const { getByText } = renderSettingsScreen();
// Account section
expect(getByText('Edit Profile')).toBeTruthy();
expect(getByText('Wallet Management')).toBeTruthy();
// App Settings section
expect(getByText('Dark Mode')).toBeTruthy();
expect(getByText('Font Size')).toBeTruthy();
expect(getByText('Push Notifications')).toBeTruthy();
expect(getByText('Email Updates')).toBeTruthy();
// Network & Security section
expect(getByText('Network Node')).toBeTruthy();
expect(getByText('Biometric Security')).toBeTruthy();
expect(getByText('Auto-Lock Timer')).toBeTruthy();
// Support section
expect(getByText('Terms of Service')).toBeTruthy();
expect(getByText('Privacy Policy')).toBeTruthy();
expect(getByText('Help Center')).toBeTruthy();
// Logout
expect(getByText('Sign Out')).toBeTruthy();
});
it('displays version info in footer', () => {
const { getByText } = renderSettingsScreen();
expect(getByText('Pezkuwi Super App v1.0.0')).toBeTruthy();
expect(getByText('© 2026 Digital Kurdistan')).toBeTruthy();
});
});
// ----------------------------------------------------------
// 2. DARK MODE TESTS
// ----------------------------------------------------------
describe('2. Dark Mode Toggle', () => {
it('shows correct subtitle when dark mode is OFF', () => {
const { getByText } = renderSettingsScreen({
theme: { isDarkMode: false },
});
expect(getByText('Light theme enabled')).toBeTruthy();
});
it('shows correct subtitle when dark mode is ON', () => {
const { getByText } = renderSettingsScreen({
theme: { isDarkMode: true },
});
expect(getByText('Dark theme enabled')).toBeTruthy();
});
it('calls toggleDarkMode when switch is toggled', async () => {
const mockToggle = jest.fn();
const { getByTestId } = renderSettingsScreen({
theme: { isDarkMode: false, toggleDarkMode: mockToggle },
});
const darkModeSwitch = getByTestId('dark-mode-switch');
fireEvent(darkModeSwitch, 'valueChange', true);
await waitFor(() => {
expect(mockToggle).toHaveBeenCalledTimes(1);
});
});
});
// ----------------------------------------------------------
// 3. FONT SIZE TESTS
// ----------------------------------------------------------
describe('3. Font Size Selection', () => {
it('shows current font size in subtitle', () => {
const { getByText } = renderSettingsScreen({
theme: { fontSize: 'medium' },
});
expect(getByText('Medium')).toBeTruthy();
});
it('opens font size modal when button is pressed', async () => {
const { getByTestId, getByText } = renderSettingsScreen();
const fontSizeButton = getByTestId('font-size-button');
fireEvent.press(fontSizeButton);
await waitFor(() => {
expect(getByText('Select Font Size')).toBeTruthy();
expect(getByText('Small')).toBeTruthy();
expect(getByText('Large')).toBeTruthy();
});
});
it('calls setFontSize when Small option is selected', async () => {
const mockSetFontSize = jest.fn();
const { getByTestId } = renderSettingsScreen({
theme: { fontSize: 'medium', setFontSize: mockSetFontSize },
});
// Open modal
fireEvent.press(getByTestId('font-size-button'));
// Select Small
await waitFor(() => {
const smallOption = getByTestId('font-size-option-small');
fireEvent.press(smallOption);
});
await waitFor(() => {
expect(mockSetFontSize).toHaveBeenCalledWith('small');
});
});
it('calls setFontSize when Large option is selected', async () => {
const mockSetFontSize = jest.fn();
const { getByTestId } = renderSettingsScreen({
theme: { fontSize: 'medium', setFontSize: mockSetFontSize },
});
// Open modal
fireEvent.press(getByTestId('font-size-button'));
// Select Large
await waitFor(() => {
const largeOption = getByTestId('font-size-option-large');
fireEvent.press(largeOption);
});
await waitFor(() => {
expect(mockSetFontSize).toHaveBeenCalledWith('large');
});
});
it('closes modal when Cancel is pressed', async () => {
const { getByTestId, queryByText } = renderSettingsScreen();
// Open modal
fireEvent.press(getByTestId('font-size-button'));
// Cancel
await waitFor(() => {
const cancelButton = getByTestId('font-size-modal-cancel');
fireEvent.press(cancelButton);
});
// Modal should close (title should not be visible)
await waitFor(() => {
// After closing, modal content should not be rendered
// This is a basic check - in reality modal visibility is controlled by state
});
});
});
// ----------------------------------------------------------
// 4. AUTO-LOCK TIMER TESTS
// ----------------------------------------------------------
describe('4. Auto-Lock Timer Selection', () => {
it('shows current auto-lock time in subtitle', () => {
const { getByText } = renderSettingsScreen({
biometric: { autoLockTimer: 5 },
});
expect(getByText('5 minutes')).toBeTruthy();
});
it('opens auto-lock modal when button is pressed', async () => {
const { getByTestId, getByText } = renderSettingsScreen();
const autoLockButton = getByTestId('auto-lock-button');
fireEvent.press(autoLockButton);
await waitFor(() => {
// Check for modal-specific content
expect(getByText('Lock app after inactivity')).toBeTruthy();
expect(getByText('1 minute')).toBeTruthy();
expect(getByText('15 minutes')).toBeTruthy();
});
});
it('calls setAutoLockTimer when option is selected', async () => {
const mockSetAutoLock = jest.fn();
const { getByTestId } = renderSettingsScreen({
biometric: { autoLockTimer: 5, setAutoLockTimer: mockSetAutoLock },
});
// Open modal
fireEvent.press(getByTestId('auto-lock-button'));
// Select 15 minutes
await waitFor(() => {
const option = getByTestId('auto-lock-option-15');
fireEvent.press(option);
});
await waitFor(() => {
expect(mockSetAutoLock).toHaveBeenCalledWith(15);
});
});
});
// ----------------------------------------------------------
// 5. BIOMETRIC SECURITY TESTS
// ----------------------------------------------------------
describe('5. Biometric Security Toggle', () => {
it('shows "FaceID / Fingerprint" when biometric is disabled', () => {
const { getByText } = renderSettingsScreen({
biometric: { isBiometricEnabled: false },
});
expect(getByText('FaceID / Fingerprint')).toBeTruthy();
});
it('shows biometric type when enabled', () => {
const { getByText } = renderSettingsScreen({
biometric: { isBiometricEnabled: true, biometricType: 'fingerprint' },
});
expect(getByText('Enabled (fingerprint)')).toBeTruthy();
});
it('calls enableBiometric when toggled ON', async () => {
const mockEnable = jest.fn().mockResolvedValue(true);
const { getByTestId } = renderSettingsScreen({
biometric: { isBiometricEnabled: false, enableBiometric: mockEnable },
});
const biometricSwitch = getByTestId('biometric-security-switch');
fireEvent(biometricSwitch, 'valueChange', true);
await waitFor(() => {
expect(mockEnable).toHaveBeenCalled();
});
});
it('calls disableBiometric when toggled OFF', async () => {
const mockDisable = jest.fn();
const { getByTestId } = renderSettingsScreen({
biometric: { isBiometricEnabled: true, disableBiometric: mockDisable },
});
const biometricSwitch = getByTestId('biometric-security-switch');
fireEvent(biometricSwitch, 'valueChange', false);
await waitFor(() => {
expect(mockDisable).toHaveBeenCalled();
});
});
});
// ----------------------------------------------------------
// 6. NETWORK NODE TESTS
// ----------------------------------------------------------
describe('6. Network Node Selection', () => {
it('shows Mainnet in subtitle for production endpoint', () => {
const { getByText } = renderSettingsScreen();
expect(getByText('Mainnet')).toBeTruthy();
});
it('opens network modal when button is pressed', async () => {
const { getByTestId, getByText } = renderSettingsScreen();
const networkButton = getByTestId('network-node-button');
fireEvent.press(networkButton);
await waitFor(() => {
expect(getByText('Select Network Node')).toBeTruthy();
expect(getByText('Pezkuwi Mainnet')).toBeTruthy();
expect(getByText('Pezkuwi Testnet')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 7. SIGN OUT TESTS
// ----------------------------------------------------------
describe('7. Sign Out Flow', () => {
it('shows confirmation alert when Sign Out is pressed', async () => {
const { getByTestId } = renderSettingsScreen();
const signOutButton = getByTestId('sign-out-button');
fireEvent.press(signOutButton);
await waitFor(() => {
expect(mockAlert).toHaveBeenCalledWith(
'Sign Out',
'Are you sure you want to sign out?',
expect.arrayContaining([
expect.objectContaining({ text: 'Cancel' }),
expect.objectContaining({ text: 'Sign Out', style: 'destructive' }),
])
);
});
});
it('calls signOut when confirmed', async () => {
const mockSignOut = jest.fn();
const { getByTestId } = renderSettingsScreen({
auth: { signOut: mockSignOut },
});
const signOutButton = getByTestId('sign-out-button');
fireEvent.press(signOutButton);
await waitFor(() => {
// Get the alert call arguments
const alertCall = mockAlert.mock.calls[0];
const buttons = alertCall[2];
const signOutAction = buttons.find((b: any) => b.text === 'Sign Out');
// Simulate pressing Sign Out
if (signOutAction?.onPress) {
signOutAction.onPress();
}
expect(mockSignOut).toHaveBeenCalled();
});
});
});
// ----------------------------------------------------------
// 8. SUPPORT LINKS TESTS
// ----------------------------------------------------------
describe('8. Support Links', () => {
it('shows Terms of Service alert when pressed', async () => {
const { getByTestId } = renderSettingsScreen();
const tosButton = getByTestId('terms-of-service-button');
fireEvent.press(tosButton);
await waitFor(() => {
expect(mockAlert).toHaveBeenCalledWith(
'Terms',
'Terms of service content...'
);
});
});
it('shows Privacy Policy alert when pressed', async () => {
const { getByTestId } = renderSettingsScreen();
const privacyButton = getByTestId('privacy-policy-button');
fireEvent.press(privacyButton);
await waitFor(() => {
expect(mockAlert).toHaveBeenCalledWith(
'Privacy',
'Privacy policy content...'
);
});
});
it('opens email client when Help Center is pressed', async () => {
const { getByTestId } = renderSettingsScreen();
const helpButton = getByTestId('help-center-button');
fireEvent.press(helpButton);
await waitFor(() => {
expect(mockLinkingOpenURL).toHaveBeenCalledWith(
'mailto:support@pezkuwichain.io'
);
});
});
});
// ----------------------------------------------------------
// 9. PROFILE EDIT TESTS
// ----------------------------------------------------------
describe('9. Profile Editing', () => {
it('opens profile edit modal when Edit Profile is pressed', async () => {
const { getByTestId, getByText } = renderSettingsScreen();
const editProfileButton = getByTestId('edit-profile-button');
fireEvent.press(editProfileButton);
await waitFor(() => {
// Check for modal-specific content (Full Name and Bio labels)
expect(getByText('Full Name')).toBeTruthy();
expect(getByText('Bio')).toBeTruthy();
});
});
});
// ----------------------------------------------------------
// 10. WALLET MANAGEMENT TESTS
// ----------------------------------------------------------
describe('10. Wallet Management', () => {
it('shows Coming Soon alert when Wallet Management is pressed', async () => {
const { getByTestId } = renderSettingsScreen();
const walletButton = getByTestId('wallet-management-button');
fireEvent.press(walletButton);
await waitFor(() => {
expect(mockAlert).toHaveBeenCalledWith(
'Coming Soon',
'Wallet management screen'
);
});
});
});
// ----------------------------------------------------------
// 11. EDGE CASES
// ----------------------------------------------------------
describe('11. Edge Cases', () => {
it('handles rapid toggle clicks gracefully', async () => {
const mockToggle = jest.fn();
const { getByTestId } = renderSettingsScreen({
theme: { isDarkMode: false, toggleDarkMode: mockToggle },
});
const darkModeSwitch = getByTestId('dark-mode-switch');
// Rapid clicks
fireEvent(darkModeSwitch, 'valueChange', true);
fireEvent(darkModeSwitch, 'valueChange', false);
fireEvent(darkModeSwitch, 'valueChange', true);
await waitFor(() => {
expect(mockToggle).toHaveBeenCalledTimes(3);
});
});
it('displays correctly with all toggles enabled', () => {
const { getByTestId } = renderSettingsScreen({
theme: { isDarkMode: true },
biometric: { isBiometricEnabled: true, biometricType: 'facial' },
});
// All toggles should be visible
expect(getByTestId('dark-mode-switch')).toBeTruthy();
expect(getByTestId('biometric-security-switch')).toBeTruthy();
expect(getByTestId('push-notifications-switch')).toBeTruthy();
expect(getByTestId('email-updates-switch')).toBeTruthy();
});
});
});
@@ -0,0 +1,179 @@
/**
* WalletButton E2E Tests
*
* Tests the Wallet button flow including:
* - WalletSetupScreen choice screen
* - Basic navigation
*/
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import { Alert } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Mock contexts
jest.mock('../../contexts/ThemeContext', () => require('../../__mocks__/contexts/ThemeContext'));
jest.mock('../../contexts/AuthContext', () => require('../../__mocks__/contexts/AuthContext'));
jest.mock('../../contexts/PezkuwiContext', () => ({
usePezkuwi: () => ({
api: null,
isApiReady: false,
accounts: [],
selectedAccount: null,
connectWallet: jest.fn().mockResolvedValue(undefined),
disconnectWallet: jest.fn(),
createWallet: jest.fn().mockResolvedValue({
address: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
mnemonic: 'test test test test test test test test test test test junk',
}),
importWallet: jest.fn().mockResolvedValue({
address: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
}),
getKeyPair: jest.fn(),
currentNetwork: 'mainnet',
switchNetwork: jest.fn(),
error: null,
}),
NetworkType: { MAINNET: 'mainnet' },
NETWORKS: { mainnet: { displayName: 'Mainnet', endpoint: 'wss://mainnet.example.com' } },
}));
// Mock @pezkuwi/util-crypto
jest.mock('@pezkuwi/util-crypto', () => ({
mnemonicGenerate: () => 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
mnemonicValidate: () => true,
cryptoWaitReady: jest.fn().mockResolvedValue(true),
}));
// Mock navigation
const mockGoBack = jest.fn();
const mockReplace = jest.fn();
jest.mock('@react-navigation/native', () => ({
...jest.requireActual('@react-navigation/native'),
useNavigation: () => ({
navigate: jest.fn(),
goBack: mockGoBack,
replace: mockReplace,
setOptions: jest.fn(),
}),
}));
// Mock Alert
jest.spyOn(Alert, 'alert');
import WalletSetupScreen from '../../screens/WalletSetupScreen';
import { MockThemeProvider } from '../../__mocks__/contexts/ThemeContext';
import { MockAuthProvider } from '../../__mocks__/contexts/AuthContext';
const renderSetup = () => render(
<MockAuthProvider>
<MockThemeProvider>
<WalletSetupScreen />
</MockThemeProvider>
</MockAuthProvider>
);
describe('WalletSetupScreen', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('renders choice screen', async () => {
const { getByTestId, getByText } = renderSetup();
await waitFor(() => {
expect(getByTestId('wallet-setup-screen')).toBeTruthy();
expect(getByText('Set Up Your Wallet')).toBeTruthy();
});
});
it('shows create button', async () => {
const { getByTestId, getByText } = renderSetup();
await waitFor(() => {
expect(getByTestId('wallet-setup-create-button')).toBeTruthy();
expect(getByText('Create New Wallet')).toBeTruthy();
});
});
it('shows import button', async () => {
const { getByTestId, getByText } = renderSetup();
await waitFor(() => {
expect(getByTestId('wallet-setup-import-button')).toBeTruthy();
expect(getByText('Import Existing Wallet')).toBeTruthy();
});
});
it('close button calls goBack', async () => {
const { getByTestId } = renderSetup();
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-close'));
});
expect(mockGoBack).toHaveBeenCalled();
});
it('create button shows seed phrase screen', async () => {
const { getByTestId, getByText } = renderSetup();
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-create-button'));
});
await waitFor(() => {
expect(getByText('Your Recovery Phrase')).toBeTruthy();
});
});
it('import button shows import screen', async () => {
const { getByTestId, getByText } = renderSetup();
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-import-button'));
});
await waitFor(() => {
expect(getByText('Import Wallet')).toBeTruthy();
});
});
it('seed phrase screen has mnemonic grid', async () => {
const { getByTestId } = renderSetup();
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-create-button'));
});
await waitFor(() => {
expect(getByTestId('mnemonic-grid')).toBeTruthy();
});
});
it('import screen has input field', async () => {
const { getByTestId } = renderSetup();
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-import-button'));
});
await waitFor(() => {
expect(getByTestId('wallet-import-input')).toBeTruthy();
});
});
it('back from seed phrase goes to choice', async () => {
const { getByTestId } = renderSetup();
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-create-button'));
});
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-back'));
});
await waitFor(() => {
expect(getByTestId('wallet-setup-choice')).toBeTruthy();
});
});
it('back from import goes to choice', async () => {
const { getByTestId } = renderSetup();
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-import-button'));
});
await waitFor(() => {
fireEvent.press(getByTestId('wallet-setup-back'));
});
await waitFor(() => {
expect(getByTestId('wallet-setup-choice')).toBeTruthy();
});
});
});
@@ -1,222 +0,0 @@
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Mock contexts before importing SettingsScreen
jest.mock('../../contexts/ThemeContext', () => require('../../__mocks__/contexts/ThemeContext'));
jest.mock('../../contexts/BiometricAuthContext', () => require('../../__mocks__/contexts/BiometricAuthContext'));
jest.mock('../../contexts/AuthContext', () => require('../../__mocks__/contexts/AuthContext'));
// Mock Alert
jest.mock('react-native/Libraries/Alert/Alert', () => ({
alert: jest.fn(),
}));
import SettingsScreen from '../../screens/SettingsScreen';
import { MockThemeProvider } from '../../__mocks__/contexts/ThemeContext';
import { MockBiometricAuthProvider } from '../../__mocks__/contexts/BiometricAuthContext';
import { MockAuthProvider } from '../../__mocks__/contexts/AuthContext';
// Helper to render SettingsScreen with all required providers
const renderSettingsScreen = (themeValue = {}, biometricValue = {}, authValue = {}) => {
return render(
<MockAuthProvider value={authValue}>
<MockBiometricAuthProvider value={biometricValue}>
<MockThemeProvider value={themeValue}>
<SettingsScreen />
</MockThemeProvider>
</MockBiometricAuthProvider>
</MockAuthProvider>
);
};
describe('SettingsScreen - Dark Mode Feature', () => {
beforeEach(async () => {
jest.clearAllMocks();
// Clear AsyncStorage before each test
await AsyncStorage.clear();
});
describe('Rendering', () => {
it('should render Dark Mode section with toggle', () => {
const { getByText } = renderSettingsScreen();
expect(getByText('APPEARANCE')).toBeTruthy();
expect(getByText('darkMode')).toBeTruthy();
});
it('should show current dark mode state', () => {
const { getByText } = renderSettingsScreen({ isDarkMode: false });
// Should show subtitle when dark mode is off
expect(getByText(/settingsScreen.subtitles.lightThemeEnabled/i)).toBeTruthy();
});
it('should show "Enabled" when dark mode is on', () => {
const { getByText } = renderSettingsScreen({ isDarkMode: true });
// Should show subtitle when dark mode is on
expect(getByText(/settingsScreen.subtitles.darkThemeEnabled/i)).toBeTruthy();
});
});
describe('Toggle Functionality', () => {
it('should toggle dark mode when switch is pressed', async () => {
const mockToggleDarkMode = jest.fn().mockResolvedValue(undefined);
const { getByTestId } = renderSettingsScreen({
isDarkMode: false,
toggleDarkMode: mockToggleDarkMode,
});
// Find the toggle switch
const darkModeSwitch = getByTestId('dark-mode-switch');
// Toggle the switch
fireEvent(darkModeSwitch, 'valueChange', true);
// Verify toggleDarkMode was called
await waitFor(() => {
expect(mockToggleDarkMode).toHaveBeenCalledTimes(1);
});
});
it('should toggle from enabled to disabled', async () => {
const mockToggleDarkMode = jest.fn().mockResolvedValue(undefined);
const { getByTestId } = renderSettingsScreen({
isDarkMode: true,
toggleDarkMode: mockToggleDarkMode,
});
const darkModeSwitch = getByTestId('dark-mode-switch');
// Toggle off
fireEvent(darkModeSwitch, 'valueChange', false);
await waitFor(() => {
expect(mockToggleDarkMode).toHaveBeenCalledTimes(1);
});
});
});
describe('Persistence', () => {
it('should save dark mode preference to AsyncStorage', async () => {
const mockToggleDarkMode = jest.fn(async () => {
await AsyncStorage.setItem('@pezkuwi/theme', 'dark');
});
const { getByTestId } = renderSettingsScreen({
isDarkMode: false,
toggleDarkMode: mockToggleDarkMode,
});
const darkModeSwitch = getByTestId('dark-mode-switch');
fireEvent(darkModeSwitch, 'valueChange', true);
await waitFor(() => {
expect(AsyncStorage.setItem).toHaveBeenCalledWith('@pezkuwi/theme', 'dark');
});
});
it('should load dark mode preference on mount', async () => {
// Pre-set dark mode in AsyncStorage
await AsyncStorage.setItem('@pezkuwi/theme', 'dark');
const { getByText } = renderSettingsScreen({ isDarkMode: true });
// Verify dark mode is enabled - check for dark theme subtitle
expect(getByText(/settingsScreen.subtitles.darkThemeEnabled/i)).toBeTruthy();
});
});
describe('Theme Application', () => {
it('should apply dark theme colors when enabled', () => {
const darkColors = {
background: '#121212',
surface: '#1E1E1E',
text: '#FFFFFF',
textSecondary: '#B0B0B0',
border: '#333333',
};
const { getByTestId } = renderSettingsScreen({
isDarkMode: true,
colors: darkColors,
});
const container = getByTestId('settings-screen');
// Verify dark background is applied
expect(container.props.style).toEqual(
expect.objectContaining({
backgroundColor: darkColors.background,
})
);
});
it('should apply light theme colors when disabled', () => {
const lightColors = {
background: '#F5F5F5',
surface: '#FFFFFF',
text: '#000000',
textSecondary: '#666666',
border: '#E0E0E0',
};
const { getByTestId } = renderSettingsScreen({
isDarkMode: false,
colors: lightColors,
});
const container = getByTestId('settings-screen');
// Verify light background is applied
expect(container.props.style).toEqual(
expect.objectContaining({
backgroundColor: lightColors.background,
})
);
});
});
describe('Edge Cases', () => {
it('should handle rapid toggle clicks', async () => {
const mockToggleDarkMode = jest.fn().mockResolvedValue(undefined);
const { getByTestId } = renderSettingsScreen({
isDarkMode: false,
toggleDarkMode: mockToggleDarkMode,
});
const darkModeSwitch = getByTestId('dark-mode-switch');
// Rapid clicks
fireEvent(darkModeSwitch, 'valueChange', true);
fireEvent(darkModeSwitch, 'valueChange', false);
fireEvent(darkModeSwitch, 'valueChange', true);
await waitFor(() => {
// Should handle all toggle attempts
expect(mockToggleDarkMode).toHaveBeenCalled();
});
});
it('should call toggleDarkMode multiple times without issues', async () => {
const mockToggleDarkMode = jest.fn().mockResolvedValue(undefined);
const { getByTestId } = renderSettingsScreen({
isDarkMode: false,
toggleDarkMode: mockToggleDarkMode,
});
const darkModeSwitch = getByTestId('dark-mode-switch');
// Toggle multiple times
fireEvent(darkModeSwitch, 'valueChange', true);
fireEvent(darkModeSwitch, 'valueChange', false);
fireEvent(darkModeSwitch, 'valueChange', true);
await waitFor(() => {
// Should handle all calls
expect(mockToggleDarkMode).toHaveBeenCalledTimes(3);
});
});
});
});
@@ -1,240 +0,0 @@
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
// Mock contexts before importing SettingsScreen
jest.mock('../../contexts/ThemeContext', () => require('../../__mocks__/contexts/ThemeContext'));
jest.mock('../../contexts/BiometricAuthContext', () => require('../../__mocks__/contexts/BiometricAuthContext'));
jest.mock('../../contexts/AuthContext', () => require('../../__mocks__/contexts/AuthContext'));
// Mock Alert
jest.mock('react-native/Libraries/Alert/Alert', () => ({
alert: jest.fn(),
}));
import SettingsScreen from '../../screens/SettingsScreen';
import FontSizeModal from '../../components/FontSizeModal';
import { MockThemeProvider } from '../../__mocks__/contexts/ThemeContext';
import { MockBiometricAuthProvider } from '../../__mocks__/contexts/BiometricAuthContext';
import { MockAuthProvider } from '../../__mocks__/contexts/AuthContext';
// Helper to render SettingsScreen with all required providers
const renderSettingsScreen = (themeValue = {}, biometricValue = {}, authValue = {}) => {
return render(
<MockAuthProvider value={authValue}>
<MockBiometricAuthProvider value={biometricValue}>
<MockThemeProvider value={themeValue}>
<SettingsScreen />
</MockThemeProvider>
</MockBiometricAuthProvider>
</MockAuthProvider>
);
};
// Helper to render FontSizeModal
const renderFontSizeModal = (overrides: any = {}) => {
const mockSetFontSize = overrides.setFontSize || jest.fn().mockResolvedValue(undefined);
const mockOnClose = overrides.onClose || jest.fn();
const themeValue = {
fontSize: overrides.fontSize || ('medium' as 'small' | 'medium' | 'large'),
setFontSize: mockSetFontSize,
};
const props = {
visible: overrides.visible !== undefined ? overrides.visible : true,
onClose: mockOnClose,
};
return {
...render(
<MockThemeProvider value={themeValue}>
<FontSizeModal {...props} />
</MockThemeProvider>
),
mockSetFontSize,
mockOnClose,
};
};
describe('SettingsScreen - Font Size Feature', () => {
beforeEach(async () => {
jest.clearAllMocks();
await AsyncStorage.clear();
});
describe('Rendering', () => {
it('should render Font Size button', () => {
const { getByText } = renderSettingsScreen();
expect(getByText('Font Size')).toBeTruthy();
});
it('should show current font size in subtitle', () => {
const { getByText } = renderSettingsScreen({ fontSize: 'medium' });
expect(getByText('Current: Medium')).toBeTruthy();
});
it('should show Small font size in subtitle', () => {
const { getByText } = renderSettingsScreen({ fontSize: 'small' });
expect(getByText('Current: Small')).toBeTruthy();
});
it('should show Large font size in subtitle', () => {
const { getByText } = renderSettingsScreen({ fontSize: 'large' });
expect(getByText('Current: Large')).toBeTruthy();
});
});
describe('Modal Interaction', () => {
it('should open font size modal when button is pressed', async () => {
const { getByText, getByTestId } = renderSettingsScreen();
const fontSizeButton = getByText('Font Size').parent?.parent;
expect(fontSizeButton).toBeTruthy();
fireEvent.press(fontSizeButton!);
// Modal should open (we'll test modal rendering separately)
await waitFor(() => {
// Just verify the button was pressable
expect(fontSizeButton).toBeTruthy();
});
});
});
describe('Font Scale Application', () => {
it('should display small font scale', () => {
const { getByText } = renderSettingsScreen({
fontSize: 'small',
fontScale: 0.875,
});
// Verify font size is displayed
expect(getByText('Current: Small')).toBeTruthy();
});
it('should display medium font scale', () => {
const { getByText } = renderSettingsScreen({
fontSize: 'medium',
fontScale: 1.0,
});
expect(getByText('Current: Medium')).toBeTruthy();
});
it('should display large font scale', () => {
const { getByText } = renderSettingsScreen({
fontSize: 'large',
fontScale: 1.125,
});
expect(getByText('Current: Large')).toBeTruthy();
});
});
describe('Persistence', () => {
it('should save font size to AsyncStorage', async () => {
const mockSetFontSize = jest.fn(async (size) => {
await AsyncStorage.setItem('@pezkuwi/font_size', size);
});
const { getByText } = renderSettingsScreen({
fontSize: 'medium',
setFontSize: mockSetFontSize,
});
// Simulate selecting a new size
await mockSetFontSize('large');
await waitFor(() => {
expect(AsyncStorage.setItem).toHaveBeenCalledWith('@pezkuwi/font_size', 'large');
});
});
it('should load saved font size on mount', async () => {
await AsyncStorage.setItem('@pezkuwi/font_size', 'large');
const { getByText } = renderSettingsScreen({ fontSize: 'large' });
expect(getByText('Current: Large')).toBeTruthy();
});
});
});
describe('FontSizeModal Component', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('Rendering', () => {
it('should render modal when visible', () => {
const { getByText } = renderFontSizeModal({ fontSize: 'medium', visible: true });
expect(getByText('Font Size')).toBeTruthy();
});
it('should render all three size options', () => {
const { getByText } = renderFontSizeModal();
expect(getByText('Small')).toBeTruthy();
expect(getByText(/Medium.*Default/i)).toBeTruthy();
expect(getByText('Large')).toBeTruthy();
});
it('should show checkmark on current size', () => {
const { getByTestId, getByText } = renderFontSizeModal({ fontSize: 'medium' });
const mediumOption = getByTestId('font-size-medium');
expect(mediumOption).toBeTruthy();
// Checkmark should be visible for medium
expect(getByText('✓')).toBeTruthy();
});
});
describe('Size Selection', () => {
it('should call setFontSize when Small is pressed', async () => {
const { getByTestId, mockSetFontSize, mockOnClose } = renderFontSizeModal({
fontSize: 'medium',
});
const smallButton = getByTestId('font-size-small');
fireEvent.press(smallButton);
await waitFor(() => {
expect(mockSetFontSize).toHaveBeenCalledWith('small');
expect(mockOnClose).toHaveBeenCalled();
});
});
it('should call setFontSize when Large is pressed', async () => {
const { getByTestId, mockSetFontSize, mockOnClose } = renderFontSizeModal({
fontSize: 'medium',
});
const largeButton = getByTestId('font-size-large');
fireEvent.press(largeButton);
await waitFor(() => {
expect(mockSetFontSize).toHaveBeenCalledWith('large');
expect(mockOnClose).toHaveBeenCalled();
});
});
});
describe('Modal Close', () => {
it('should call onClose when close button is pressed', async () => {
const { getByTestId, mockOnClose } = renderFontSizeModal();
const closeButton = getByTestId('font-size-modal-close');
fireEvent.press(closeButton);
await waitFor(() => {
expect(mockOnClose).toHaveBeenCalled();
});
});
});
});
+3 -6
View File
@@ -4,7 +4,6 @@ import { render, RenderOptions } from '@testing-library/react-native';
// Mock all contexts with simple implementations
const MockAuthProvider = ({ children }: { children: React.ReactNode }) => <>{children}</>;
const MockPezkuwiProvider = ({ children }: { children: React.ReactNode }) => <>{children}</>;
const MockLanguageProvider = ({ children }: { children: React.ReactNode }) => <>{children}</>;
const MockBiometricAuthProvider = ({ children }: { children: React.ReactNode }) => <>{children}</>;
// Wrapper component with all providers
@@ -12,11 +11,9 @@ const AllTheProviders = ({ children }: { children: React.ReactNode }) => {
return (
<MockAuthProvider>
<MockPezkuwiProvider>
<MockLanguageProvider>
<MockBiometricAuthProvider>
{children}
</MockBiometricAuthProvider>
</MockLanguageProvider>
<MockBiometricAuthProvider>
{children}
</MockBiometricAuthProvider>
</MockPezkuwiProvider>
</MockAuthProvider>
);
+67 -32
View File
@@ -16,6 +16,16 @@ import { KurdistanColors } from '../theme/colors';
import { useAuth } from '../contexts/AuthContext';
import { supabase } from '../lib/supabase';
// Cross-platform alert helper
const showAlert = (title: string, message: string, buttons?: Array<{text: string; onPress?: () => void}>) => {
if (Platform.OS === 'web') {
window.alert(`${title}\n\n${message}`);
if (buttons?.[0]?.onPress) buttons[0].onPress();
} else {
showAlert(title, message, buttons);
}
};
// Avatar pool - Kurdish/Middle Eastern themed avatars
const AVATAR_POOL = [
{ id: 'avatar1', emoji: '👨🏻', label: 'Man 1' },
@@ -74,7 +84,7 @@ const AvatarPickerModal: React.FC<AvatarPickerModalProps> = ({
if (Platform.OS !== 'web') {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
Alert.alert(
showAlert(
'Permission Required',
'Sorry, we need camera roll permissions to upload your photo!'
);
@@ -111,63 +121,88 @@ const AvatarPickerModal: React.FC<AvatarPickerModalProps> = ({
if (__DEV__) console.log('[AvatarPicker] Upload successful:', uploadedUrl);
setUploadedImageUri(uploadedUrl);
setSelectedAvatar(null); // Clear emoji selection
Alert.alert('Success', 'Photo uploaded successfully!');
showAlert('Success', 'Photo uploaded successfully!');
} else {
if (__DEV__) console.error('[AvatarPicker] Upload failed: no URL returned');
Alert.alert('Upload Failed', 'Could not upload your photo. Please check your internet connection and try again.');
showAlert('Upload Failed', 'Could not upload your photo. Please check your internet connection and try again.');
}
}
} catch (error) {
setIsUploading(false);
if (__DEV__) console.error('[AvatarPicker] Error picking image:', error);
Alert.alert('Error', 'Failed to pick image. Please try again.');
showAlert('Error', 'Failed to pick image. Please try again.');
}
};
const uploadImageToSupabase = async (imageUri: string): Promise<string | null> => {
if (!user) {
if (__DEV__) console.error('[AvatarPicker] No user found');
console.error('[AvatarPicker] No user found');
return null;
}
try {
if (__DEV__) console.log('[AvatarPicker] Fetching image blob...');
// Convert image URI to blob for web, or use file for native
console.log('[AvatarPicker] Starting upload for URI:', imageUri.substring(0, 50) + '...');
// Convert image URI to blob
const response = await fetch(imageUri);
const blob = await response.blob();
if (__DEV__) console.log('[AvatarPicker] Blob size:', blob.size, 'bytes');
console.log('[AvatarPicker] Blob created - size:', blob.size, 'bytes, type:', blob.type);
// Generate unique filename
const fileExt = imageUri.split('.').pop()?.toLowerCase() || 'jpg';
const fileName = `${user.id}-${Date.now()}.${fileExt}`;
const filePath = `avatars/${fileName}`;
if (__DEV__) console.log('[AvatarPicker] Uploading to:', filePath);
// Upload to Supabase Storage
const { data: uploadData, error: uploadError } = await supabase.storage
.from('profiles')
.upload(filePath, blob, {
contentType: `image/${fileExt}`,
upsert: false,
});
if (uploadError) {
if (__DEV__) console.error('[AvatarPicker] Upload error:', uploadError);
if (blob.size === 0) {
console.error('[AvatarPicker] Blob is empty!');
return null;
}
if (__DEV__) console.log('[AvatarPicker] Upload successful:', uploadData);
// Get file extension from blob type or URI
let fileExt = 'jpg';
if (blob.type) {
// Extract extension from MIME type (e.g., 'image/jpeg' -> 'jpeg')
const mimeExt = blob.type.split('/')[1];
if (mimeExt && mimeExt !== 'octet-stream') {
fileExt = mimeExt === 'jpeg' ? 'jpg' : mimeExt;
}
} else if (!imageUri.startsWith('blob:') && !imageUri.startsWith('data:')) {
// Try to get extension from URI for non-blob URIs
const uriExt = imageUri.split('.').pop()?.toLowerCase();
if (uriExt && ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(uriExt)) {
fileExt = uriExt;
}
}
const fileName = `${user.id}-${Date.now()}.${fileExt}`;
const filePath = `avatars/${fileName}`;
const contentType = blob.type || `image/${fileExt}`;
console.log('[AvatarPicker] Uploading to path:', filePath, 'contentType:', contentType);
// Upload to Supabase Storage
const { data: uploadData, error: uploadError } = await supabase.storage
.from('avatars')
.upload(filePath, blob, {
contentType: contentType,
upsert: true, // Allow overwriting if file exists
});
if (uploadError) {
console.error('[AvatarPicker] Supabase upload error:', uploadError.message, uploadError);
// Show more specific error to user
showAlert('Upload Error', `Storage error: ${uploadError.message}`);
return null;
}
console.log('[AvatarPicker] Upload successful:', uploadData);
// Get public URL
const { data } = supabase.storage
.from('profiles')
.from('avatars')
.getPublicUrl(filePath);
if (__DEV__) console.log('[AvatarPicker] Public URL:', data.publicUrl);
console.log('[AvatarPicker] Public URL:', data.publicUrl);
return data.publicUrl;
} catch (error) {
if (__DEV__) console.error('[AvatarPicker] Error uploading to Supabase:', error);
} catch (error: any) {
console.error('[AvatarPicker] Error uploading to Supabase:', error?.message || error);
showAlert('Upload Error', `Failed to upload: ${error?.message || 'Unknown error'}`);
return null;
}
};
@@ -176,7 +211,7 @@ const AvatarPickerModal: React.FC<AvatarPickerModalProps> = ({
const avatarToSave = uploadedImageUri || selectedAvatar;
if (!avatarToSave || !user) {
Alert.alert('Error', 'Please select an avatar or upload a photo');
showAlert('Error', 'Please select an avatar or upload a photo');
return;
}
@@ -199,7 +234,7 @@ const AvatarPickerModal: React.FC<AvatarPickerModalProps> = ({
if (__DEV__) console.log('[AvatarPicker] Avatar saved successfully:', data);
Alert.alert('Success', 'Avatar updated successfully!');
showAlert('Success', 'Avatar updated successfully!');
if (onAvatarSelected) {
onAvatarSelected(avatarToSave);
@@ -208,7 +243,7 @@ const AvatarPickerModal: React.FC<AvatarPickerModalProps> = ({
onClose();
} catch (error) {
if (__DEV__) console.error('[AvatarPicker] Error updating avatar:', error);
Alert.alert('Error', 'Failed to update avatar. Please try again.');
showAlert('Error', 'Failed to update avatar. Please try again.');
} finally {
setIsSaving(false);
}
+224
View File
@@ -0,0 +1,224 @@
import React, { useEffect, useRef } from 'react';
import { View, Animated, Easing, StyleSheet } from 'react-native';
import Svg, { Circle, Line, Defs, RadialGradient, Stop } from 'react-native-svg';
interface KurdistanSunProps {
size?: number;
}
const AnimatedView = Animated.View;
export const KurdistanSun: React.FC<KurdistanSunProps> = ({ size = 200 }) => {
// Animation values
const greenHaloRotation = useRef(new Animated.Value(0)).current;
const redHaloRotation = useRef(new Animated.Value(0)).current;
const yellowHaloRotation = useRef(new Animated.Value(0)).current;
const raysPulse = useRef(new Animated.Value(1)).current;
const glowPulse = useRef(new Animated.Value(0.6)).current;
useEffect(() => {
// Green halo rotation (3s, clockwise)
Animated.loop(
Animated.timing(greenHaloRotation, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true,
})
).start();
// Red halo rotation (2.5s, counter-clockwise)
Animated.loop(
Animated.timing(redHaloRotation, {
toValue: -1,
duration: 2500,
easing: Easing.linear,
useNativeDriver: true,
})
).start();
// Yellow halo rotation (2s, clockwise)
Animated.loop(
Animated.timing(yellowHaloRotation, {
toValue: 1,
duration: 2000,
easing: Easing.linear,
useNativeDriver: true,
})
).start();
// Rays pulse animation
Animated.loop(
Animated.sequence([
Animated.timing(raysPulse, {
toValue: 0.7,
duration: 1000,
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
}),
Animated.timing(raysPulse, {
toValue: 1,
duration: 1000,
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
}),
])
).start();
// Glow pulse animation
Animated.loop(
Animated.sequence([
Animated.timing(glowPulse, {
toValue: 0.3,
duration: 1000,
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
}),
Animated.timing(glowPulse, {
toValue: 0.6,
duration: 1000,
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
}),
])
).start();
}, []);
const greenSpin = greenHaloRotation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
const redSpin = redHaloRotation.interpolate({
inputRange: [-1, 0],
outputRange: ['-360deg', '0deg'],
});
const yellowSpin = yellowHaloRotation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
const haloSize = size * 0.9;
const borderWidth = size * 0.02;
// Generate 21 rays for Kurdistan flag
const rays = Array.from({ length: 21 }).map((_, i) => {
const angle = (i * 360) / 21;
return (
<Line
key={i}
x1="100"
y1="100"
x2="100"
y2="20"
stroke="rgba(255, 255, 255, 0.9)"
strokeWidth="3"
strokeLinecap="round"
transform={`rotate(${angle} 100 100)`}
/>
);
});
return (
<View style={[styles.container, { width: size, height: size }]}>
{/* Rotating colored halos */}
<View style={styles.halosContainer}>
{/* Green halo (outermost) */}
<AnimatedView
style={[
styles.halo,
{
width: haloSize,
height: haloSize,
borderWidth: borderWidth,
borderTopColor: '#00FF00',
borderBottomColor: '#00FF00',
borderLeftColor: 'transparent',
borderRightColor: 'transparent',
transform: [{ rotate: greenSpin }],
},
]}
/>
{/* Red halo (middle) */}
<AnimatedView
style={[
styles.halo,
{
width: haloSize * 0.8,
height: haloSize * 0.8,
borderWidth: borderWidth,
borderTopColor: 'transparent',
borderBottomColor: 'transparent',
borderLeftColor: '#FF0000',
borderRightColor: '#FF0000',
transform: [{ rotate: redSpin }],
},
]}
/>
{/* Yellow halo (inner) */}
<AnimatedView
style={[
styles.halo,
{
width: haloSize * 0.6,
height: haloSize * 0.6,
borderWidth: borderWidth,
borderTopColor: '#FFD700',
borderBottomColor: '#FFD700',
borderLeftColor: 'transparent',
borderRightColor: 'transparent',
transform: [{ rotate: yellowSpin }],
},
]}
/>
</View>
{/* Kurdistan Sun SVG with 21 rays */}
<AnimatedView style={[styles.svgContainer, { opacity: raysPulse }]}>
<Svg width={size} height={size} viewBox="0 0 200 200">
<Defs>
<RadialGradient id="sunGradient" cx="50%" cy="50%" r="50%">
<Stop offset="0%" stopColor="rgba(255, 255, 255, 0.8)" />
<Stop offset="100%" stopColor="rgba(255, 255, 255, 0.2)" />
</RadialGradient>
</Defs>
{/* Sun rays (21 rays for Kurdistan flag) */}
{rays}
{/* Central white circle */}
<Circle cx="100" cy="100" r="35" fill="white" />
{/* Inner glow */}
<Circle cx="100" cy="100" r="35" fill="url(#sunGradient)" />
</Svg>
</AnimatedView>
</View>
);
};
const styles = StyleSheet.create({
container: {
position: 'relative',
alignItems: 'center',
justifyContent: 'center',
},
halosContainer: {
position: 'absolute',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
},
halo: {
position: 'absolute',
borderRadius: 1000,
},
svgContainer: {
position: 'relative',
zIndex: 1,
},
});
export default KurdistanSun;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
export { default as HezTokenLogo } from './HezTokenLogo';
export { default as PezTokenLogo } from './PezTokenLogo';
-64
View File
@@ -1,64 +0,0 @@
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { I18nManager } from 'react-native';
import { isRTL, languages } from '../i18n';
import i18n from '../i18n';
// Language is set at build time via environment variable
const BUILD_LANGUAGE = process.env.EXPO_PUBLIC_DEFAULT_LANGUAGE || 'en';
interface Language {
code: string;
name: string;
nativeName: string;
rtl: boolean;
}
interface LanguageContextType {
currentLanguage: string;
isRTL: boolean;
hasSelectedLanguage: boolean;
availableLanguages: Language[];
}
const LanguageContext = createContext<LanguageContextType | undefined>(undefined);
export const LanguageProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
// Language is fixed at build time - no runtime switching
const [currentLanguage] = useState(BUILD_LANGUAGE);
const [currentIsRTL] = useState(isRTL(BUILD_LANGUAGE));
useEffect(() => {
// Initialize i18n with build-time language
i18n.changeLanguage(BUILD_LANGUAGE);
// Set RTL if needed
const isRTLLanguage = ['ar', 'ckb', 'fa'].includes(BUILD_LANGUAGE);
I18nManager.allowRTL(isRTLLanguage);
I18nManager.forceRTL(isRTLLanguage);
if (__DEV__) {
console.log(`[LanguageContext] Build language: ${BUILD_LANGUAGE}, RTL: ${isRTLLanguage}`);
}
}, []);
return (
<LanguageContext.Provider
value={{
currentLanguage,
isRTL: currentIsRTL,
hasSelectedLanguage: true, // Always true - language pre-selected at build time
availableLanguages: languages,
}}
>
{children}
</LanguageContext.Provider>
);
};
export const useLanguage = (): LanguageContextType => {
const context = useContext(LanguageContext);
if (!context) {
throw new Error('useLanguage must be used within LanguageProvider');
}
return context;
};
+114 -23
View File
@@ -1,4 +1,5 @@
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { Platform } from 'react-native';
import { Keyring } from '@pezkuwi/keyring';
import { KeyringPair } from '@pezkuwi/keyring/types';
import { ApiPromise, WsProvider } from '@pezkuwi/api';
@@ -7,6 +8,34 @@ import * as SecureStore from 'expo-secure-store';
import { cryptoWaitReady, mnemonicGenerate } from '@pezkuwi/util-crypto';
import { ENV } from '../config/environment';
// Secure storage helper - uses SecureStore on native, AsyncStorage on web (with warning)
const secureStorage = {
setItem: async (key: string, value: string): Promise<void> => {
if (Platform.OS === 'web') {
// WARNING: AsyncStorage is NOT secure for storing seeds on web
// In production, consider using Web Crypto API or server-side storage
if (__DEV__) console.warn('[SecureStorage] Using AsyncStorage on web - NOT SECURE for production');
await AsyncStorage.setItem(key, value);
} else {
await SecureStore.setItemAsync(key, value);
}
},
getItem: async (key: string): Promise<string | null> => {
if (Platform.OS === 'web') {
return await AsyncStorage.getItem(key);
} else {
return await SecureStore.getItemAsync(key);
}
},
removeItem: async (key: string): Promise<void> => {
if (Platform.OS === 'web') {
await AsyncStorage.removeItem(key);
} else {
await SecureStore.deleteItemAsync(key);
}
},
};
interface Account {
address: string;
name: string;
@@ -15,14 +44,14 @@ interface Account {
};
}
export type NetworkType = 'pezkuwi' | 'dicle' | 'zagros' | 'bizinikiwi';
export type NetworkType = 'pezkuwi' | 'dicle' | 'zagros' | 'bizinikiwi' | 'zombienet';
export interface NetworkConfig {
name: string;
displayName: string;
rpcEndpoint: string;
ss58Format: number;
type: 'mainnet' | 'testnet' | 'canary';
type: 'mainnet' | 'testnet' | 'canary' | 'dev';
}
export const NETWORKS: Record<NetworkType, NetworkConfig> = {
@@ -54,6 +83,13 @@ export const NETWORKS: Record<NetworkType, NetworkConfig> = {
ss58Format: 42,
type: 'testnet',
},
zombienet: {
name: 'zombienet',
displayName: 'Zombienet Dev (Alice/Bob)',
rpcEndpoint: 'wss://zombienet-rpc.pezkuwichain.io',
ss58Format: 42,
type: 'dev',
},
};
interface PezkuwiContextType {
@@ -73,6 +109,7 @@ interface PezkuwiContextType {
disconnectWallet: () => void;
createWallet: (name: string, mnemonic?: string) => Promise<{ address: string; mnemonic: string }>;
importWallet: (name: string, mnemonic: string) => Promise<{ address: string }>;
deleteWallet: (address: string) => Promise<void>;
getKeyPair: (address: string) => Promise<KeyringPair | null>;
signMessage: (address: string, message: string) => Promise<string | null>;
error: string | null;
@@ -131,7 +168,14 @@ export const PezkuwiProvider: React.FC<PezkuwiProviderProps> = ({ children }) =>
const provider = new WsProvider(networkConfig.rpcEndpoint);
console.log('📡 [Pezkuwi] WsProvider created, creating API...');
const newApi = await ApiPromise.create({ provider });
console.log('✅ [Pezkuwi] API created successfully');
// Set SS58 format for address encoding/decoding
newApi.registry.setChainProperties(
newApi.registry.createType('ChainProperties', {
ss58Format: networkConfig.ss58Format,
})
);
console.log(`✅ [Pezkuwi] API created with SS58 format: ${networkConfig.ss58Format}`);
if (isSubscribed) {
setApi(newApi);
@@ -256,9 +300,9 @@ export const PezkuwiProvider: React.FC<PezkuwiProviderProps> = ({ children }) =>
setAccounts(updatedAccounts);
await AsyncStorage.setItem(WALLET_STORAGE_KEY, JSON.stringify(updatedAccounts));
// SECURITY: Store encrypted seed in SecureStore (hardware-backed storage)
// SECURITY: Store encrypted seed in secure storage (hardware-backed on native)
const seedKey = `pezkuwi_seed_${pair.address}`;
await SecureStore.setItemAsync(seedKey, mnemonicPhrase);
await secureStorage.setItem(seedKey, mnemonicPhrase);
if (__DEV__) console.log('[Pezkuwi] Wallet created:', pair.address);
@@ -266,24 +310,33 @@ export const PezkuwiProvider: React.FC<PezkuwiProviderProps> = ({ children }) =>
address: pair.address,
mnemonic: mnemonicPhrase,
};
} catch (err) {
if (__DEV__) console.error('[Pezkuwi] Failed to create wallet:', err);
throw new Error('Failed to create wallet');
} catch (err: any) {
if (__DEV__) {
console.error('[Pezkuwi] Failed to create wallet:', err);
console.error('[Pezkuwi] Error message:', err?.message);
console.error('[Pezkuwi] Error stack:', err?.stack);
}
throw new Error(err?.message || 'Failed to create wallet');
}
};
// Import existing wallet from mnemonic
// Import existing wallet from mnemonic or dev URI (like //Alice)
const importWallet = async (
name: string,
mnemonic: string
seedOrUri: string
): Promise<{ address: string }> => {
if (!keyring) {
throw new Error('Keyring not initialized');
}
try {
// Create account from mnemonic
const pair = keyring.addFromMnemonic(mnemonic.trim(), { name });
const trimmedInput = seedOrUri.trim();
const isDevUri = trimmedInput.startsWith('//');
// Create account from URI or mnemonic
const pair = isDevUri
? keyring.addFromUri(trimmedInput, { name })
: keyring.addFromMnemonic(trimmedInput, { name });
// Check if account already exists
if (accounts.some(a => a.address === pair.address)) {
@@ -301,16 +354,49 @@ export const PezkuwiProvider: React.FC<PezkuwiProviderProps> = ({ children }) =>
setAccounts(updatedAccounts);
await AsyncStorage.setItem(WALLET_STORAGE_KEY, JSON.stringify(updatedAccounts));
// Store seed securely
// Store seed/URI securely
const seedKey = `pezkuwi_seed_${pair.address}`;
await SecureStore.setItemAsync(seedKey, mnemonic.trim());
await secureStorage.setItem(seedKey, trimmedInput);
if (__DEV__) console.log('[Pezkuwi] Wallet imported:', pair.address);
if (__DEV__) console.log('[Pezkuwi] Wallet imported:', pair.address, isDevUri ? '(dev URI)' : '(mnemonic)');
return { address: pair.address };
} catch (err) {
if (__DEV__) console.error('[Pezkuwi] Failed to import wallet:', err);
throw err;
} catch (err: any) {
if (__DEV__) {
console.error('[Pezkuwi] Failed to import wallet:', err);
console.error('[Pezkuwi] Error message:', err?.message);
}
throw new Error(err?.message || 'Failed to import wallet');
}
};
// Delete a wallet
const deleteWallet = async (address: string): Promise<void> => {
try {
// Remove from accounts list
const updatedAccounts = accounts.filter(a => a.address !== address);
setAccounts(updatedAccounts);
await AsyncStorage.setItem(WALLET_STORAGE_KEY, JSON.stringify(updatedAccounts));
// Remove seed from secure storage
const seedKey = `pezkuwi_seed_${address}`;
await secureStorage.removeItem(seedKey);
// If deleted account was selected, select another one
if (selectedAccount?.address === address) {
if (updatedAccounts.length > 0) {
setSelectedAccount(updatedAccounts[0]);
await AsyncStorage.setItem(SELECTED_ACCOUNT_KEY, updatedAccounts[0].address);
} else {
setSelectedAccount(null);
await AsyncStorage.removeItem(SELECTED_ACCOUNT_KEY);
}
}
if (__DEV__) console.log('[Pezkuwi] Wallet deleted:', address);
} catch (err: any) {
if (__DEV__) console.error('[Pezkuwi] Failed to delete wallet:', err);
throw new Error(err?.message || 'Failed to delete wallet');
}
};
@@ -321,17 +407,21 @@ export const PezkuwiProvider: React.FC<PezkuwiProviderProps> = ({ children }) =>
}
try {
// SECURITY: Load seed from SecureStore (encrypted storage)
// SECURITY: Load seed/URI from secure storage (encrypted on native)
const seedKey = `pezkuwi_seed_${address}`;
const mnemonic = await SecureStore.getItemAsync(seedKey);
const seedOrUri = await secureStorage.getItem(seedKey);
if (!mnemonic) {
if (!seedOrUri) {
if (__DEV__) console.error('[Pezkuwi] No seed found for address:', address);
return null;
}
// Recreate keypair from mnemonic
const pair = keyring.addFromMnemonic(mnemonic);
// Recreate keypair from URI or mnemonic
const isDevUri = seedOrUri.startsWith('//');
const pair = isDevUri
? keyring.addFromUri(seedOrUri)
: keyring.addFromMnemonic(seedOrUri);
return pair;
} catch (err) {
if (__DEV__) console.error('[Pezkuwi] Failed to get keypair:', err);
@@ -431,6 +521,7 @@ export const PezkuwiProvider: React.FC<PezkuwiProviderProps> = ({ children }) =>
disconnectWallet,
createWallet,
importWallet,
deleteWallet,
getKeyPair,
signMessage,
error,
@@ -1,105 +0,0 @@
import React from 'react';
import { renderHook, act } from '@testing-library/react-native';
import { LanguageProvider, useLanguage } from '../LanguageContext';
// Mock the i18n module relative to src/
jest.mock('../../i18n', () => ({
saveLanguage: jest.fn(() => Promise.resolve()),
getCurrentLanguage: jest.fn(() => 'en'),
isRTL: jest.fn((code?: string) => {
const testCode = code || 'en';
return ['ckb', 'ar', 'fa'].includes(testCode);
}),
LANGUAGE_KEY: '@language',
languages: [
{ code: 'en', name: 'English', nativeName: 'English', rtl: false },
{ code: 'tr', name: 'Turkish', nativeName: 'Türkçe', rtl: false },
{ code: 'kmr', name: 'Kurdish Kurmanji', nativeName: 'Kurmancî', rtl: false },
{ code: 'ckb', name: 'Kurdish Sorani', nativeName: 'سۆرانی', rtl: true },
{ code: 'ar', name: 'Arabic', nativeName: 'العربية', rtl: true },
{ code: 'fa', name: 'Persian', nativeName: 'فارسی', rtl: true },
],
}));
// Wrapper for provider
const wrapper = ({ children }: { children: React.ReactNode }) => (
<LanguageProvider>{children}</LanguageProvider>
);
describe('LanguageContext', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should provide language context', () => {
const { result } = renderHook(() => useLanguage(), { wrapper });
expect(result.current).toBeDefined();
expect(result.current.currentLanguage).toBe('en');
});
it('should change language', async () => {
const { result } = renderHook(() => useLanguage(), { wrapper });
await act(async () => {
await result.current.changeLanguage('kmr');
});
expect(result.current.currentLanguage).toBe('kmr');
});
it('should provide available languages', () => {
const { result } = renderHook(() => useLanguage(), { wrapper });
expect(result.current.availableLanguages).toBeDefined();
expect(Array.isArray(result.current.availableLanguages)).toBe(true);
expect(result.current.availableLanguages.length).toBeGreaterThan(0);
});
it('should handle RTL languages', async () => {
const { result } = renderHook(() => useLanguage(), { wrapper });
await act(async () => {
await result.current.changeLanguage('ar');
});
expect(result.current.isRTL).toBe(true);
});
it('should handle LTR languages', async () => {
const { result } = renderHook(() => useLanguage(), { wrapper });
expect(result.current.isRTL).toBe(false);
});
it('should throw error when used outside provider', () => {
const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
expect(() => {
renderHook(() => useLanguage());
}).toThrow('useLanguage must be used within LanguageProvider');
spy.mockRestore();
});
it('should handle language change errors gracefully', async () => {
const { result } = renderHook(() => useLanguage(), { wrapper });
// changeLanguage should not throw but handle errors internally
await act(async () => {
await result.current.changeLanguage('en');
});
expect(result.current.currentLanguage).toBeDefined();
});
it('should persist language selection', async () => {
const { result } = renderHook(() => useLanguage(), { wrapper });
await act(async () => {
await result.current.changeLanguage('tr');
});
expect(result.current.currentLanguage).toBe('tr');
});
});
-22
View File
@@ -1,22 +0,0 @@
import i18n from '../index';
describe('i18n Configuration', () => {
it('should be initialized', () => {
expect(i18n).toBeDefined();
});
it('should have language property', () => {
expect(i18n.language).toBeDefined();
});
it('should have translation function', () => {
expect(i18n.t).toBeDefined();
expect(typeof i18n.t).toBe('function');
});
it('should support changeLanguage', async () => {
expect(i18n.changeLanguage).toBeDefined();
await i18n.changeLanguage('en');
expect(i18n.language).toBe('en');
});
});
-55
View File
@@ -1,55 +0,0 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// Import shared translations and language configurations
import {
comprehensiveTranslations as translations,
LANGUAGES,
DEFAULT_LANGUAGE,
isRTL as checkIsRTL,
} from '../../../shared/i18n';
// Language is set at build time via environment variable
const BUILD_LANGUAGE = (process.env.EXPO_PUBLIC_DEFAULT_LANGUAGE || DEFAULT_LANGUAGE) as string;
// Available languages (re-export for compatibility)
export const languages = LANGUAGES;
// Initialize i18n with build-time language only
const initializeI18n = () => {
if (__DEV__) {
console.log(`[i18n] Initializing with build language: ${BUILD_LANGUAGE}`);
}
i18n
.use(initReactI18next)
.init({
resources: {
// Only load the build-time language (reduces APK size)
[BUILD_LANGUAGE]: { translation: translations[BUILD_LANGUAGE as keyof typeof translations] },
},
lng: BUILD_LANGUAGE,
fallbackLng: BUILD_LANGUAGE,
compatibilityJSON: 'v3',
interpolation: {
escapeValue: false,
},
});
return BUILD_LANGUAGE;
};
// Get current language (always returns BUILD_LANGUAGE)
export const getCurrentLanguage = () => BUILD_LANGUAGE;
// Check if language is RTL
export const isRTL = (languageCode?: string) => {
const code = languageCode || BUILD_LANGUAGE;
return checkIsRTL(code);
};
// Initialize i18n automatically
initializeI18n();
export { initializeI18n, BUILD_LANGUAGE };
export default i18n;
-228
View File
@@ -1,228 +0,0 @@
{
"welcome": {
"title": "مرحباً بك في بيزكوي",
"subtitle": "بوابتك للحوكمة اللامركزية",
"selectLanguage": "اختر لغتك",
"continue": "متابعة"
},
"auth": {
"signIn": "تسجيل الدخول",
"signUp": "إنشاء حساب",
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"confirmPassword": "تأكيد كلمة المرور",
"forgotPassword": "نسيت كلمة المرور؟",
"noAccount": "ليس لديك حساب؟",
"haveAccount": "هل لديك حساب بالفعل؟",
"createAccount": "إنشاء حساب",
"welcomeBack": "مرحباً بعودتك!",
"getStarted": "ابدأ الآن",
"username": "اسم المستخدم",
"emailRequired": "البريد الإلكتروني مطلوب",
"passwordRequired": "كلمة المرور مطلوبة",
"usernameRequired": "اسم المستخدم مطلوب",
"signInSuccess": "تم تسجيل الدخول بنجاح!",
"signUpSuccess": "تم إنشاء الحساب بنجاح!",
"invalidCredentials": "بريد إلكتروني أو كلمة مرور غير صحيحة",
"passwordsMustMatch": "يجب أن تتطابق كلمات المرور"
},
"dashboard": {
"title": "لوحة التحكم",
"wallet": "المحفظة",
"staking": "التخزين",
"governance": "الحوكمة",
"dex": "البورصة",
"history": "السجل",
"settings": "الإعدادات",
"balance": "الرصيد",
"totalStaked": "إجمالي المخزن",
"rewards": "المكافآت",
"activeProposals": "المقترحات النشطة"
},
"wallet": {
"title": "المحفظة",
"connect": "ربط المحفظة",
"disconnect": "فصل الاتصال",
"address": "العنوان",
"balance": "الرصيد",
"send": "إرسال",
"receive": "استقبال",
"transaction": "المعاملة",
"history": "السجل"
},
"governance": {
"title": "الحوكمة",
"vote": "تصويت",
"voteFor": "تصويت نعم",
"voteAgainst": "تصويت لا",
"submitVote": "إرسال التصويت",
"votingSuccess": "تم تسجيل تصويتك!",
"selectCandidate": "اختر مرشحاً",
"multipleSelect": "يمكنك اختيار عدة مرشحين",
"singleSelect": "اختر مرشحاً واحداً",
"proposals": "المقترحات",
"elections": "الانتخابات",
"parliament": "البرلمان",
"activeElections": "الانتخابات النشطة",
"totalVotes": "إجمالي الأصوات",
"blocksLeft": "الكتل المتبقية",
"leading": "الرائد"
},
"citizenship": {
"title": "المواطنة",
"applyForCitizenship": "التقدم للحصول على الجنسية",
"newCitizen": "مواطن جديد",
"existingCitizen": "مواطن حالي",
"fullName": "الاسم الكامل",
"fatherName": "اسم الأب",
"motherName": "اسم الأم",
"tribe": "القبيلة",
"region": "المنطقة",
"profession": "المهنة",
"referralCode": "رمز الإحالة",
"submitApplication": "إرسال الطلب",
"applicationSuccess": "تم إرسال طلبك بنجاح!",
"applicationPending": "طلبك قيد المراجعة",
"citizenshipBenefits": "مزايا المواطنة",
"votingRights": "حق التصويت في الحوكمة",
"exclusiveAccess": "الوصول إلى الخدمات الحصرية",
"referralRewards": "برنامج مكافآت الإحالة",
"communityRecognition": "الاعتراف المجتمعي"
},
"p2p": {
"title": "تداول P2P",
"trade": "تداول",
"createOffer": "إنشاء عرض",
"buyToken": "شراء",
"sellToken": "بيع",
"amount": "الكمية",
"price": "السعر",
"total": "الإجمالي",
"initiateTrade": "بدء التداول",
"comingSoon": "قريباً",
"tradingWith": "التداول مع",
"available": "متاح",
"minOrder": "الحد الأدنى للطلب",
"maxOrder": "الحد الأقصى للطلب",
"youWillPay": "ستدفع",
"myOffers": "عروضي",
"noOffers": "لا توجد عروض",
"postAd": "نشر إعلان"
},
"forum": {
"title": "المنتدى",
"categories": "الفئات",
"threads": "المواضيع",
"replies": "الردود",
"views": "المشاهدات",
"lastActivity": "آخر نشاط",
"createThread": "إنشاء موضوع",
"generalDiscussion": "مناقشة عامة",
"noThreads": "لا توجد مواضيع",
"pinned": "مثبت",
"locked": "مقفل"
},
"referral": {
"title": "برنامج الإحالة",
"myReferralCode": "رمز الإحالة الخاص بي",
"totalReferrals": "إجمالي الإحالات",
"activeReferrals": "الإحالات النشطة",
"totalEarned": "إجمالي الأرباح",
"pendingRewards": "المكافآت المعلقة",
"shareCode": "مشاركة الرمز",
"copyCode": "نسخ الرمز",
"connectWallet": "ربط المحفظة",
"inviteFriends": "دعوة الأصدقاء",
"earnRewards": "احصل على المكافآت",
"codeCopied": "تم نسخ الرمز!"
},
"settings": {
"title": "الإعدادات",
"sections": {
"appearance": "المظهر",
"language": "اللغة",
"security": "الأمان",
"notifications": "الإشعارات",
"about": "حول"
},
"appearance": {
"darkMode": "الوضع الداكن",
"darkModeSubtitle": "التبديل بين السمة الفاتحة والداكنة",
"fontSize": "حجم الخط",
"fontSizeSubtitle": "الحالي: {{size}}",
"fontSizePrompt": "اختر حجم الخط المفضل لديك",
"small": "صغير",
"medium": "متوسط",
"large": "كبير"
},
"language": {
"title": "اللغة",
"changePrompt": "التبديل إلى {{language}}؟",
"changeSuccess": "تم تحديث اللغة بنجاح!"
},
"security": {
"biometric": "المصادقة البيومترية",
"biometricSubtitle": "استخدم بصمة الإصبع أو التعرف على الوجه",
"biometricPrompt": "هل تريد تفعيل المصادقة البيومترية؟",
"biometricEnabled": "تم تفعيل المصادقة البيومترية",
"twoFactor": "المصادقة الثنائية",
"twoFactorSubtitle": "أضف طبقة أمان إضافية",
"twoFactorPrompt": "المصادقة الثنائية تضيف طبقة أمان إضافية.",
"twoFactorSetup": "إعداد",
"changePassword": "تغيير كلمة المرور",
"changePasswordSubtitle": "تحديث كلمة مرور حسابك"
},
"notifications": {
"push": "الإشعارات الفورية",
"pushSubtitle": "تلقي التنبيهات والتحديثات",
"email": "إشعارات البريد الإلكتروني",
"emailSubtitle": "إدارة تفضيلات البريد الإلكتروني"
},
"about": {
"pezkuwi": "حول بيزكوي",
"pezkuwiSubtitle": "تعرف أكثر على كردستان الرقمية",
"pezkuwiMessage": "بيزكوي هو منصة بلوكتشين لامركزية لكردستان الرقمية.\n\nالإصدار: 1.0.0\n\nصُنع بـ ❤️",
"terms": "شروط الخدمة",
"privacy": "سياسة الخصوصية",
"contact": "اتصل بالدعم",
"contactSubtitle": "احصل على مساعدة من فريقنا",
"contactEmail": "البريد الإلكتروني: support@pezkuwichain.io"
},
"version": {
"app": "بيزكوي موبايل",
"number": "الإصدار 1.0.0",
"copyright": "© 2026 كردستان الرقمية"
},
"alerts": {
"comingSoon": "قريباً",
"darkModeMessage": "الوضع الداكن سيكون متاحاً قريباً",
"twoFactorMessage": "إعداد المصادقة الثنائية سيكون متاحاً قريباً",
"passwordMessage": "تغيير كلمة المرور سيكون متاحاً قريباً",
"emailMessage": "إعدادات البريد الإلكتروني ستكون متاحة قريباً",
"termsMessage": "شروط الخدمة ستكون متاحة قريباً",
"privacyMessage": "سياسة الخصوصية ستكون متاحة قريباً"
},
"common": {
"enable": "تفعيل",
"cancel": "إلغاء",
"confirm": "تأكيد",
"success": "نجح",
"error": "خطأ"
}
},
"common": {
"cancel": "إلغاء",
"confirm": "تأكيد",
"save": "حفظ",
"loading": "جاري التحميل...",
"error": "خطأ",
"success": "نجاح",
"retry": "إعادة المحاولة",
"close": "إغلاق",
"back": "رجوع",
"next": "التالي",
"submit": "إرسال",
"required": "مطلوب",
"optional": "اختياري"
}
}
-228
View File
@@ -1,228 +0,0 @@
{
"welcome": {
"title": "بەخێربێیت بۆ پێزکووی",
"subtitle": "دەرگای تۆ بۆ بەڕێوەبردنی نامەرکەزی",
"selectLanguage": "زمانەکەت هەڵبژێرە",
"continue": "بەردەوام بە"
},
"auth": {
"signIn": "چوونەژوورەوە",
"signUp": "تۆمارکردن",
"email": "ئیمەیڵ",
"password": "وشەی نهێنی",
"username": "ناوی بەکارهێنەر",
"confirmPassword": "پشتڕاستکردنەوەی وشەی نهێنی",
"forgotPassword": "وشەی نهێنیت لەبیرکردووە؟",
"noAccount": "هەژمارت نییە؟",
"haveAccount": "هەژمارت هەیە؟",
"createAccount": "دروستکردنی هەژمار",
"welcomeBack": "بەخێربێیتەوە!",
"getStarted": "دەست پێبکە",
"emailRequired": "ئیمەیڵ پێویستە",
"passwordRequired": "وشەی نهێنی پێویستە",
"usernameRequired": "ناوی بەکارهێنەر پێویستە",
"signInSuccess": "بەسەرکەوتووی چوویتە ژوورەوە!",
"signUpSuccess": "هەژمار بەسەرکەوتووی دروستکرا!",
"invalidCredentials": "ئیمەیڵ یان وشەی نهێنی هەڵەیە",
"passwordsMustMatch": "وشەی نهێنییەکان دەبێت وەک یەک بن"
},
"dashboard": {
"title": "سەرەتا",
"wallet": "جزدان",
"staking": "ستەیکینگ",
"governance": "بەڕێوەبردن",
"dex": "ئاڵوگۆڕ",
"history": "مێژوو",
"settings": "ڕێکخستنەکان",
"balance": "باڵانس",
"totalStaked": "کۆی گشتی",
"rewards": "خەڵات",
"activeProposals": "پێشنیارە چالاکەکان"
},
"governance": {
"title": "بەڕێوەبردن",
"vote": "دەنگدان",
"voteFor": "دەنگی بەڵێ",
"voteAgainst": "دەنگی نەخێر",
"submitVote": "ناردنی دەنگ",
"votingSuccess": "دەنگەکەت تۆمارکرا!",
"selectCandidate": "کاندیدێک هەڵبژێرە",
"multipleSelect": "دەتوانیت چەند کاندیدێک هەڵبژێریت",
"singleSelect": "تەنها کاندیدێک هەڵبژێرە",
"proposals": "پێشنیارەکان",
"elections": "هەڵبژاردنەکان",
"parliament": "پەرلەمان",
"activeElections": "هەڵبژاردنە چالاکەکان",
"totalVotes": "کۆی دەنگەکان",
"blocksLeft": "بلۆکی ماوە",
"leading": "پێشەنگ"
},
"citizenship": {
"title": "هاووڵاتیێتی",
"applyForCitizenship": "داوای هاووڵاتیێتی بکە",
"newCitizen": "هاووڵاتی نوێ",
"existingCitizen": "هاووڵاتی هەیە",
"fullName": "ناوی تەواو",
"fatherName": "ناوی باوک",
"motherName": "ناوی دایک",
"tribe": "عەشیرە",
"region": "هەرێم",
"profession": "پیشە",
"referralCode": "کۆدی ئاماژەپێدان",
"submitApplication": "ناردنی داواکاری",
"applicationSuccess": "داواکاریەکەت بەسەرکەوتووی نێردرا!",
"applicationPending": "داواکاریەکەت لە ژێر پێداچوونەوەدایە",
"citizenshipBenefits": "سوودەکانی هاووڵاتیێتی",
"votingRights": "مافی دەنگدان لە بەڕێوەبردندا",
"exclusiveAccess": "دەستگەیشتن بە خزمەتگوزارییە تایبەتەکان",
"referralRewards": "بەرنامەی خەڵاتی ئاماژەپێدان",
"communityRecognition": "ناسینەوەی کۆمەڵگە"
},
"p2p": {
"title": "بازرگانیی P2P",
"trade": "بازرگانی",
"createOffer": "دروستکردنی پێشنیار",
"buyToken": "کڕین",
"sellToken": "فرۆشتن",
"amount": "بڕ",
"price": "نرخ",
"total": "کۆ",
"initiateTrade": "دەستپێکردنی بازرگانی",
"comingSoon": "بەم زووانە",
"tradingWith": "بازرگانی لەگەڵ",
"available": "بەردەستە",
"minOrder": "کەمترین داواکاری",
"maxOrder": "زۆرترین داواکاری",
"youWillPay": "تۆ دەدەیت",
"myOffers": "پێشنیارەکانم",
"noOffers": "هیچ پێشنیارێک نییە",
"postAd": "ڕیکلام بکە"
},
"forum": {
"title": "فۆرەم",
"categories": "هاوپۆلەکان",
"threads": "بابەتەکان",
"replies": "وەڵامەکان",
"views": "بینینەکان",
"lastActivity": "دوا چالاکی",
"createThread": "دروستکردنی بابەت",
"generalDiscussion": "گفتوگۆی گشتی",
"noThreads": "هیچ بابەتێک نییە",
"pinned": "جێگیرکراو",
"locked": "داخراو"
},
"referral": {
"title": "بەرنامەی ئاماژەپێدان",
"myReferralCode": "کۆدی ئاماژەپێدانی من",
"totalReferrals": "کۆی ئاماژەپێدانەکان",
"activeReferrals": "ئاماژەپێدانە چالاکەکان",
"totalEarned": "کۆی قازانج",
"pendingRewards": "خەڵاتە چاوەڕوانکراوەکان",
"shareCode": "هاوبەشکردنی کۆد",
"copyCode": "کۆپیکردنی کۆد",
"connectWallet": "گرێدانی جزدان",
"inviteFriends": "بانگهێشتکردنی هاوڕێیان",
"earnRewards": "خەڵات بەدەستبهێنە",
"codeCopied": "کۆدەکە کۆپیکرا!"
},
"wallet": {
"title": "جزدان",
"connect": "گرێدانی جزدان",
"disconnect": "پچڕاندنی گرێدان",
"address": "ناونیشان",
"balance": "باڵانس",
"send": "ناردن",
"receive": "وەرگرتن",
"transaction": "مامەڵە",
"history": "مێژوو"
},
"settings": {
"title": "ڕێکخستنەکان",
"sections": {
"appearance": "دەرکەوتن",
"language": "زمان",
"security": "ئاسایش",
"notifications": "ئاگادارییەکان",
"about": "دەربارە"
},
"appearance": {
"darkMode": "دۆخی تاریک",
"darkModeSubtitle": "لە نێوان دۆخی ڕووناک و تاریک بگۆڕە",
"fontSize": "قەبارەی فۆنت",
"fontSizeSubtitle": "ئێستا: {{size}}",
"fontSizePrompt": "قەبارەی فۆنتی دڵخوازت هەڵبژێرە",
"small": "بچووک",
"medium": "مامناوەند",
"large": "گەورە"
},
"language": {
"title": "زمان",
"changePrompt": "بگۆڕدرێت بۆ {{language}}؟",
"changeSuccess": "زمان بە سەرکەوتوویی نوێکرایەوە!"
},
"security": {
"biometric": "ناسینەوەی بایۆمێتریک",
"biometricSubtitle": "پەنجە نوێن یان ناسینەوەی ڕوخسار بەکاربهێنە",
"biometricPrompt": "دەتەوێت ناسینەوەی بایۆمێتریک چالاک بکەیت؟",
"biometricEnabled": "ناسینەوەی بایۆمێتریک چالاککرا",
"twoFactor": "ناسینەوەی دوو-هەنگاوی",
"twoFactorSubtitle": "چینێکی ئاسایشی زیادە زیاد بکە",
"twoFactorPrompt": "ناسینەوەی دوو-هەنگاوی چینێکی ئاسایشی زیادە زیاد دەکات.",
"twoFactorSetup": "ڕێکبخە",
"changePassword": "وشەی نهێنی بگۆڕە",
"changePasswordSubtitle": "وشەی نهێنی هەژمارەکەت نوێ بکەرەوە"
},
"notifications": {
"push": "ئاگادارییە خێراکان",
"pushSubtitle": "ئاگاداری و نوێکارییەکان وەربگرە",
"email": "ئاگادارییەکانی ئیمەیل",
"emailSubtitle": "هەڵبژاردنەکانی ئیمەیل بەڕێوەببە"
},
"about": {
"pezkuwi": "دەربارەی پێزکووی",
"pezkuwiSubtitle": "زیاتر دەربارەی کوردستانی دیجیتاڵ بزانە",
"pezkuwiMessage": "پێزکووی پلاتفۆرمێکی بلۆکچەینی ناناوەندییە بۆ کوردستانی دیجیتاڵ.\n\nوەشان: 1.0.0\n\nبە ❤️ دروستکرا",
"terms": "مەرجەکانی خزمەتگوزاری",
"privacy": "سیاسەتی تایبەتمەندی",
"contact": "پەیوەندی پشتگیری",
"contactSubtitle": "یارمەتی لە تیمەکەمان وەربگرە",
"contactEmail": "ئیمەیل: support@pezkuwichain.io"
},
"version": {
"app": "پێزکووی مۆبایل",
"number": "وەشان 1.0.0",
"copyright": "© 2026 کوردستانی دیجیتاڵ"
},
"alerts": {
"comingSoon": "بەم زووانە",
"darkModeMessage": "دۆخی تاریک لە نوێکردنەوەی داهاتوودا بەردەست دەبێت",
"twoFactorMessage": "ڕێکخستنی 2FA بەم زووانە بەردەست دەبێت",
"passwordMessage": "گۆڕینی وشەی نهێنی بەم زووانە بەردەست دەبێت",
"emailMessage": "ڕێکخستنەکانی ئیمەیل بەم زووانە بەردەست دەبن",
"termsMessage": "مەرجەکانی خزمەتگوزاری بەم زووانە بەردەست دەبن",
"privacyMessage": "سیاسەتی تایبەتمەندی بەم زووانە بەردەست دەبێت"
},
"common": {
"enable": "چالاککردن",
"cancel": "هەڵوەشاندنەوە",
"confirm": "پشتڕاستکردنەوە",
"success": "سەرکەوتوو",
"error": "هەڵە"
}
},
"common": {
"cancel": "هەڵوەشاندنەوە",
"confirm": "پشتڕاستکردنەوە",
"save": "پاشەکەوتکردن",
"loading": "بارکردن...",
"error": "هەڵە",
"success": "سەرکەوتوو",
"retry": "هەوڵ بدەرەوە",
"close": "داخستن",
"back": "گەڕانەوە",
"next": "دواتر",
"submit": "ناردن",
"required": "پێویستە",
"optional": "ئیختیاری"
}
}
-228
View File
@@ -1,228 +0,0 @@
{
"welcome": {
"title": "Welcome to Pezkuwi",
"subtitle": "Your gateway to decentralized governance",
"selectLanguage": "Select Your Language",
"continue": "Continue"
},
"auth": {
"signIn": "Sign In",
"signUp": "Sign Up",
"email": "Email",
"password": "Password",
"username": "Username",
"confirmPassword": "Confirm Password",
"forgotPassword": "Forgot Password?",
"noAccount": "Don't have an account?",
"haveAccount": "Already have an account?",
"createAccount": "Create Account",
"welcomeBack": "Welcome Back!",
"getStarted": "Get Started",
"emailRequired": "Email is required",
"passwordRequired": "Password is required",
"usernameRequired": "Username is required",
"signInSuccess": "Signed in successfully!",
"signUpSuccess": "Account created successfully!",
"invalidCredentials": "Invalid email or password",
"passwordsMustMatch": "Passwords must match"
},
"dashboard": {
"title": "Dashboard",
"wallet": "Wallet",
"staking": "Staking",
"governance": "Governance",
"dex": "Exchange",
"history": "History",
"settings": "Settings",
"balance": "Balance",
"totalStaked": "Total Staked",
"rewards": "Rewards",
"activeProposals": "Active Proposals"
},
"governance": {
"title": "Governance",
"vote": "Vote",
"voteFor": "Vote FOR",
"voteAgainst": "Vote AGAINST",
"submitVote": "Submit Vote",
"votingSuccess": "Your vote has been recorded!",
"selectCandidate": "Select Candidate",
"multipleSelect": "You can select multiple candidates",
"singleSelect": "Select one candidate",
"proposals": "Proposals",
"elections": "Elections",
"parliament": "Parliament",
"activeElections": "Active Elections",
"totalVotes": "Total Votes",
"blocksLeft": "Blocks Left",
"leading": "Leading"
},
"citizenship": {
"title": "Citizenship",
"applyForCitizenship": "Apply for Citizenship",
"newCitizen": "New Citizen",
"existingCitizen": "Existing Citizen",
"fullName": "Full Name",
"fatherName": "Father's Name",
"motherName": "Mother's Name",
"tribe": "Tribe",
"region": "Region",
"profession": "Profession",
"referralCode": "Referral Code",
"submitApplication": "Submit Application",
"applicationSuccess": "Application submitted successfully!",
"applicationPending": "Your application is pending review",
"citizenshipBenefits": "Citizenship Benefits",
"votingRights": "Voting rights in governance",
"exclusiveAccess": "Access to exclusive services",
"referralRewards": "Referral rewards program",
"communityRecognition": "Community recognition"
},
"p2p": {
"title": "P2P Trading",
"trade": "Trade",
"createOffer": "Create Offer",
"buyToken": "Buy",
"sellToken": "Sell",
"amount": "Amount",
"price": "Price",
"total": "Total",
"initiateTrade": "Initiate Trade",
"comingSoon": "Coming Soon",
"tradingWith": "Trading with",
"available": "Available",
"minOrder": "Min Order",
"maxOrder": "Max Order",
"youWillPay": "You will pay",
"myOffers": "My Offers",
"noOffers": "No offers available",
"postAd": "Post Ad"
},
"forum": {
"title": "Forum",
"categories": "Categories",
"threads": "Threads",
"replies": "Replies",
"views": "Views",
"lastActivity": "Last Activity",
"createThread": "Create Thread",
"generalDiscussion": "General Discussion",
"noThreads": "No threads available",
"pinned": "Pinned",
"locked": "Locked"
},
"referral": {
"title": "Referral Program",
"myReferralCode": "My Referral Code",
"totalReferrals": "Total Referrals",
"activeReferrals": "Active Referrals",
"totalEarned": "Total Earned",
"pendingRewards": "Pending Rewards",
"shareCode": "Share Code",
"copyCode": "Copy Code",
"connectWallet": "Connect Wallet",
"inviteFriends": "Invite Friends",
"earnRewards": "Earn Rewards",
"codeCopied": "Code copied to clipboard!"
},
"wallet": {
"title": "Wallet",
"connect": "Connect Wallet",
"disconnect": "Disconnect",
"address": "Address",
"balance": "Balance",
"send": "Send",
"receive": "Receive",
"transaction": "Transaction",
"history": "History"
},
"settings": {
"title": "Settings",
"sections": {
"appearance": "APPEARANCE",
"language": "LANGUAGE",
"security": "SECURITY",
"notifications": "NOTIFICATIONS",
"about": "ABOUT"
},
"appearance": {
"darkMode": "Dark Mode",
"darkModeSubtitle": "Switch between light and dark theme",
"fontSize": "Font Size",
"fontSizeSubtitle": "Current: {{size}}",
"fontSizePrompt": "Choose your preferred font size",
"small": "Small",
"medium": "Medium",
"large": "Large"
},
"language": {
"title": "Language",
"changePrompt": "Switch to {{language}}?",
"changeSuccess": "Language updated successfully!"
},
"security": {
"biometric": "Biometric Authentication",
"biometricSubtitle": "Use fingerprint or face recognition",
"biometricPrompt": "Do you want to enable biometric authentication (fingerprint/face recognition)?",
"biometricEnabled": "Biometric authentication enabled",
"twoFactor": "Two-Factor Authentication",
"twoFactorSubtitle": "Add an extra layer of security",
"twoFactorPrompt": "Two-factor authentication adds an extra layer of security. You will need to set up an authenticator app.",
"twoFactorSetup": "Set Up",
"changePassword": "Change Password",
"changePasswordSubtitle": "Update your account password"
},
"notifications": {
"push": "Push Notifications",
"pushSubtitle": "Receive alerts and updates",
"email": "Email Notifications",
"emailSubtitle": "Manage email preferences"
},
"about": {
"pezkuwi": "About Pezkuwi",
"pezkuwiSubtitle": "Learn more about Digital Kurdistan",
"pezkuwiMessage": "Pezkuwi is a decentralized blockchain platform for Digital Kurdistan, enabling citizens to participate in governance, economy, and social life.\n\nVersion: 1.0.0\n\nBuilt with ❤️ by the Digital Kurdistan team",
"terms": "Terms of Service",
"privacy": "Privacy Policy",
"contact": "Contact Support",
"contactSubtitle": "Get help from our team",
"contactEmail": "Email: support@pezkuwichain.io"
},
"version": {
"app": "Pezkuwi Mobile",
"number": "Version 1.0.0",
"copyright": "© 2026 Digital Kurdistan"
},
"alerts": {
"comingSoon": "Coming Soon",
"darkModeMessage": "Dark mode will be available in the next update",
"twoFactorMessage": "2FA setup will be available soon",
"passwordMessage": "Password change will be available soon",
"emailMessage": "Email settings will be available soon",
"termsMessage": "Terms of Service will be available soon",
"privacyMessage": "Privacy Policy will be available soon"
},
"common": {
"enable": "Enable",
"cancel": "Cancel",
"confirm": "Confirm",
"success": "Success",
"error": "Error"
}
},
"common": {
"cancel": "Cancel",
"confirm": "Confirm",
"save": "Save",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"retry": "Retry",
"close": "Close",
"back": "Back",
"next": "Next",
"submit": "Submit",
"required": "Required",
"optional": "Optional"
}
}
-163
View File
@@ -1,163 +0,0 @@
{
"welcome": {
"title": "به پێزکووی خوش آمدید",
"subtitle": "دروازه شما به حکمرانی غیرمتمرکز",
"selectLanguage": "زبان خود را انتخاب کنید",
"continue": "ادامه"
},
"auth": {
"signIn": "ورود",
"signUp": "ثبت نام",
"email": "ایمیل",
"password": "رمز عبور",
"confirmPassword": "تأیید رمز عبور",
"forgotPassword": "رمز عبور را فراموش کرده‌اید؟",
"noAccount": "حساب کاربری ندارید؟",
"haveAccount": "قبلاً حساب کاربری دارید؟",
"createAccount": "ایجاد حساب",
"welcomeBack": "خوش آمدید!",
"getStarted": "شروع کنید",
"username": "نام کاربری",
"emailRequired": "ایمیل الزامی است",
"passwordRequired": "رمز عبور الزامی است",
"usernameRequired": "نام کاربری الزامی است",
"signInSuccess": "با موفقیت وارد شدید!",
"signUpSuccess": "حساب با موفقیت ایجاد شد!",
"invalidCredentials": "ایمیل یا رمز عبور نامعتبر",
"passwordsMustMatch": "رمزهای عبور باید یکسان باشند"
},
"dashboard": {
"title": "داشبورد",
"wallet": "کیف پول",
"staking": "سپرده‌گذاری",
"governance": "حکمرانی",
"dex": "صرافی",
"history": "تاریخچه",
"settings": "تنظیمات",
"balance": "موجودی",
"totalStaked": "کل سپرده",
"rewards": "پاداش‌ها",
"activeProposals": "پیشنهادات فعال"
},
"wallet": {
"title": "کیف پول",
"connect": "اتصال کیف پول",
"disconnect": "قطع اتصال",
"address": "آدرس",
"balance": "موجودی",
"send": "ارسال",
"receive": "دریافت",
"transaction": "تراکنش",
"history": "تاریخچه"
},
"governance": {
"title": "حکمرانی",
"vote": "رأی دادن",
"voteFor": "رأی موافق",
"voteAgainst": "رأی مخالف",
"submitVote": "ثبت رأی",
"votingSuccess": "رأی شما ثبت شد!",
"selectCandidate": "انتخاب کاندیدا",
"multipleSelect": "می‌توانید چند کاندیدا انتخاب کنید",
"singleSelect": "یک کاندیدا انتخاب کنید",
"proposals": "پیشنهادها",
"elections": "انتخابات",
"parliament": "پارلمان",
"activeElections": "انتخابات فعال",
"totalVotes": "مجموع آرا",
"blocksLeft": "بلوک‌های باقیمانده",
"leading": "پیشرو"
},
"citizenship": {
"title": "تابعیت",
"applyForCitizenship": "درخواست تابعیت",
"newCitizen": "شهروند جدید",
"existingCitizen": "شهروند موجود",
"fullName": "نام کامل",
"fatherName": "نام پدر",
"motherName": "نام مادر",
"tribe": "قبیله",
"region": "منطقه",
"profession": "شغل",
"referralCode": "کد معرف",
"submitApplication": "ارسال درخواست",
"applicationSuccess": "درخواست شما با موفقیت ارسال شد!",
"applicationPending": "درخواست شما در حال بررسی است",
"citizenshipBenefits": "مزایای تابعیت",
"votingRights": "حق رأی در حکمرانی",
"exclusiveAccess": "دسترسی به خدمات انحصاری",
"referralRewards": "برنامه پاداش معرفی",
"communityRecognition": "شناخت اجتماعی"
},
"p2p": {
"title": "تجارت P2P",
"trade": "معامله",
"createOffer": "ایجاد پیشنهاد",
"buyToken": "خرید",
"sellToken": "فروش",
"amount": "مقدار",
"price": "قیمت",
"total": "مجموع",
"initiateTrade": "شروع معامله",
"comingSoon": "به زودی",
"tradingWith": "معامله با",
"available": "موجود",
"minOrder": "حداقل سفارش",
"maxOrder": "حداکثر سفارش",
"youWillPay": "شما پرداخت خواهید کرد",
"myOffers": "پیشنهادهای من",
"noOffers": "پیشنهادی موجود نیست",
"postAd": "ثبت آگهی"
},
"forum": {
"title": "انجمن",
"categories": "دسته‌بندی‌ها",
"threads": "موضوعات",
"replies": "پاسخ‌ها",
"views": "بازدیدها",
"lastActivity": "آخرین فعالیت",
"createThread": "ایجاد موضوع",
"generalDiscussion": "بحث عمومی",
"noThreads": "موضوعی موجود نیست",
"pinned": "پین شده",
"locked": "قفل شده"
},
"referral": {
"title": "برنامه معرفی",
"myReferralCode": "کد معرف من",
"totalReferrals": "مجموع معرفی‌ها",
"activeReferrals": "معرفی‌های فعال",
"totalEarned": "مجموع درآمد",
"pendingRewards": "پاداش‌های در انتظار",
"shareCode": "اشتراک‌گذاری کد",
"copyCode": "کپی کد",
"connectWallet": "اتصال کیف پول",
"inviteFriends": "دعوت از دوستان",
"earnRewards": "کسب پاداش",
"codeCopied": "کد کپی شد!"
},
"settings": {
"title": "تنظیمات",
"language": "زبان",
"theme": "تم",
"notifications": "اعلان‌ها",
"security": "امنیت",
"about": "درباره",
"logout": "خروج"
},
"common": {
"cancel": "لغو",
"confirm": "تأیید",
"save": "ذخیره",
"loading": "در حال بارگذاری...",
"error": "خطا",
"success": "موفق",
"retry": "تلاش مجدد",
"close": "بستن",
"back": "بازگشت",
"next": "بعدی",
"submit": "ارسال",
"required": "الزامی",
"optional": "اختیاری"
}
}
-228
View File
@@ -1,228 +0,0 @@
{
"welcome": {
"title": "Bi xêr hatî Pezkuwî",
"subtitle": "Deriyê te yê bo rêveberiya desentralîze",
"selectLanguage": "Zimanê Xwe Hilbijêre",
"continue": "Bidomîne"
},
"auth": {
"signIn": "Têkeve",
"signUp": "Tomar bibe",
"email": "E-posta",
"password": "Şîfre",
"username": "Navê Bikarhêner",
"confirmPassword": "Şîfreyê Bipejirîne",
"forgotPassword": "Şîfreyê te ji bîr kiriye?",
"noAccount": "Hesabê te tune ye?",
"haveAccount": "Jixwe hesabê te heye?",
"createAccount": "Hesab Biafirîne",
"welcomeBack": "Dîsa bi xêr hatî!",
"getStarted": "Dest pê bike",
"emailRequired": "E-posta hewce ye",
"passwordRequired": "Şîfre hewce ye",
"usernameRequired": "Navê bikarhêner hewce ye",
"signInSuccess": "Bi serfirazî têkeve!",
"signUpSuccess": "Hesab bi serfirazî hate afirandin!",
"invalidCredentials": "E-posta an şîfreya nederbasdar",
"passwordsMustMatch": "Şîfre divê hevdu bigire"
},
"dashboard": {
"title": "Serûpel",
"wallet": "Berîk",
"staking": "Staking",
"governance": "Rêvebir",
"dex": "Guherîn",
"history": "Dîrok",
"settings": "Mîheng",
"balance": "Bilanço",
"totalStaked": "Hemû Stake",
"rewards": "Xelat",
"activeProposals": "Pêşniyarên Çalak"
},
"governance": {
"title": "Rêvebir",
"vote": "Deng bide",
"voteFor": "Dengê ERÊ",
"voteAgainst": "Dengê NA",
"submitVote": "Dengê Xwe Bişîne",
"votingSuccess": "Dengê we hate tomarkirin!",
"selectCandidate": "Namzed Hilbijêre",
"multipleSelect": "Hûn dikarin çend namzedan hilbijêrin",
"singleSelect": "Yek namzed hilbijêre",
"proposals": "Pêşniyar",
"elections": "Hilbijartin",
"parliament": "Parlamenter",
"activeElections": "Hilbijartinên Çalak",
"totalVotes": "Giştî Deng",
"blocksLeft": "Blokên Mayî",
"leading": "Pêşeng"
},
"citizenship": {
"title": "Hemwelatî",
"applyForCitizenship": "Ji bo Hemwelatî Serlêdan Bike",
"newCitizen": "Hemwelatîyê Nû",
"existingCitizen": "Hemwelatîya Heyî",
"fullName": "Nav û Paşnav",
"fatherName": "Navê Bav",
"motherName": "Navê Dê",
"tribe": "Eşîret",
"region": "Herêm",
"profession": "Pîşe",
"referralCode": "Koda Referansê",
"submitApplication": "Serldanê Bişîne",
"applicationSuccess": "Serlêdan bi serfirazî hate şandin!",
"applicationPending": "Serlêdana we di bin lêkolînê de ye",
"citizenshipBenefits": "Faydeyên Hemwelatî",
"votingRights": "Mafê dengdanê di rêvebiriyê de",
"exclusiveAccess": "Gihîştina karûbarên taybet",
"referralRewards": "Bernameya xelatên referansê",
"communityRecognition": "Naskirina civakê"
},
"p2p": {
"title": "Bazirganiya P2P",
"trade": "Bazirganî",
"createOffer": "Pêşniyar Biafirîne",
"buyToken": "Bikire",
"sellToken": "Bifiroşe",
"amount": "Mîqdar",
"price": "Biha",
"total": "Giştî",
"initiateTrade": "Bazirganiyê Destpêbike",
"comingSoon": "Pir nêzîk",
"tradingWith": "Bi re bazirganî",
"available": "Heyî",
"minOrder": "Daxwaza Kêm",
"maxOrder": "Daxwaza Zêde",
"youWillPay": "Hûn dê bidin",
"myOffers": "Pêşniyarên Min",
"noOffers": "Pêşniyar tunene",
"postAd": "Agahî Bide"
},
"forum": {
"title": "Forum",
"categories": "Kategoriyan",
"threads": "Mijar",
"replies": "Bersiv",
"views": "Nêrîn",
"lastActivity": "Çalakiya Dawî",
"createThread": "Mijar Biafirîne",
"generalDiscussion": "Gotûbêja Giştî",
"noThreads": "Mijar tunene",
"pinned": "Girêdayî",
"locked": "Girtî"
},
"referral": {
"title": "Bernameya Referansê",
"myReferralCode": "Koda Referansa Min",
"totalReferrals": "Giştî Referans",
"activeReferrals": "Referansên Çalak",
"totalEarned": "Giştî Qezenc",
"pendingRewards": "Xelatên Li Benda",
"shareCode": "Kodê Parve Bike",
"copyCode": "Kodê Kopî Bike",
"connectWallet": "Berîkê Girêbide",
"inviteFriends": "Hevalên Xwe Vexwîne",
"earnRewards": "Xelat Qezenc Bike",
"codeCopied": "Kod hate kopîkirin!"
},
"wallet": {
"title": "Berîk",
"connect": "Berîkê Girêde",
"disconnect": "Girêdanê Rake",
"address": "Navnîşan",
"balance": "Bilanço",
"send": "Bişîne",
"receive": "Bistîne",
"transaction": "Ragihandin",
"history": "Dîrok"
},
"settings": {
"title": "Mîhengên",
"sections": {
"appearance": "XUYANÎ",
"language": "ZIMAN",
"security": "EWLEHÎ",
"notifications": "AGAHDARÎ",
"about": "DER BARÊ"
},
"appearance": {
"darkMode": "Moda Tarî",
"darkModeSubtitle": "Di navbera moda ronî û tarî de biguherîne",
"fontSize": "Mezinahiya Nivîsê",
"fontSizeSubtitle": "Niha: {{size}}",
"fontSizePrompt": "Mezinahiya nivîsê ya xwe hilbijêre",
"small": "Piçûk",
"medium": "Nav",
"large": "Mezin"
},
"language": {
"title": "Ziman",
"changePrompt": "Biguherîne bo {{language}}?",
"changeSuccess": "Ziman bi serkeftî hate nûkirin!"
},
"security": {
"biometric": "Naskirina Bîyometrîk",
"biometricSubtitle": "Şopa tilî yan naskirina rû bikar bîne",
"biometricPrompt": "Hûn dixwazin naskirina bîyometrîk çalak bikin?",
"biometricEnabled": "Naskirina bîyometrîk çalak kirin",
"twoFactor": "Naskirina Du-Pîlan",
"twoFactorSubtitle": "Qateka ewlehiyê zêde bikin",
"twoFactorPrompt": "Naskirina du-pîlan qateka ewlehiyê zêde dike.",
"twoFactorSetup": "Saz Bike",
"changePassword": "Şîfreyê Biguherîne",
"changePasswordSubtitle": "Şîfreya hesabê xwe nû bike"
},
"notifications": {
"push": "Agahdariyên Zû",
"pushSubtitle": "Hişyarî û nûvekirinên werbigire",
"email": "Agahdariyên E-nameyê",
"emailSubtitle": "Vebijarkên e-nameyê birêve bibin"
},
"about": {
"pezkuwi": "Der barê Pezkuwi",
"pezkuwiSubtitle": "Zêdetir der barê Kurdistana Dîjîtal bizanin",
"pezkuwiMessage": "Pezkuwi platformek blockchain-ê ya bê-navend e ji bo Kurdistana Dîjîtal.\n\nGuherto: 1.0.0\n\nBi ❤️ hatiye çêkirin",
"terms": "Mercên Karûbarê",
"privacy": "Siyaseta Nepenîtiyê",
"contact": "Têkiliya Piştgiriyê",
"contactSubtitle": "Ji tîma me alîkarî bistînin",
"contactEmail": "E-name: support@pezkuwichain.io"
},
"version": {
"app": "Pezkuwi Mobîl",
"number": "Guherto 1.0.0",
"copyright": "© 2026 Kurdistana Dîjîtal"
},
"alerts": {
"comingSoon": "Zû tê",
"darkModeMessage": "Moda tarî di nûvekirina pêş de berdest dibe",
"twoFactorMessage": "Sazkirina 2FA zû berdest dibe",
"passwordMessage": "Guherandina şîfreyê zû berdest dibe",
"emailMessage": "Mîhengên e-nameyê zû berdest dibin",
"termsMessage": "Mercên karûbarê zû berdest dibin",
"privacyMessage": "Siyaseta nepenîtiyê zû berdest dibe"
},
"common": {
"enable": "Çalak Bike",
"cancel": "Betal Bike",
"confirm": "Pejirandin",
"success": "Serkeft",
"error": "Çewtî"
}
},
"common": {
"cancel": "Betal bike",
"confirm": "Bipejirîne",
"save": "Tomar bike",
"loading": "Tê barkirin...",
"error": "Çewtî",
"success": "Serkeftin",
"retry": "Dîsa biceribîne",
"close": "Bigire",
"back": "Paş",
"next": "Pêş",
"submit": "Bişîne",
"required": "Hewce ye",
"optional": "Bijarte"
}
}
-228
View File
@@ -1,228 +0,0 @@
{
"welcome": {
"title": "Pezkuwi'ye Hoş Geldiniz",
"subtitle": "Merkezi olmayan yönetim kapınız",
"selectLanguage": "Dilinizi Seçin",
"continue": "Devam Et"
},
"auth": {
"signIn": "Giriş Yap",
"signUp": "Kayıt Ol",
"email": "E-posta",
"password": "Şifre",
"username": "Kullanıcı Adı",
"confirmPassword": "Şifreyi Onayla",
"forgotPassword": "Şifremi Unuttum",
"noAccount": "Hesabınız yok mu?",
"haveAccount": "Zaten hesabınız var mı?",
"createAccount": "Hesap Oluştur",
"welcomeBack": "Tekrar Hoş Geldiniz!",
"getStarted": "Başlayın",
"emailRequired": "E-posta gereklidir",
"passwordRequired": "Şifre gereklidir",
"usernameRequired": "Kullanıcı adı gereklidir",
"signInSuccess": "Başarıyla giriş yapıldı!",
"signUpSuccess": "Hesap başarıyla oluşturuldu!",
"invalidCredentials": "Geçersiz e-posta veya şifre",
"passwordsMustMatch": "Şifreler eşleşmelidir"
},
"dashboard": {
"title": "Ana Sayfa",
"wallet": "Cüzdan",
"staking": "Stake Etme",
"governance": "Yönetişim",
"dex": "Borsa",
"history": "Geçmiş",
"settings": "Ayarlar",
"balance": "Bakiye",
"totalStaked": "Toplam Stake",
"rewards": "Ödüller",
"activeProposals": "Aktif Teklifler"
},
"governance": {
"title": "Yönetişim",
"vote": "Oy Ver",
"voteFor": "EVET Oyu",
"voteAgainst": "HAYIR Oyu",
"submitVote": "Oyu Gönder",
"votingSuccess": "Oyunuz kaydedildi!",
"selectCandidate": "Aday Seç",
"multipleSelect": "Birden fazla aday seçebilirsiniz",
"singleSelect": "Bir aday seçin",
"proposals": "Teklifler",
"elections": "Seçimler",
"parliament": "Meclis",
"activeElections": "Aktif Seçimler",
"totalVotes": "Toplam Oylar",
"blocksLeft": "Kalan Bloklar",
"leading": "Önde Giden"
},
"citizenship": {
"title": "Vatandaşlık",
"applyForCitizenship": "Vatandaşlığa Başvur",
"newCitizen": "Yeni Vatandaş",
"existingCitizen": "Mevcut Vatandaş",
"fullName": "Ad Soyad",
"fatherName": "Baba Adı",
"motherName": "Anne Adı",
"tribe": "Aşiret",
"region": "Bölge",
"profession": "Meslek",
"referralCode": "Referans Kodu",
"submitApplication": "Başvuruyu Gönder",
"applicationSuccess": "Başvuru başarıyla gönderildi!",
"applicationPending": "Başvurunuz inceleniyor",
"citizenshipBenefits": "Vatandaşlık Avantajları",
"votingRights": "Yönetişimde oy hakkı",
"exclusiveAccess": "Özel hizmetlere erişim",
"referralRewards": "Referans ödül programı",
"communityRecognition": "Topluluk tanınması"
},
"p2p": {
"title": "P2P Ticaret",
"trade": "Ticaret",
"createOffer": "Teklif Oluştur",
"buyToken": "Al",
"sellToken": "Sat",
"amount": "Miktar",
"price": "Fiyat",
"total": "Toplam",
"initiateTrade": "Ticareti Başlat",
"comingSoon": "Yakında",
"tradingWith": "İle ticaret",
"available": "Mevcut",
"minOrder": "Min Sipariş",
"maxOrder": "Max Sipariş",
"youWillPay": "Ödeyeceğiniz",
"myOffers": "Tekliflerim",
"noOffers": "Teklif bulunmuyor",
"postAd": "İlan Ver"
},
"forum": {
"title": "Forum",
"categories": "Kategoriler",
"threads": "Konular",
"replies": "Cevaplar",
"views": "Görüntüleme",
"lastActivity": "Son Aktivite",
"createThread": "Konu Oluştur",
"generalDiscussion": "Genel Tartışma",
"noThreads": "Konu bulunmuyor",
"pinned": "Sabitlenmiş",
"locked": "Kilitli"
},
"referral": {
"title": "Referans Programı",
"myReferralCode": "Referans Kodum",
"totalReferrals": "Toplam Referanslar",
"activeReferrals": "Aktif Referanslar",
"totalEarned": "Toplam Kazanç",
"pendingRewards": "Bekleyen Ödüller",
"shareCode": "Kodu Paylaş",
"copyCode": "Kodu Kopyala",
"connectWallet": "Cüzdan Bağla",
"inviteFriends": "Arkadaşlarını Davet Et",
"earnRewards": "Ödül Kazan",
"codeCopied": "Kod panoya kopyalandı!"
},
"wallet": {
"title": "Cüzdan",
"connect": "Cüzdan Bağla",
"disconnect": "Bağlantıyı Kes",
"address": "Adres",
"balance": "Bakiye",
"send": "Gönder",
"receive": "Al",
"transaction": "İşlem",
"history": "Geçmiş"
},
"settings": {
"title": "Ayarlar",
"sections": {
"appearance": "GÖRÜNÜM",
"language": "DİL",
"security": "GÜVENLİK",
"notifications": "BİLDİRİMLER",
"about": "HAKKINDA"
},
"appearance": {
"darkMode": "Karanlık Mod",
"darkModeSubtitle": "Açık ve karanlık tema arasında geçiş yapın",
"fontSize": "Yazı Boyutu",
"fontSizeSubtitle": "Şu anki: {{size}}",
"fontSizePrompt": "Tercih ettiğiniz yazı boyutunu seçin",
"small": "Küçük",
"medium": "Orta",
"large": "Büyük"
},
"language": {
"title": "Dil",
"changePrompt": "{{language}} diline geçilsin mi?",
"changeSuccess": "Dil başarıyla güncellendi!"
},
"security": {
"biometric": "Biyometrik Kimlik Doğrulama",
"biometricSubtitle": "Parmak izi veya yüz tanıma kullanın",
"biometricPrompt": "Biyometrik kimlik doğrulamayı (parmak izi/yüz tanıma) etkinleştirmek istiyor musunuz?",
"biometricEnabled": "Biyometrik kimlik doğrulama etkinleştirildi",
"twoFactor": "İki Faktörlü Kimlik Doğrulama",
"twoFactorSubtitle": "Ekstra bir güvenlik katmanı ekleyin",
"twoFactorPrompt": "İki faktörlü kimlik doğrulama ekstra bir güvenlik katmanı ekler. Bir kimlik doğrulayıcı uygulama kurmanız gerekecek.",
"twoFactorSetup": "Kur",
"changePassword": "Şifre Değiştir",
"changePasswordSubtitle": "Hesap şifrenizi güncelleyin"
},
"notifications": {
"push": "Anlık Bildirimler",
"pushSubtitle": "Uyarılar ve güncellemeler alın",
"email": "E-posta Bildirimleri",
"emailSubtitle": "E-posta tercihlerini yönetin"
},
"about": {
"pezkuwi": "Pezkuwi Hakkında",
"pezkuwiSubtitle": "Dijital Kürdistan hakkında daha fazla bilgi edinin",
"pezkuwiMessage": "Pezkuwi, vatandaşların yönetişim, ekonomi ve sosyal yaşama katılımını sağlayan Dijital Kürdistan için merkezi olmayan bir blockchain platformudur.\n\nVersiyon: 1.0.0\n\nDijital Kürdistan ekibi tarafından ❤️ ile yapıldı",
"terms": "Hizmet Şartları",
"privacy": "Gizlilik Politikası",
"contact": "Destek İletişim",
"contactSubtitle": "Ekibimizden yardım alın",
"contactEmail": "E-posta: support@pezkuwichain.io"
},
"version": {
"app": "Pezkuwi Mobil",
"number": "Versiyon 1.0.0",
"copyright": "© 2026 Dijital Kürdistan"
},
"alerts": {
"comingSoon": "Yakında",
"darkModeMessage": "Karanlık mod bir sonraki güncellemede kullanılabilir olacak",
"twoFactorMessage": "2FA kurulumu yakında kullanılabilir olacak",
"passwordMessage": "Şifre değiştirme yakında kullanılabilir olacak",
"emailMessage": "E-posta ayarları yakında kullanılabilir olacak",
"termsMessage": "Hizmet Şartları yakında kullanılabilir olacak",
"privacyMessage": "Gizlilik Politikası yakında kullanılabilir olacak"
},
"common": {
"enable": "Etkinleştir",
"cancel": "İptal",
"confirm": "Onayla",
"success": "Başarılı",
"error": "Hata"
}
},
"common": {
"cancel": "İptal",
"confirm": "Onayla",
"save": "Kaydet",
"loading": "Yükleniyor...",
"error": "Hata",
"success": "Başarılı",
"retry": "Tekrar Dene",
"close": "Kapat",
"back": "Geri",
"next": "İleri",
"submit": "Gönder",
"required": "Gerekli",
"optional": "İsteğe Bağlı"
}
}
+36
View File
@@ -15,6 +15,10 @@ import SettingsScreen from '../screens/SettingsScreen';
import BeCitizenChoiceScreen from '../screens/BeCitizenChoiceScreen';
import BeCitizenApplyScreen from '../screens/BeCitizenApplyScreen';
import BeCitizenClaimScreen from '../screens/BeCitizenClaimScreen';
import EditProfileScreen from '../screens/EditProfileScreen';
import WalletScreen from '../screens/WalletScreen';
import WalletSetupScreen from '../screens/WalletSetupScreen';
import SwapScreen from '../screens/SwapScreen';
export type RootStackParamList = {
Welcome: undefined;
@@ -22,6 +26,10 @@ export type RootStackParamList = {
Auth: undefined;
MainApp: undefined;
Settings: undefined;
EditProfile: undefined;
Wallet: undefined;
WalletSetup: undefined;
Swap: undefined;
BeCitizenChoice: undefined;
BeCitizenApply: undefined;
BeCitizenClaim: undefined;
@@ -119,6 +127,34 @@ const AppNavigator: React.FC = () => {
headerBackTitle: 'Back',
}}
/>
<Stack.Screen
name="EditProfile"
component={EditProfileScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="Wallet"
component={WalletScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="WalletSetup"
component={WalletSetupScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="Swap"
component={SwapScreen}
options={{
headerShown: false,
}}
/>
</>
)}
</Stack.Navigator>
+30 -32
View File
@@ -14,12 +14,10 @@ import {
Image,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { useAuth } from '../contexts/AuthContext';
import { KurdistanColors } from '../theme/colors';
const AuthScreen: React.FC = () => {
const { t } = useTranslation();
const { signIn, signUp } = useAuth();
// Tab state
@@ -47,7 +45,7 @@ const AuthScreen: React.FC = () => {
setError('');
if (!loginEmail || !loginPassword) {
setError(t('auth.fillAllFields', 'Please fill in all fields'));
setError('Please fill in all fields');
return;
}
@@ -58,13 +56,13 @@ const AuthScreen: React.FC = () => {
if (signInError) {
if (signInError.message?.includes('Invalid login credentials')) {
setError(t('auth.invalidCredentials', 'Email or password is incorrect'));
setError('Email or password is incorrect');
} else {
setError(signInError.message || t('auth.loginFailed', 'Login failed'));
setError(signInError.message || 'Login failed');
}
}
} catch (err) {
setError(t('auth.loginFailed', 'Login failed. Please try again.'));
setError('Login failed. Please try again.');
if (__DEV__) console.error('Sign in error:', err);
} finally {
setLoading(false);
@@ -75,17 +73,17 @@ const AuthScreen: React.FC = () => {
setError('');
if (!signupName || !signupEmail || !signupPassword || !signupConfirmPassword) {
setError(t('auth.fillAllFields', 'Please fill in all required fields'));
setError('Please fill in all required fields');
return;
}
if (signupPassword !== signupConfirmPassword) {
setError(t('auth.passwordsDoNotMatch', 'Passwords do not match'));
setError('Passwords do not match');
return;
}
if (signupPassword.length < 8) {
setError(t('auth.passwordTooShort', 'Password must be at least 8 characters'));
setError('Password must be at least 8 characters');
return;
}
@@ -100,10 +98,10 @@ const AuthScreen: React.FC = () => {
);
if (signUpError) {
setError(signUpError.message || t('auth.signupFailed', 'Sign up failed'));
setError(signUpError.message || 'Sign up failed');
}
} catch (err) {
setError(t('auth.signupFailed', 'Sign up failed. Please try again.'));
setError('Sign up failed. Please try again.');
if (__DEV__) console.error('Sign up error:', err);
} finally {
setLoading(false);
@@ -144,7 +142,7 @@ const AuthScreen: React.FC = () => {
</View>
<Text style={styles.brandTitle}>PezkuwiChain</Text>
<Text style={styles.subtitle}>
{t('login.subtitle', 'Access your governance account')}
Access your governance account
</Text>
</View>
@@ -158,7 +156,7 @@ const AuthScreen: React.FC = () => {
}}
>
<Text style={[styles.tabText, activeTab === 'signin' && styles.tabTextActive]}>
{t('login.signin', 'Sign In')}
Sign In
</Text>
</TouchableOpacity>
<TouchableOpacity
@@ -169,7 +167,7 @@ const AuthScreen: React.FC = () => {
}}
>
<Text style={[styles.tabText, activeTab === 'signup' && styles.tabTextActive]}>
{t('login.signup', 'Sign Up')}
Sign Up
</Text>
</TouchableOpacity>
</View>
@@ -178,7 +176,7 @@ const AuthScreen: React.FC = () => {
{activeTab === 'signin' && (
<View style={styles.form}>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('login.email', 'Email')}</Text>
<Text style={styles.label}>Email</Text>
<View style={styles.inputContainer}>
<Text style={styles.inputIcon}></Text>
<TextInput
@@ -195,7 +193,7 @@ const AuthScreen: React.FC = () => {
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('login.password', 'Password')}</Text>
<Text style={styles.label}>Password</Text>
<View style={styles.inputContainer}>
<Text style={styles.inputIcon}>🔒</Text>
<TextInput
@@ -225,12 +223,12 @@ const AuthScreen: React.FC = () => {
{rememberMe && <Text style={styles.checkmark}></Text>}
</View>
<Text style={styles.checkboxLabel}>
{t('login.rememberMe', 'Remember me')}
Remember me
</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.linkText}>
{t('login.forgotPassword', 'Forgot password?')}
Forgot password?
</Text>
</TouchableOpacity>
</View>
@@ -251,7 +249,7 @@ const AuthScreen: React.FC = () => {
<ActivityIndicator color="#FFFFFF" />
) : (
<Text style={styles.primaryButtonText}>
{t('login.signin', 'Sign In')}
Sign In
</Text>
)}
</TouchableOpacity>
@@ -262,7 +260,7 @@ const AuthScreen: React.FC = () => {
{activeTab === 'signup' && (
<View style={styles.form}>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('login.fullName', 'Full Name')}</Text>
<Text style={styles.label}>Full Name</Text>
<View style={styles.inputContainer}>
<Text style={styles.inputIcon}>👤</Text>
<TextInput
@@ -277,7 +275,7 @@ const AuthScreen: React.FC = () => {
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('login.email', 'Email')}</Text>
<Text style={styles.label}>Email</Text>
<View style={styles.inputContainer}>
<Text style={styles.inputIcon}></Text>
<TextInput
@@ -294,7 +292,7 @@ const AuthScreen: React.FC = () => {
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('login.password', 'Password')}</Text>
<Text style={styles.label}>Password</Text>
<View style={styles.inputContainer}>
<Text style={styles.inputIcon}>🔒</Text>
<TextInput
@@ -316,7 +314,7 @@ const AuthScreen: React.FC = () => {
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('login.confirmPassword', 'Confirm Password')}</Text>
<Text style={styles.label}>Confirm Password</Text>
<View style={styles.inputContainer}>
<Text style={styles.inputIcon}>🔒</Text>
<TextInput
@@ -333,16 +331,16 @@ const AuthScreen: React.FC = () => {
<View style={styles.inputGroup}>
<Text style={styles.label}>
{t('login.referralCode', 'Referral Code')}{' '}
Referral Code{' '}
<Text style={styles.optionalText}>
({t('login.optional', 'Optional')})
(Optional)
</Text>
</Text>
<View style={styles.inputContainer}>
<Text style={styles.inputIcon}>👥</Text>
<TextInput
style={styles.input}
placeholder={t('login.enterReferralCode', 'Referral code (optional)')}
placeholder="Referral code (optional)"
placeholderTextColor="#9CA3AF"
value={signupReferralCode}
onChangeText={setSignupReferralCode}
@@ -350,7 +348,7 @@ const AuthScreen: React.FC = () => {
/>
</View>
<Text style={styles.hintText}>
{t('login.referralDescription', 'If someone referred you, enter their code here')}
If someone referred you, enter their code here
</Text>
</View>
@@ -370,7 +368,7 @@ const AuthScreen: React.FC = () => {
<ActivityIndicator color="#FFFFFF" />
) : (
<Text style={styles.primaryButtonText}>
{t('login.createAccount', 'Create Account')}
Create Account
</Text>
)}
</TouchableOpacity>
@@ -380,15 +378,15 @@ const AuthScreen: React.FC = () => {
{/* Footer */}
<View style={styles.footer}>
<Text style={styles.footerText}>
{t('login.terms', 'By continuing, you agree to our')}{' '}
By continuing, you agree to our{' '}
</Text>
<View style={styles.footerLinks}>
<Text style={styles.footerLink}>
{t('login.termsOfService', 'Terms of Service')}
Terms of Service
</Text>
<Text style={styles.footerText}> {t('login.and', 'and')} </Text>
<Text style={styles.footerText}> and </Text>
<Text style={styles.footerLink}>
{t('login.privacyPolicy', 'Privacy Policy')}
Privacy Policy
</Text>
</View>
</View>
@@ -12,7 +12,6 @@ import {
ActivityIndicator,
Modal,
} from 'react-native';
import { useTranslation } from 'react-i18next';
import { useNavigation } from '@react-navigation/native';
import { usePezkuwi } from '../contexts/PezkuwiContext';
import {
@@ -97,7 +96,6 @@ const CustomPicker: React.FC<{
};
const BeCitizenApplyScreen: React.FC = () => {
const { t } = useTranslation();
const navigation = useNavigation();
const { api, selectedAccount } = usePezkuwi();
const [isSubmitting, setIsSubmitting] = useState(false);
@@ -9,7 +9,6 @@ import {
StatusBar,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { useNavigation } from '@react-navigation/native';
import { KurdistanColors } from '../theme/colors';
import type { NavigationProp } from '@react-navigation/native';
@@ -21,7 +20,6 @@ type RootStackParamList = {
};
const BeCitizenChoiceScreen: React.FC = () => {
const { t } = useTranslation();
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
return (
@@ -10,14 +10,12 @@ import {
Alert,
ActivityIndicator,
} from 'react-native';
import { useTranslation } from 'react-i18next';
import { useNavigation } from '@react-navigation/native';
import { usePezkuwi } from '../contexts/PezkuwiContext';
import { getCitizenshipStatus } from '@pezkuwi/lib/citizenship-workflow';
import { KurdistanColors } from '../theme/colors';
const BeCitizenClaimScreen: React.FC = () => {
const { t } = useTranslation();
const navigation = useNavigation();
const { api, selectedAccount } = usePezkuwi();
const [isSubmitting, setIsSubmitting] = useState(false);
-2
View File
@@ -12,7 +12,6 @@ import {
ActivityIndicator,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { usePezkuwi } from '../contexts/PezkuwiContext';
import {
submitKycApplication,
@@ -22,7 +21,6 @@ import {
import { KurdistanColors } from '../theme/colors';
const BeCitizenScreen: React.FC = () => {
const { t: _t } = useTranslation();
const { api, selectedAccount } = usePezkuwi();
const [_isExistingCitizen, _setIsExistingCitizen] = useState(false);
const [currentStep, setCurrentStep] = useState<'choice' | 'new' | 'existing'>('choice');
+4 -19
View File
@@ -14,7 +14,6 @@ import {
ActivityIndicator,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { useNavigation } from '@react-navigation/native';
import type { NavigationProp } from '@react-navigation/native';
import type { BottomTabParamList } from '../navigation/BottomTabNavigator';
@@ -82,7 +81,6 @@ const getEmojiFromAvatarId = (avatarId: string): string => {
interface DashboardScreenProps {}
const DashboardScreen: React.FC<DashboardScreenProps> = () => {
const { t } = useTranslation();
const navigation = useNavigation<NavigationProp<BottomTabParamList & RootStackParamList>>();
const { user } = useAuth();
const { api, isApiReady, selectedAccount } = usePezkuwi();
@@ -171,8 +169,8 @@ const DashboardScreen: React.FC<DashboardScreenProps> = () => {
const showComingSoon = (featureName: string) => {
Alert.alert(
t('settingsScreen.comingSoon'),
`${featureName} ${t('settingsScreen.comingSoonMessage')}`,
'Coming Soon',
`${featureName} will be available soon!`,
[{ text: 'OK' }]
);
};
@@ -431,21 +429,8 @@ const DashboardScreen: React.FC<DashboardScreenProps> = () => {
</TouchableOpacity>
</View>
<View style={styles.appsGrid}>
{/* Wallet Visitors - Everyone can use */}
{renderAppIcon('Wallet Visitors', '👁️', () => showComingSoon('Wallet Visitors'), true)}
{/* Wallet Welati - Only Citizens can use */}
{renderAppIcon('Wallet Welati', '🏛️', () => {
if (tikis.includes('Citizen') || tikis.includes('Welati')) {
showComingSoon('Wallet Welati');
} else {
Alert.alert(
'Citizens Only',
'Wallet Welati is only available to Pezkuwi citizens. Please apply for citizenship first.',
[{ text: 'OK' }]
);
}
}, true, !tikis.includes('Citizen') && !tikis.includes('Welati'))}
{/* Wallet - Navigate to WalletScreen */}
{renderAppIcon('Wallet', '👛', () => navigation.navigate('Wallet'), true)}
{renderAppIcon('Bank', qaBank, () => showComingSoon('Bank'), false, true)}
{renderAppIcon('Exchange', qaExchange, () => showComingSoon('Swap'), false)}
+450
View File
@@ -0,0 +1,450 @@
import React, { useState, useEffect } from 'react';
import {
View,
Text,
TouchableOpacity,
StyleSheet,
SafeAreaView,
ScrollView,
TextInput,
ActivityIndicator,
Alert,
Platform,
KeyboardAvoidingView,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { useAuth } from '../contexts/AuthContext';
import { useTheme } from '../contexts/ThemeContext';
import { KurdistanColors } from '../theme/colors';
import { supabase } from '../lib/supabase';
import AvatarPickerModal from '../components/AvatarPickerModal';
// Cross-platform alert helper
const showAlert = (title: string, message: string, buttons?: Array<{text: string; onPress?: () => void; style?: string}>) => {
if (Platform.OS === 'web') {
if (buttons && buttons.length > 1) {
const result = window.confirm(`${title}\n\n${message}`);
if (result && buttons[1]?.onPress) {
buttons[1].onPress();
} else if (!result && buttons[0]?.onPress) {
buttons[0].onPress();
}
} else {
window.alert(`${title}\n\n${message}`);
if (buttons?.[0]?.onPress) buttons[0].onPress();
}
} else {
Alert.alert(title, message, buttons as any);
}
};
// Avatar pool matching AvatarPickerModal
const AVATAR_POOL = [
{ id: 'avatar1', emoji: '👨🏻' },
{ id: 'avatar2', emoji: '👨🏼' },
{ id: 'avatar3', emoji: '👨🏽' },
{ id: 'avatar4', emoji: '👨🏾' },
{ id: 'avatar5', emoji: '👩🏻' },
{ id: 'avatar6', emoji: '👩🏼' },
{ id: 'avatar7', emoji: '👩🏽' },
{ id: 'avatar8', emoji: '👩🏾' },
{ id: 'avatar9', emoji: '🧔🏻' },
{ id: 'avatar10', emoji: '🧔🏼' },
{ id: 'avatar11', emoji: '🧔🏽' },
{ id: 'avatar12', emoji: '🧔🏾' },
{ id: 'avatar13', emoji: '👳🏻‍♂️' },
{ id: 'avatar14', emoji: '👳🏼‍♂️' },
{ id: 'avatar15', emoji: '👳🏽‍♂️' },
{ id: 'avatar16', emoji: '🧕🏻' },
{ id: 'avatar17', emoji: '🧕🏼' },
{ id: 'avatar18', emoji: '🧕🏽' },
{ id: 'avatar19', emoji: '👴🏻' },
{ id: 'avatar20', emoji: '👴🏼' },
{ id: 'avatar21', emoji: '👵🏻' },
{ id: 'avatar22', emoji: '👵🏼' },
{ id: 'avatar23', emoji: '👦🏻' },
{ id: 'avatar24', emoji: '👦🏼' },
{ id: 'avatar25', emoji: '👧🏻' },
{ id: 'avatar26', emoji: '👧🏼' },
];
const getEmojiFromAvatarId = (avatarId: string): string => {
const avatar = AVATAR_POOL.find(a => a.id === avatarId);
return avatar ? avatar.emoji : '👤';
};
const EditProfileScreen: React.FC = () => {
const navigation = useNavigation();
const { user } = useAuth();
const { isDarkMode, colors, fontScale } = useTheme();
const [fullName, setFullName] = useState('');
const [avatarUrl, setAvatarUrl] = useState<string | null>(null);
const [originalName, setOriginalName] = useState('');
const [originalAvatar, setOriginalAvatar] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [avatarModalVisible, setAvatarModalVisible] = useState(false);
useEffect(() => {
fetchProfile();
}, []);
const fetchProfile = async () => {
if (!user) {
setLoading(false);
return;
}
try {
const { data, error } = await supabase
.from('profiles')
.select('full_name, avatar_url')
.eq('id', user.id)
.single();
if (error) throw error;
setFullName(data?.full_name || '');
setAvatarUrl(data?.avatar_url || null);
setOriginalName(data?.full_name || '');
setOriginalAvatar(data?.avatar_url || null);
} catch (error) {
if (__DEV__) console.error('Error fetching profile:', error);
showAlert('Error', 'Failed to load profile data');
} finally {
setLoading(false);
}
};
const hasChanges = () => {
return fullName !== originalName || avatarUrl !== originalAvatar;
};
const handleSave = async () => {
if (!user) return;
if (!hasChanges()) {
navigation.goBack();
return;
}
setSaving(true);
try {
const updates: { full_name?: string | null; avatar_url?: string | null } = {};
if (fullName !== originalName) {
updates.full_name = fullName.trim() || null;
}
if (avatarUrl !== originalAvatar) {
updates.avatar_url = avatarUrl;
}
const { error } = await supabase
.from('profiles')
.update(updates)
.eq('id', user.id);
if (error) throw error;
showAlert('Success', 'Profile updated successfully', [
{ text: 'OK', onPress: () => navigation.goBack() }
]);
} catch (error) {
if (__DEV__) console.error('Error saving profile:', error);
showAlert('Error', 'Failed to save profile. Please try again.');
} finally {
setSaving(false);
}
};
const handleCancel = () => {
if (hasChanges()) {
showAlert(
'Discard Changes?',
'You have unsaved changes. Are you sure you want to go back?',
[
{ text: 'Keep Editing', style: 'cancel' },
{ text: 'Discard', style: 'destructive', onPress: () => navigation.goBack() }
]
);
} else {
navigation.goBack();
}
};
const handleAvatarSelected = (newAvatarUrl: string) => {
setAvatarUrl(newAvatarUrl);
};
if (loading) {
return (
<SafeAreaView style={[styles.container, { backgroundColor: colors.background }]} testID="edit-profile-loading">
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={KurdistanColors.kesk} />
<Text style={[styles.loadingText, { color: colors.textSecondary, fontSize: 14 * fontScale }]}>
Loading profile...
</Text>
</View>
</SafeAreaView>
);
}
return (
<SafeAreaView style={[styles.container, { backgroundColor: colors.background }]} testID="edit-profile-screen">
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoid}
>
{/* Header */}
<View style={[styles.header, { borderBottomColor: colors.border }]} testID="edit-profile-header">
<TouchableOpacity onPress={handleCancel} testID="edit-profile-cancel-button">
<Text style={[styles.headerButton, { color: colors.textSecondary, fontSize: 16 * fontScale }]}>
Cancel
</Text>
</TouchableOpacity>
<Text style={[styles.headerTitle, { color: colors.text, fontSize: 18 * fontScale }]}>
Edit Profile
</Text>
<TouchableOpacity
onPress={handleSave}
disabled={saving || !hasChanges()}
testID="edit-profile-save-button"
>
{saving ? (
<ActivityIndicator size="small" color={KurdistanColors.kesk} />
) : (
<Text style={[
styles.headerButton,
styles.saveButton,
{ fontSize: 16 * fontScale },
!hasChanges() && styles.saveButtonDisabled
]}>
Save
</Text>
)}
</TouchableOpacity>
</View>
<ScrollView
style={styles.content}
contentContainerStyle={styles.contentContainer}
showsVerticalScrollIndicator={false}
testID="edit-profile-scroll"
>
{/* Avatar Section */}
<View style={styles.avatarSection} testID="edit-profile-avatar-section">
<TouchableOpacity
onPress={() => setAvatarModalVisible(true)}
style={styles.avatarButton}
testID="edit-profile-avatar-button"
>
<View style={[styles.avatarCircle, { backgroundColor: colors.surface }]}>
{avatarUrl ? (
<Text style={styles.avatarEmoji}>{getEmojiFromAvatarId(avatarUrl)}</Text>
) : (
<Text style={[styles.avatarInitial, { color: colors.textSecondary }]}>
{fullName?.charAt(0)?.toUpperCase() || user?.email?.charAt(0)?.toUpperCase() || '?'}
</Text>
)}
</View>
<View style={styles.editAvatarBadge}>
<Text style={styles.editAvatarIcon}>📷</Text>
</View>
</TouchableOpacity>
<Text style={[styles.changePhotoText, { color: KurdistanColors.kesk, fontSize: 14 * fontScale }]}>
Change Avatar
</Text>
</View>
{/* Form Section */}
<View style={styles.formSection}>
{/* Display Name */}
<View style={styles.inputGroup} testID="edit-profile-name-group">
<Text style={[styles.inputLabel, { color: colors.textSecondary, fontSize: 14 * fontScale }]}>
Display Name
</Text>
<TextInput
style={[styles.textInput, {
backgroundColor: colors.surface,
color: colors.text,
borderColor: colors.border,
fontSize: 16 * fontScale
}]}
value={fullName}
onChangeText={setFullName}
placeholder="Enter your display name"
placeholderTextColor={colors.textSecondary}
autoCapitalize="words"
autoCorrect={false}
testID="edit-profile-name-input"
/>
<Text style={[styles.inputHint, { color: colors.textSecondary, fontSize: 12 * fontScale }]}>
This is how other users will see you
</Text>
</View>
{/* Email (Read-only) */}
<View style={styles.inputGroup} testID="edit-profile-email-group">
<Text style={[styles.inputLabel, { color: colors.textSecondary, fontSize: 14 * fontScale }]}>
Email
</Text>
<View style={[styles.readOnlyField, { backgroundColor: colors.background, borderColor: colors.border }]}>
<Text style={[styles.readOnlyText, { color: colors.textSecondary, fontSize: 16 * fontScale }]}>
{user?.email || 'N/A'}
</Text>
<Text style={styles.lockIcon}>🔒</Text>
</View>
<Text style={[styles.inputHint, { color: colors.textSecondary, fontSize: 12 * fontScale }]}>
Email cannot be changed
</Text>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>
{/* Avatar Picker Modal */}
<AvatarPickerModal
visible={avatarModalVisible}
onClose={() => setAvatarModalVisible(false)}
currentAvatar={avatarUrl || undefined}
onAvatarSelected={handleAvatarSelected}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
keyboardAvoid: {
flex: 1,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
gap: 12,
},
loadingText: {
fontSize: 14,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 12,
borderBottomWidth: 1,
},
headerButton: {
fontSize: 16,
fontWeight: '500',
},
headerTitle: {
fontSize: 18,
fontWeight: '600',
},
saveButton: {
color: KurdistanColors.kesk,
fontWeight: '600',
},
saveButtonDisabled: {
opacity: 0.4,
},
content: {
flex: 1,
},
contentContainer: {
padding: 24,
},
avatarSection: {
alignItems: 'center',
marginBottom: 32,
},
avatarButton: {
position: 'relative',
},
avatarCircle: {
width: 120,
height: 120,
borderRadius: 60,
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 4,
},
avatarEmoji: {
fontSize: 70,
},
avatarInitial: {
fontSize: 48,
fontWeight: 'bold',
},
editAvatarBadge: {
position: 'absolute',
bottom: 4,
right: 4,
backgroundColor: '#FFFFFF',
width: 36,
height: 36,
borderRadius: 18,
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
elevation: 4,
},
editAvatarIcon: {
fontSize: 18,
},
changePhotoText: {
marginTop: 12,
fontWeight: '500',
},
formSection: {
gap: 24,
},
inputGroup: {
gap: 8,
},
inputLabel: {
fontSize: 14,
fontWeight: '600',
marginLeft: 4,
},
textInput: {
borderWidth: 1,
borderRadius: 12,
padding: 16,
fontSize: 16,
},
inputHint: {
fontSize: 12,
marginLeft: 4,
},
readOnlyField: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
borderWidth: 1,
borderRadius: 12,
padding: 16,
},
readOnlyText: {
fontSize: 16,
flex: 1,
},
lockIcon: {
fontSize: 16,
marginLeft: 8,
},
});
export default EditProfileScreen;
+77 -37
View File
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import {
View,
Text,
@@ -10,15 +10,33 @@ import {
Image,
ActivityIndicator,
Alert,
Platform,
} from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { useNavigation } from '@react-navigation/native';
import { useAuth } from '../contexts/AuthContext';
import { useTheme } from '../contexts/ThemeContext';
import { KurdistanColors } from '../theme/colors';
import { supabase } from '../lib/supabase';
import AvatarPickerModal from '../components/AvatarPickerModal';
// Cross-platform alert helper
const showAlert = (title: string, message: string, buttons?: Array<{text: string; onPress?: () => void; style?: string}>) => {
if (Platform.OS === 'web') {
if (buttons && buttons.length > 1) {
const result = window.confirm(`${title}\n\n${message}`);
if (result && buttons[1]?.onPress) {
buttons[1].onPress();
}
} else {
window.alert(`${title}\n\n${message}`);
}
} else {
Alert.alert(title, message, buttons as any);
}
};
// Avatar pool matching AvatarPickerModal
const AVATAR_POOL = [
{ id: 'avatar1', emoji: '👨🏻' },
@@ -65,16 +83,19 @@ interface ProfileData {
}
const ProfileScreen: React.FC = () => {
const { t } = useTranslation();
const navigation = useNavigation();
const navigation = useNavigation<any>();
const { user, signOut } = useAuth();
const { isDarkMode, colors, fontScale } = useTheme();
const [profileData, setProfileData] = useState<ProfileData | null>(null);
const [loading, setLoading] = useState(true);
const [avatarModalVisible, setAvatarModalVisible] = useState(false);
useEffect(() => {
fetchProfileData();
}, [user]);
// Refresh profile data when screen is focused (e.g., after EditProfile)
useFocusEffect(
useCallback(() => {
fetchProfileData();
}, [user])
);
const fetchProfileData = async () => {
if (!user) {
@@ -100,7 +121,7 @@ const ProfileScreen: React.FC = () => {
};
const handleLogout = () => {
Alert.alert(
showAlert(
'Logout',
'Are you sure you want to logout?',
[
@@ -120,12 +141,22 @@ const ProfileScreen: React.FC = () => {
setProfileData(prev => prev ? { ...prev, avatar_url: avatarUrl } : null);
};
const ProfileCard = ({ icon, title, value, onPress }: { icon: string; title: string; value: string; onPress?: () => void }) => (
<TouchableOpacity style={styles.profileCard} onPress={onPress} disabled={!onPress} activeOpacity={onPress ? 0.7 : 1}>
const handleEditProfile = () => {
navigation.navigate('EditProfile');
};
const ProfileCard = ({ icon, title, value, onPress, testID }: { icon: string; title: string; value: string; onPress?: () => void; testID?: string }) => (
<TouchableOpacity
style={[styles.profileCard, { backgroundColor: colors.surface }]}
onPress={onPress}
disabled={!onPress}
activeOpacity={onPress ? 0.7 : 1}
testID={testID}
>
<Text style={styles.cardIcon}>{icon}</Text>
<View style={styles.cardContent}>
<Text style={styles.cardTitle}>{title}</Text>
<Text style={styles.cardValue} numberOfLines={1}>{value}</Text>
<Text style={[styles.cardTitle, { fontSize: 12 * fontScale }]}>{title}</Text>
<Text style={[styles.cardValue, { color: colors.text, fontSize: 16 * fontScale }]} numberOfLines={1}>{value}</Text>
</View>
{onPress && <Text style={styles.cardArrow}></Text>}
</TouchableOpacity>
@@ -133,41 +164,42 @@ const ProfileScreen: React.FC = () => {
if (loading) {
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={[styles.container, { backgroundColor: colors.background }]} testID="profile-loading-container">
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={KurdistanColors.kesk} />
<ActivityIndicator size="large" color={KurdistanColors.kesk} testID="profile-loading-indicator" />
</View>
</SafeAreaView>
);
}
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<SafeAreaView style={[styles.container, { backgroundColor: colors.background }]} testID="profile-screen">
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView showsVerticalScrollIndicator={false}>
<ScrollView showsVerticalScrollIndicator={false} testID="profile-scroll-view">
{/* Header with Gradient */}
<LinearGradient
colors={[KurdistanColors.kesk, '#008f43']}
style={styles.header}
testID="profile-header-gradient"
>
<View style={styles.avatarContainer}>
<TouchableOpacity onPress={() => setAvatarModalVisible(true)} style={styles.avatarWrapper}>
<TouchableOpacity onPress={() => setAvatarModalVisible(true)} style={styles.avatarWrapper} testID="profile-avatar-button">
{profileData?.avatar_url ? (
// Check if avatar_url is a URL (starts with http) or an emoji ID
profileData.avatar_url.startsWith('http') ? (
<Image source={{ uri: profileData.avatar_url }} style={styles.avatar} />
<Image source={{ uri: profileData.avatar_url }} style={styles.avatar} testID="profile-avatar-image" />
) : (
// It's an emoji ID, render as emoji text
<View style={styles.avatarPlaceholder}>
<Text style={styles.avatarEmojiLarge}>
<View style={styles.avatarPlaceholder} testID="profile-avatar-emoji-container">
<Text style={styles.avatarEmojiLarge} testID="profile-avatar-emoji">
{getEmojiFromAvatarId(profileData.avatar_url)}
</Text>
</View>
)
) : (
<View style={styles.avatarPlaceholder}>
<Text style={styles.avatarText}>
<View style={styles.avatarPlaceholder} testID="profile-avatar-placeholder">
<Text style={styles.avatarText} testID="profile-avatar-initial">
{profileData?.full_name?.charAt(0)?.toUpperCase() || user?.email?.charAt(0)?.toUpperCase() || '?'}
</Text>
</View>
@@ -176,25 +208,27 @@ const ProfileScreen: React.FC = () => {
<Text style={styles.editAvatarIcon}>📷</Text>
</View>
</TouchableOpacity>
<Text style={styles.name}>
<Text style={[styles.name, { fontSize: 24 * fontScale }]} testID="profile-name">
{profileData?.full_name || user?.email?.split('@')[0] || 'User'}
</Text>
<Text style={styles.email}>{user?.email}</Text>
<Text style={[styles.email, { fontSize: 14 * fontScale }]} testID="profile-email">{user?.email}</Text>
</View>
</LinearGradient>
{/* Profile Info Cards */}
<View style={styles.cardsContainer}>
<View style={styles.cardsContainer} testID="profile-cards-container">
<ProfileCard
icon="📧"
title="Email"
value={user?.email || 'N/A'}
testID="profile-card-email"
/>
<ProfileCard
icon="📅"
title="Member Since"
value={profileData?.created_at ? new Date(profileData.created_at).toLocaleDateString() : 'N/A'}
testID="profile-card-member-since"
/>
<ProfileCard
@@ -202,6 +236,7 @@ const ProfileScreen: React.FC = () => {
title="Referrals"
value={`${profileData?.referral_count || 0} people`}
onPress={() => (navigation as any).navigate('Referral')}
testID="profile-card-referrals"
/>
{profileData?.referral_code && (
@@ -209,6 +244,7 @@ const ProfileScreen: React.FC = () => {
icon="🎁"
title="Your Referral Code"
value={profileData.referral_code}
testID="profile-card-referral-code"
/>
)}
@@ -217,31 +253,34 @@ const ProfileScreen: React.FC = () => {
icon="👛"
title="Wallet Address"
value={`${profileData.wallet_address.slice(0, 10)}...${profileData.wallet_address.slice(-8)}`}
testID="profile-card-wallet"
/>
)}
</View>
{/* Action Buttons */}
<View style={styles.actionsContainer}>
<View style={styles.actionsContainer} testID="profile-actions-container">
<TouchableOpacity
style={styles.actionButton}
onPress={() => Alert.alert('Coming Soon', 'Edit profile feature will be available soon')}
style={[styles.actionButton, { backgroundColor: colors.surface }]}
onPress={handleEditProfile}
testID="profile-edit-button"
>
<Text style={styles.actionIcon}></Text>
<Text style={styles.actionText}>Edit Profile</Text>
<Text style={[styles.actionText, { color: colors.text, fontSize: 16 * fontScale }]}>Edit Profile</Text>
<Text style={styles.actionArrow}></Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.actionButton}
onPress={() => Alert.alert(
style={[styles.actionButton, { backgroundColor: colors.surface }]}
onPress={() => showAlert(
'About Pezkuwi',
'Pezkuwi is a decentralized blockchain platform for Digital Kurdistan.\n\nVersion: 1.0.0\n\n© 2026 Digital Kurdistan',
[{ text: 'OK' }]
)}
testID="profile-about-button"
>
<Text style={styles.actionIcon}></Text>
<Text style={styles.actionText}>About Pezkuwi</Text>
<Text style={[styles.actionText, { color: colors.text, fontSize: 16 * fontScale }]}>About Pezkuwi</Text>
<Text style={styles.actionArrow}></Text>
</TouchableOpacity>
</View>
@@ -251,15 +290,16 @@ const ProfileScreen: React.FC = () => {
style={styles.logoutButton}
onPress={handleLogout}
activeOpacity={0.8}
testID="profile-logout-button"
>
<Text style={styles.logoutButtonText}>Logout</Text>
<Text style={[styles.logoutButtonText, { fontSize: 16 * fontScale }]}>Logout</Text>
</TouchableOpacity>
<View style={styles.footer}>
<Text style={styles.footerText}>
<View style={styles.footer} testID="profile-footer">
<Text style={[styles.footerText, { color: colors.textSecondary, fontSize: 12 * fontScale }]}>
Pezkuwi Blockchain {new Date().getFullYear()}
</Text>
<Text style={styles.footerVersion}>Version 1.0.0</Text>
<Text style={[styles.footerVersion, { fontSize: 10 * fontScale }]}>Version 1.0.0</Text>
</View>
</ScrollView>
-2
View File
@@ -13,7 +13,6 @@ import {
ActivityIndicator,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { usePezkuwi } from '../contexts/PezkuwiContext';
import { KurdistanColors } from '../theme/colors';
import {
@@ -41,7 +40,6 @@ interface Referral {
}
const ReferralScreen: React.FC = () => {
const { t: _t } = useTranslation();
const { selectedAccount, api, connectWallet, isApiReady } = usePezkuwi();
const isConnected = !!selectedAccount;
File diff suppressed because it is too large Load Diff
+10 -12
View File
@@ -14,7 +14,6 @@ import {
ActivityIndicator,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { useAuth } from '../contexts/AuthContext';
import { KurdistanColors } from '../theme/colors';
@@ -24,7 +23,6 @@ interface SignInScreenProps {
}
const SignInScreen: React.FC<SignInScreenProps> = ({ onSignIn, onNavigateToSignUp }) => {
const { t } = useTranslation();
const { signIn } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
@@ -78,17 +76,17 @@ const SignInScreen: React.FC<SignInScreenProps> = ({ onSignIn, onNavigateToSignU
<View style={styles.logoContainer}>
<Text style={styles.logoText}>PZK</Text>
</View>
<Text style={styles.title}>{t('auth.welcomeBack')}</Text>
<Text style={styles.subtitle}>{t('auth.signIn')}</Text>
<Text style={styles.title}>Welcome Back!</Text>
<Text style={styles.subtitle}>Sign In</Text>
</View>
{/* Form */}
<View style={styles.form}>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('auth.email')}</Text>
<Text style={styles.label}>Email</Text>
<TextInput
style={styles.input}
placeholder={t('auth.email')}
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
@@ -98,10 +96,10 @@ const SignInScreen: React.FC<SignInScreenProps> = ({ onSignIn, onNavigateToSignU
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('auth.password')}</Text>
<Text style={styles.label}>Password</Text>
<TextInput
style={styles.input}
placeholder={t('auth.password')}
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
@@ -111,7 +109,7 @@ const SignInScreen: React.FC<SignInScreenProps> = ({ onSignIn, onNavigateToSignU
<TouchableOpacity style={styles.forgotPassword}>
<Text style={styles.forgotPasswordText}>
{t('auth.forgotPassword')}
Forgot Password?
</Text>
</TouchableOpacity>
@@ -124,7 +122,7 @@ const SignInScreen: React.FC<SignInScreenProps> = ({ onSignIn, onNavigateToSignU
{isLoading ? (
<ActivityIndicator color={KurdistanColors.spi} />
) : (
<Text style={styles.signInButtonText}>{t('auth.signIn')}</Text>
<Text style={styles.signInButtonText}>Sign In</Text>
)}
</TouchableOpacity>
@@ -139,8 +137,8 @@ const SignInScreen: React.FC<SignInScreenProps> = ({ onSignIn, onNavigateToSignU
onPress={onNavigateToSignUp}
>
<Text style={styles.signUpPromptText}>
{t('auth.noAccount')}{' '}
<Text style={styles.signUpLink}>{t('auth.signUp')}</Text>
Don't have an account?{' '}
<Text style={styles.signUpLink}>Sign Up</Text>
</Text>
</TouchableOpacity>
</View>
+13 -15
View File
@@ -14,7 +14,6 @@ import {
ActivityIndicator,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { useAuth } from '../contexts/AuthContext';
import { KurdistanColors } from '../theme/colors';
@@ -24,7 +23,6 @@ interface SignUpScreenProps {
}
const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignIn }) => {
const { t } = useTranslation();
const { signUp } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
@@ -85,17 +83,17 @@ const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignI
<View style={styles.logoContainer}>
<Text style={styles.logoText}>PZK</Text>
</View>
<Text style={styles.title}>{t('auth.getStarted')}</Text>
<Text style={styles.subtitle}>{t('auth.createAccount')}</Text>
<Text style={styles.title}>Get Started</Text>
<Text style={styles.subtitle}>Create Account</Text>
</View>
{/* Form */}
<View style={styles.form}>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('auth.email')}</Text>
<Text style={styles.label}>Email</Text>
<TextInput
style={styles.input}
placeholder={t('auth.email')}
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
@@ -105,10 +103,10 @@ const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignI
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('auth.username')}</Text>
<Text style={styles.label}>Username</Text>
<TextInput
style={styles.input}
placeholder={t('auth.username')}
placeholder="Username"
value={username}
onChangeText={setUsername}
autoCapitalize="none"
@@ -117,10 +115,10 @@ const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignI
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('auth.password')}</Text>
<Text style={styles.label}>Password</Text>
<TextInput
style={styles.input}
placeholder={t('auth.password')}
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
@@ -129,10 +127,10 @@ const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignI
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>{t('auth.confirmPassword')}</Text>
<Text style={styles.label}>Confirm Password</Text>
<TextInput
style={styles.input}
placeholder={t('auth.confirmPassword')}
placeholder="Confirm Password"
value={confirmPassword}
onChangeText={setConfirmPassword}
secureTextEntry
@@ -149,7 +147,7 @@ const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignI
{isLoading ? (
<ActivityIndicator color={KurdistanColors.spi} />
) : (
<Text style={styles.signUpButtonText}>{t('auth.signUp')}</Text>
<Text style={styles.signUpButtonText}>Sign Up</Text>
)}
</TouchableOpacity>
@@ -164,8 +162,8 @@ const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignI
onPress={onNavigateToSignIn}
>
<Text style={styles.signInPromptText}>
{t('auth.haveAccount')}{' '}
<Text style={styles.signInLink}>{t('auth.signIn')}</Text>
Already have an account?{' '}
<Text style={styles.signInLink}>Sign In</Text>
</Text>
</TouchableOpacity>
</View>
+35 -10
View File
@@ -42,7 +42,7 @@ const SCORE_WEIGHTS = {
};
export default function StakingScreen() {
const { api, selectedAccount, isApiReady } = usePezkuwi();
const { api, selectedAccount, isApiReady, getKeyPair } = usePezkuwi();
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
@@ -137,17 +137,20 @@ export default function StakingScreen() {
setProcessing(true);
if (!api || !selectedAccount) return;
// Get keypair for signing
const keyPair = await getKeyPair(selectedAccount.address);
if (!keyPair) {
Alert.alert('Error', 'Could not retrieve wallet keypair for signing');
return;
}
// Convert amount to planck
const amountPlanck = BigInt(Math.floor(parseFloat(stakeAmount) * 1e12));
// Bond tokens (or bond_extra if already bonding)
// For simplicity, using bond_extra if already bonded, otherwise bond
// But UI should handle controller/stash logic. Assuming simple setup.
// This part is simplified.
const tx = api.tx.staking.bondExtra(amountPlanck);
await tx.signAndSend(selectedAccount.address, ({ status }) => {
await tx.signAndSend(keyPair, ({ status }) => {
if (status.isInBlock) {
Alert.alert('Success', `Successfully staked ${stakeAmount} HEZ!`);
setStakeSheetVisible(false);
@@ -173,10 +176,17 @@ export default function StakingScreen() {
setProcessing(true);
if (!api || !selectedAccount) return;
// Get keypair for signing
const keyPair = await getKeyPair(selectedAccount.address);
if (!keyPair) {
Alert.alert('Error', 'Could not retrieve wallet keypair for signing');
return;
}
const amountPlanck = BigInt(Math.floor(parseFloat(unstakeAmount) * 1e12));
const tx = api.tx.staking.unbond(amountPlanck);
await tx.signAndSend(selectedAccount.address, ({ status }) => {
await tx.signAndSend(keyPair, ({ status }) => {
if (status.isInBlock) {
Alert.alert(
'Success',
@@ -200,10 +210,17 @@ export default function StakingScreen() {
setProcessing(true);
if (!api || !selectedAccount) return;
// Get keypair for signing
const keyPair = await getKeyPair(selectedAccount.address);
if (!keyPair) {
Alert.alert('Error', 'Could not retrieve wallet keypair for signing');
return;
}
// Withdraw all available unbonded funds
// num_slashing_spans is usually 0 for simple stakers
const tx = api.tx.staking.withdrawUnbonded(0);
await tx.signAndSend(selectedAccount.address, ({ status }) => {
await tx.signAndSend(keyPair, ({ status }) => {
if (status.isInBlock) {
Alert.alert('Success', 'Successfully withdrawn unbonded tokens!');
fetchStakingData();
@@ -226,8 +243,16 @@ export default function StakingScreen() {
setProcessing(true);
try {
// Get keypair for signing
const keyPair = await getKeyPair(selectedAccount.address);
if (!keyPair) {
Alert.alert('Error', 'Could not retrieve wallet keypair for signing');
setProcessing(false);
return;
}
const tx = api.tx.staking.nominate(validators);
await tx.signAndSend(selectedAccount.address, ({ status }) => {
await tx.signAndSend(keyPair, ({ status }) => {
if (status.isInBlock) {
Alert.alert('Success', 'Nomination transaction sent!');
setValidatorSheetVisible(false);
+233 -29
View File
@@ -13,8 +13,10 @@ import {
Platform,
Image,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { KurdistanColors } from '../theme/colors';
import { usePezkuwi } from '../contexts/PezkuwiContext';
import { KurdistanSun } from '../components/KurdistanSun';
// Token Images
const hezLogo = require('../../../shared/images/hez_logo.png');
@@ -30,14 +32,15 @@ interface TokenInfo {
}
const TOKENS: TokenInfo[] = [
{ symbol: 'HEZ', name: 'Hemuwelet', assetId: 0, decimals: 12, logo: hezLogo },
{ symbol: 'PEZ', name: 'Pezkunel', assetId: 1, decimals: 12, logo: pezLogo },
{ symbol: 'HEZ', name: 'Welati Coin', assetId: 0, decimals: 12, logo: hezLogo },
{ symbol: 'PEZ', name: 'Pezkuwichain Token', assetId: 1, decimals: 12, logo: pezLogo },
{ symbol: 'USDT', name: 'Tether USD', assetId: 1000, decimals: 6, logo: usdtLogo },
];
type TransactionStatus = 'idle' | 'signing' | 'submitting' | 'success' | 'error';
const SwapScreen: React.FC = () => {
const navigation = useNavigation<any>();
const { api, isApiReady, selectedAccount, getKeyPair } = usePezkuwi();
const [fromToken, setFromToken] = useState<TokenInfo>(TOKENS[0]);
@@ -49,6 +52,17 @@ const SwapScreen: React.FC = () => {
const [fromBalance, setFromBalance] = useState('0');
const [toBalance, setToBalance] = useState('0');
// Pool reserves for AMM calculation
const [poolReserves, setPoolReserves] = useState<{
reserve0: number;
reserve1: number;
asset0: number;
asset1: number;
} | null>(null);
const [exchangeRate, setExchangeRate] = useState(0);
const [isLoadingRate, setIsLoadingRate] = useState(false);
const [isDexAvailable, setIsDexAvailable] = useState(false);
const [txStatus, setTxStatus] = useState<TransactionStatus>('idle');
const [errorMessage, setErrorMessage] = useState('');
@@ -93,18 +107,184 @@ const SwapScreen: React.FC = () => {
fetchBalances();
}, [api, isApiReady, selectedAccount, fromToken, toToken]);
// Calculate output amount (simple 1:1 for now - should use pool reserves)
// Check if AssetConversion pallet is available
useEffect(() => {
if (api && isApiReady) {
const hasAssetConversion = api.tx.assetConversion !== undefined;
setIsDexAvailable(hasAssetConversion);
if (__DEV__ && !hasAssetConversion) {
console.warn('AssetConversion pallet not available in runtime');
}
}
}, [api, isApiReady]);
// Fetch exchange rate from AssetConversion pool
useEffect(() => {
const fetchExchangeRate = async () => {
if (!api || !isApiReady || !isDexAvailable) {
return;
}
setIsLoadingRate(true);
try {
// Map user-selected tokens to actual pool assets
// HEZ → wHEZ (Asset 0) behind the scenes
const getPoolAssetId = (token: TokenInfo) => {
if (token.symbol === 'HEZ') return 0; // wHEZ
return token.assetId;
};
const fromAssetId = getPoolAssetId(fromToken);
const toAssetId = getPoolAssetId(toToken);
// Pool ID must be sorted (smaller asset ID first)
const [asset1, asset2] = fromAssetId < toAssetId
? [fromAssetId, toAssetId]
: [toAssetId, fromAssetId];
// Create pool asset tuple [asset1, asset2] - must be sorted!
const poolAssets = [
{ NativeOrAsset: { Asset: asset1 } },
{ NativeOrAsset: { Asset: asset2 } }
];
// Query pool from AssetConversion pallet
const poolInfo = await api.query.assetConversion.pools(poolAssets);
if (poolInfo && !poolInfo.isEmpty) {
try {
// Derive pool account using AccountIdConverter
// blake2_256(&Encode::encode(&(PalletId, PoolId))[..])
const { stringToU8a } = await import('@pezkuwi/util');
const { blake2AsU8a } = await import('@pezkuwi/util-crypto');
// PalletId for AssetConversion: "py/ascon" (8 bytes)
const PALLET_ID = stringToU8a('py/ascon');
// Create PoolId tuple (u32, u32)
const poolId = api.createType('(u32, u32)', [asset1, asset2]);
// Create (PalletId, PoolId) tuple: ([u8; 8], (u32, u32))
const palletIdType = api.createType('[u8; 8]', PALLET_ID);
const fullTuple = api.createType('([u8; 8], (u32, u32))', [palletIdType, poolId]);
// Hash the SCALE-encoded tuple
const accountHash = blake2AsU8a(fullTuple.toU8a(), 256);
const poolAccountId = api.createType('AccountId32', accountHash);
// Query pool account's asset balances
const reserve0Query = await api.query.assets.account(asset1, poolAccountId);
const reserve1Query = await api.query.assets.account(asset2, poolAccountId);
const reserve0Data = reserve0Query.toJSON() as { balance?: string } | null;
const reserve1Data = reserve1Query.toJSON() as { balance?: string } | null;
if (reserve0Data?.balance && reserve1Data?.balance) {
// Parse hex string balances to BigInt, then to number
const balance0Hex = reserve0Data.balance.toString();
const balance1Hex = reserve1Data.balance.toString();
// Use correct decimals for each asset
const decimals0 = asset1 === 1000 ? 6 : 12;
const decimals1 = asset2 === 1000 ? 6 : 12;
const reserve0 = Number(BigInt(balance0Hex)) / (10 ** decimals0);
const reserve1 = Number(BigInt(balance1Hex)) / (10 ** decimals1);
if (__DEV__) {
console.log('Pool reserves found:', { reserve0, reserve1, asset1, asset2 });
}
// Store pool reserves for AMM calculation
setPoolReserves({
reserve0,
reserve1,
asset0: asset1,
asset1: asset2
});
// Calculate simple exchange rate for display
const rate = fromAssetId === asset1
? reserve1 / reserve0 // from asset1 to asset2
: reserve0 / reserve1; // from asset2 to asset1
setExchangeRate(rate);
} else {
if (__DEV__) console.warn('Pool has no reserves');
setExchangeRate(0);
setPoolReserves(null);
}
} catch (err) {
if (__DEV__) console.error('Error deriving pool account:', err);
setExchangeRate(0);
setPoolReserves(null);
}
} else {
if (__DEV__) console.warn('No liquidity pool found for this pair');
setExchangeRate(0);
setPoolReserves(null);
}
} catch (error) {
if (__DEV__) console.error('Failed to fetch exchange rate:', error);
setExchangeRate(0);
setPoolReserves(null);
} finally {
setIsLoadingRate(false);
}
};
fetchExchangeRate();
}, [api, isApiReady, isDexAvailable, fromToken, toToken]);
// Calculate output amount using Uniswap V2 AMM formula
useEffect(() => {
if (!fromAmount || parseFloat(fromAmount) <= 0) {
setToAmount('');
return;
}
// TODO: Implement proper AMM calculation using pool reserves
// For now, simple 1:1 conversion (placeholder)
const calculatedAmount = (parseFloat(fromAmount) * 0.97).toFixed(6); // 3% fee simulation
setToAmount(calculatedAmount);
}, [fromAmount, fromToken, toToken]);
// If no pool reserves available, cannot calculate
if (!poolReserves) {
setToAmount('');
return;
}
const amountIn = parseFloat(fromAmount);
const { reserve0, reserve1, asset0 } = poolReserves;
// Determine which reserve is input and which is output
const getPoolAssetId = (token: TokenInfo) => {
if (token.symbol === 'HEZ') return 0; // wHEZ
return token.assetId;
};
const fromAssetId = getPoolAssetId(fromToken);
const isAsset0ToAsset1 = fromAssetId === asset0;
const reserveIn = isAsset0ToAsset1 ? reserve0 : reserve1;
const reserveOut = isAsset0ToAsset1 ? reserve1 : reserve0;
// Uniswap V2 AMM formula (matches Substrate runtime exactly)
// Runtime: amount_in_with_fee = amount_in * (1000 - LPFee) = amount_in * 970
// LPFee = 30 (3% fee)
// Formula: amountOut = (amountIn * 970 * reserveOut) / (reserveIn * 1000 + amountIn * 970)
const LP_FEE = 30; // 3% fee
const amountInWithFee = amountIn * (1000 - LP_FEE);
const numerator = amountInWithFee * reserveOut;
const denominator = reserveIn * 1000 + amountInWithFee;
const amountOut = numerator / denominator;
if (__DEV__) {
console.log('AMM calculation:', {
amountIn,
reserveIn,
reserveOut,
amountOut,
lpFee: `${LP_FEE / 10}%`
});
}
setToAmount(amountOut.toFixed(6));
}, [fromAmount, fromToken, toToken, poolReserves]);
// Calculate formatted balances
const fromBalanceFormatted = useMemo(() => {
@@ -161,6 +341,11 @@ const SwapScreen: React.FC = () => {
return;
}
if (!exchangeRate || exchangeRate === 0) {
Alert.alert('Error', 'No liquidity pool available for this pair');
return;
}
setTxStatus('signing');
setShowConfirm(false);
setErrorMessage('');
@@ -276,21 +461,22 @@ const SwapScreen: React.FC = () => {
return (
<SafeAreaView style={styles.container}>
{/* Transaction Loading Overlay */}
{/* Kurdistan Sun Loading Overlay */}
{(txStatus === 'signing' || txStatus === 'submitting') && (
<View style={styles.loadingOverlay}>
<View style={styles.loadingCard}>
<ActivityIndicator size="large" color={KurdistanColors.kesk} />
<Text style={styles.loadingText}>
{txStatus === 'signing' ? 'Waiting for signature...' : 'Processing swap...'}
</Text>
</View>
<KurdistanSun size={250} />
<Text style={styles.loadingText}>
{txStatus === 'signing' ? 'Waiting for signature...' : 'Processing your swap...'}
</Text>
</View>
)}
<ScrollView style={styles.scrollContent} contentContainerStyle={styles.scrollContentContainer}>
{/* Header */}
<View style={styles.header}>
<TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
<Text style={styles.backButtonText}></Text>
</TouchableOpacity>
<Text style={styles.headerTitle}>Swap Tokens</Text>
<TouchableOpacity onPress={() => setShowSettings(true)} style={styles.settingsButton}>
<Text style={styles.settingsIcon}></Text>
@@ -369,7 +555,13 @@ const SwapScreen: React.FC = () => {
<View style={styles.detailsCard}>
<View style={styles.detailRow}>
<Text style={styles.detailLabel}> Exchange Rate</Text>
<Text style={styles.detailValue}>1 {fromToken.symbol} 1 {toToken.symbol}</Text>
<Text style={styles.detailValue}>
{isLoadingRate
? 'Loading...'
: exchangeRate > 0
? `1 ${fromToken.symbol}${exchangeRate.toFixed(4)} ${toToken.symbol}`
: 'No pool available'}
</Text>
</View>
<View style={styles.detailRow}>
<Text style={styles.detailLabel}>Slippage Tolerance</Text>
@@ -389,14 +581,16 @@ const SwapScreen: React.FC = () => {
<TouchableOpacity
style={[
styles.swapButton,
(!fromAmount || hasInsufficientBalance || txStatus !== 'idle') && styles.swapButtonDisabled
(!fromAmount || hasInsufficientBalance || txStatus !== 'idle' || exchangeRate === 0) && styles.swapButtonDisabled
]}
onPress={() => setShowConfirm(true)}
disabled={!fromAmount || hasInsufficientBalance || txStatus !== 'idle'}
disabled={!fromAmount || hasInsufficientBalance || txStatus !== 'idle' || exchangeRate === 0}
>
<Text style={styles.swapButtonText}>
{hasInsufficientBalance
? `Insufficient ${fromToken.symbol} Balance`
: exchangeRate === 0
? 'No Pool Available'
: 'Swap Tokens'}
</Text>
</TouchableOpacity>
@@ -468,6 +662,10 @@ const SwapScreen: React.FC = () => {
<Text style={styles.confirmValue}>{toAmount} {toToken.symbol}</Text>
</View>
<View style={[styles.confirmRow, styles.confirmRowBorder]}>
<Text style={styles.confirmLabelSmall}>Exchange Rate</Text>
<Text style={styles.confirmValueSmall}>1 {fromToken.symbol} = {exchangeRate.toFixed(4)} {toToken.symbol}</Text>
</View>
<View style={styles.confirmRow}>
<Text style={styles.confirmLabelSmall}>Slippage</Text>
<Text style={styles.confirmValueSmall}>{slippage}%</Text>
</View>
@@ -519,8 +717,20 @@ const styles = StyleSheet.create({
alignItems: 'center',
marginBottom: 20,
},
headerTitle: {
backButton: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#F5F5F5',
justifyContent: 'center',
alignItems: 'center',
},
backButtonText: {
fontSize: 24,
color: '#333',
},
headerTitle: {
fontSize: 20,
fontWeight: 'bold',
color: '#333',
},
@@ -693,22 +903,16 @@ const styles = StyleSheet.create({
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0,0,0,0.7)',
backgroundColor: 'rgba(0,0,0,0.85)',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1000,
},
loadingCard: {
backgroundColor: '#FFFFFF',
borderRadius: 20,
padding: 32,
alignItems: 'center',
gap: 16,
},
loadingText: {
fontSize: 16,
marginTop: 24,
fontSize: 18,
fontWeight: '600',
color: '#333',
color: '#FFFFFF',
},
modalOverlay: {
flex: 1,
+6 -8
View File
@@ -9,7 +9,6 @@ import {
Animated,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { KurdistanColors } from '../theme/colors';
import AsyncStorage from '@react-native-async-storage/async-storage';
@@ -20,7 +19,6 @@ interface VerifyHumanScreenProps {
}
const VerifyHumanScreen: React.FC<VerifyHumanScreenProps> = ({ onVerified }) => {
const { t } = useTranslation();
const [isChecked, setIsChecked] = useState(false);
const [scaleValue] = useState(new Animated.Value(1));
@@ -71,9 +69,9 @@ const VerifyHumanScreen: React.FC<VerifyHumanScreenProps> = ({ onVerified }) =>
</View>
{/* Title */}
<Text style={styles.title}>{t('verify.title', 'Security Verification')}</Text>
<Text style={styles.title}>Security Verification</Text>
<Text style={styles.subtitle}>
{t('verify.subtitle', 'Please confirm you are human to continue')}
Please confirm you are human to continue
</Text>
{/* Verification Box */}
@@ -86,13 +84,13 @@ const VerifyHumanScreen: React.FC<VerifyHumanScreenProps> = ({ onVerified }) =>
{isChecked && <Text style={styles.checkmark}></Text>}
</View>
<Text style={styles.verificationText}>
{t('verify.checkbox', "I'm not a robot")}
I'm not a robot
</Text>
</TouchableOpacity>
{/* Info Text */}
<Text style={styles.infoText}>
{t('verify.info', 'This helps protect the Pezkuwi network from automated attacks')}
This helps protect the Pezkuwi network from automated attacks
</Text>
{/* Continue Button */}
@@ -109,7 +107,7 @@ const VerifyHumanScreen: React.FC<VerifyHumanScreenProps> = ({ onVerified }) =>
!isChecked && styles.continueButtonTextDisabled,
]}
>
{t('verify.continue', 'Continue')}
Continue
</Text>
</Animated.View>
</TouchableOpacity>
@@ -117,7 +115,7 @@ const VerifyHumanScreen: React.FC<VerifyHumanScreenProps> = ({ onVerified }) =>
{/* Footer */}
<View style={styles.footer}>
<Text style={styles.footerText}>
🔒 {t('verify.secure', 'Secure & Private')}
Secure & Private
</Text>
</View>
</View>
+425 -159
View File
@@ -18,12 +18,44 @@ import {
Share,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { useNavigation } from '@react-navigation/native';
import QRCode from 'react-native-qrcode-svg';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as SecureStore from 'expo-secure-store';
import { KurdistanColors } from '../theme/colors';
import { usePezkuwi, NetworkType, NETWORKS } from '../contexts/PezkuwiContext';
import { AddTokenModal } from '../components/wallet/AddTokenModal';
import { HezTokenLogo, PezTokenLogo } from '../components/icons';
// Secure storage helper - same as in PezkuwiContext
const secureStorage = {
getItem: async (key: string): Promise<string | null> => {
if (Platform.OS === 'web') {
return await AsyncStorage.getItem(key);
} else {
return await SecureStore.getItemAsync(key);
}
},
};
// Cross-platform alert helper
const showAlert = (title: string, message: string, buttons?: Array<{text: string; onPress?: () => void; style?: string}>) => {
if (Platform.OS === 'web') {
if (buttons && buttons.length > 1) {
const result = window.confirm(`${title}\n\n${message}`);
if (result && buttons[1]?.onPress) {
buttons[1].onPress();
} else if (!result && buttons[0]?.onPress) {
buttons[0].onPress();
}
} else {
window.alert(`${title}\n\n${message}`);
if (buttons?.[0]?.onPress) buttons[0].onPress();
}
} else {
showAlert(title, message, buttons as any);
}
};
// Token Images - From shared/images
const hezLogo = require('../../../shared/images/hez_logo.png');
@@ -59,16 +91,17 @@ interface Transaction {
}
const WalletScreen: React.FC = () => {
const { t } = useTranslation();
const navigation = useNavigation<any>();
const {
api,
isApiReady,
accounts,
selectedAccount,
setSelectedAccount,
connectWallet,
disconnectWallet,
createWallet,
deleteWallet,
getKeyPair,
currentNetwork,
switchNetwork,
@@ -82,6 +115,7 @@ const WalletScreen: React.FC = () => {
const [importWalletModalVisible, setImportWalletModalVisible] = useState(false);
const [backupModalVisible, setBackupModalVisible] = useState(false);
const [networkSelectorVisible, setNetworkSelectorVisible] = useState(false);
const [walletSelectorVisible, setWalletSelectorVisible] = useState(false);
const [addTokenModalVisible, setAddTokenModalVisible] = useState(false);
const [recipientAddress, setRecipientAddress] = useState('');
const [sendAmount, setSendAmount] = useState('');
@@ -225,7 +259,7 @@ const WalletScreen: React.FC = () => {
const handleConfirmSend = async () => {
if (!recipientAddress || !sendAmount || !selectedToken || !selectedAccount || !api) {
Alert.alert('Error', 'Please enter recipient address and amount');
showAlert('Error', 'Please enter recipient address and amount');
return;
}
@@ -251,13 +285,13 @@ const WalletScreen: React.FC = () => {
if (status.isFinalized) {
setSendModalVisible(false);
setIsSending(false);
Alert.alert('Success', 'Transaction Sent!');
showAlert('Success', 'Transaction Sent!');
fetchData();
}
});
} catch (e: any) {
setIsSending(false);
Alert.alert('Error', e.message);
showAlert('Error', e.message);
}
};
@@ -272,21 +306,21 @@ const WalletScreen: React.FC = () => {
const { address, mnemonic } = await createWallet(walletName);
setUserMnemonic(mnemonic); // Save for backup
setCreateWalletModalVisible(false);
Alert.alert('Wallet Created', `Save this mnemonic:\n${mnemonic}`, [{ text: 'OK', onPress: () => connectWallet() }]);
} catch (e) { Alert.alert('Error', 'Failed'); }
showAlert('Wallet Created', `Save this mnemonic:\n${mnemonic}`, [{ text: 'OK', onPress: () => connectWallet() }]);
} catch (e) { showAlert('Error', 'Failed'); }
};
// Copy Address Handler
const handleCopyAddress = () => {
if (!selectedAccount) return;
Clipboard.setString(selectedAccount.address);
Alert.alert('Copied!', 'Address copied to clipboard');
showAlert('Copied!', 'Address copied to clipboard');
};
// Import Wallet Handler
const handleImportWallet = async () => {
if (!importMnemonic.trim()) {
Alert.alert('Error', 'Please enter a valid mnemonic');
showAlert('Error', 'Please enter a valid mnemonic');
return;
}
try {
@@ -297,23 +331,36 @@ const WalletScreen: React.FC = () => {
const pair = keyring.addFromMnemonic(importMnemonic.trim());
// Store in AsyncStorage (via context method ideally)
Alert.alert('Success', `Wallet imported: ${pair.address.slice(0,8)}...`);
showAlert('Success', `Wallet imported: ${pair.address.slice(0,8)}...`);
setImportWalletModalVisible(false);
setImportMnemonic('');
connectWallet();
} catch (e: any) {
Alert.alert('Error', e.message || 'Invalid mnemonic');
showAlert('Error', e.message || 'Invalid mnemonic');
}
};
// Backup Mnemonic Handler
const handleBackupMnemonic = async () => {
// Retrieve mnemonic from secure storage
// For demo, we show the saved one or prompt user
if (userMnemonic) {
setBackupModalVisible(true);
} else {
Alert.alert('No Backup', 'Mnemonic not available. Create a new wallet or import existing one.');
if (!selectedAccount) {
showAlert('No Wallet', 'Please create or import a wallet first.');
return;
}
try {
// Retrieve mnemonic from secure storage
const seedKey = `pezkuwi_seed_${selectedAccount.address}`;
const storedMnemonic = await secureStorage.getItem(seedKey);
if (storedMnemonic) {
setUserMnemonic(storedMnemonic);
setBackupModalVisible(true);
} else {
showAlert('No Backup', 'Mnemonic not found in secure storage. It may have been imported from another device.');
}
} catch (error) {
console.error('Error retrieving mnemonic:', error);
showAlert('Error', 'Failed to retrieve mnemonic from secure storage.');
}
};
@@ -334,156 +381,110 @@ const WalletScreen: React.FC = () => {
try {
await switchNetwork(network);
setNetworkSelectorVisible(false);
Alert.alert('Success', `Switched to ${NETWORKS[network].displayName}`);
showAlert('Success', `Switched to ${NETWORKS[network].displayName}`);
} catch (e: any) {
Alert.alert('Error', e.message || 'Failed to switch network');
showAlert('Error', e.message || 'Failed to switch network');
}
};
if (!selectedAccount) {
return (
<SafeAreaView style={styles.container}>
<LinearGradient
colors={['#00693E', '#008f43', '#00A651']}
style={styles.welcomeGradient}
>
<View style={styles.welcomeContent}>
<Text style={styles.welcomeEmoji}>🔐</Text>
<Text style={styles.welcomeTitle}>Welcome to</Text>
<Text style={styles.welcomeBrand}>Pezkuwichain Wallet</Text>
<Text style={styles.welcomeSubtitle}>
Secure, Fast & Decentralized
</Text>
</View>
</LinearGradient>
// Redirect to WalletSetupScreen if no wallet exists
useEffect(() => {
if (!selectedAccount && accounts.length === 0) {
navigation.replace('WalletSetup');
}
}, [selectedAccount, accounts, navigation]);
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.primaryWalletButton}
onPress={handleConnectWallet}
activeOpacity={0.8}
>
<LinearGradient
colors={[KurdistanColors.kesk, '#00A651']}
style={styles.buttonGradient}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
>
<View style={styles.buttonIcon}>
<Text style={styles.buttonIconText}></Text>
</View>
<View style={styles.buttonTextContainer}>
<Text style={styles.primaryButtonText}>Create New Wallet</Text>
<Text style={styles.primaryButtonSubtext}>
Get started in seconds
</Text>
</View>
</LinearGradient>
</TouchableOpacity>
<TouchableOpacity
style={styles.secondaryWalletButton}
onPress={() => setImportWalletModalVisible(true)}
activeOpacity={0.8}
>
<View style={styles.secondaryButtonContent}>
<View style={[styles.buttonIcon, {backgroundColor: 'rgba(0,105,62,0.1)'}]}>
<Text style={[styles.buttonIconText, {color: KurdistanColors.kesk}]}>📥</Text>
</View>
<View style={styles.buttonTextContainer}>
<Text style={styles.secondaryButtonText}>Import Existing Wallet</Text>
<Text style={styles.secondaryButtonSubtext}>
Use your seed phrase
</Text>
</View>
</View>
</TouchableOpacity>
<View style={styles.securityNotice}>
<Text style={styles.securityIcon}>🛡</Text>
<Text style={styles.securityText}>
Your keys are encrypted and stored locally on your device
</Text>
</View>
</View>
{/* Create Wallet Modal */}
<Modal visible={createWalletModalVisible} transparent animationType="slide" onRequestClose={() => setCreateWalletModalVisible(false)}>
<View style={styles.modalOverlay}>
<View style={styles.modalCard}>
<Text style={styles.modalHeader}>Create New Wallet</Text>
<TextInput style={styles.inputField} placeholder="Wallet Name" value={walletName} onChangeText={setWalletName} />
<View style={styles.modalActions}>
<TouchableOpacity style={styles.btnCancel} onPress={() => setCreateWalletModalVisible(false)}><Text>Cancel</Text></TouchableOpacity>
<TouchableOpacity style={styles.btnConfirm} onPress={handleCreateWallet}><Text style={{color:'white'}}>Create</Text></TouchableOpacity>
</View>
</View>
</View>
</Modal>
{/* Import Wallet Modal */}
<Modal visible={importWalletModalVisible} transparent animationType="slide" onRequestClose={() => setImportWalletModalVisible(false)}>
<View style={styles.modalOverlay}>
<View style={styles.modalCard}>
<Text style={styles.modalHeader}>Import Wallet</Text>
<Text style={{color: '#666', fontSize: 12, marginBottom: 12}}>Enter your 12 or 24 word mnemonic phrase</Text>
<TextInput
style={[styles.inputField, {height: 100, textAlignVertical: 'top'}]}
placeholder="word1 word2 word3..."
multiline
value={importMnemonic}
onChangeText={setImportMnemonic}
/>
<View style={styles.modalActions}>
<TouchableOpacity style={styles.btnCancel} onPress={() => setImportWalletModalVisible(false)}><Text>Cancel</Text></TouchableOpacity>
<TouchableOpacity style={styles.btnConfirm} onPress={handleImportWallet}><Text style={{color:'white'}}>Import</Text></TouchableOpacity>
</View>
</View>
</View>
</Modal>
</SafeAreaView>
);
// Show loading while checking wallet state or redirecting
if (!selectedAccount && accounts.length === 0) {
return (
<SafeAreaView style={styles.container} testID="wallet-redirecting">
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={KurdistanColors.kesk} />
<Text style={styles.loadingText}>Loading wallet...</Text>
</View>
</SafeAreaView>
);
}
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={styles.container} testID="wallet-screen">
<StatusBar barStyle="dark-content" />
{/* Top Header with Back Button */}
<View style={styles.topHeader} testID="wallet-top-header">
<TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton} testID="wallet-back-button">
<Text style={styles.backButtonText}> Back</Text>
</TouchableOpacity>
<Text style={styles.topHeaderTitle}>Wallet</Text>
<TouchableOpacity onPress={() => setNetworkSelectorVisible(true)} testID="wallet-network-button">
<Text style={styles.networkBadge}>🌐 {NETWORKS[currentNetwork].displayName}</Text>
</TouchableOpacity>
</View>
<ScrollView
style={styles.scrollContent}
refreshControl={<RefreshControl refreshing={isLoadingBalances} onRefresh={fetchData} />}
showsVerticalScrollIndicator={false}
testID="wallet-scroll-view"
>
{/* Header */}
<View style={styles.headerContainer}>
<Text style={styles.walletTitle}>pezkuwi wallet</Text>
<TouchableOpacity onPress={() => setNetworkSelectorVisible(true)}>
<Text style={styles.networkBadge}>🌐 {NETWORKS[currentNetwork].displayName}</Text>
{/* Wallet Selector Row */}
<View style={styles.walletSelectorRow}>
<TouchableOpacity
style={styles.walletSelector}
onPress={() => setWalletSelectorVisible(true)}
testID="wallet-selector-button"
>
<View style={styles.walletSelectorInfo}>
<Text style={styles.walletSelectorName}>{selectedAccount?.name || 'Wallet'}</Text>
<Text style={styles.walletSelectorAddress} numberOfLines={1}>
{selectedAccount?.address ? `${selectedAccount.address.slice(0, 8)}...${selectedAccount.address.slice(-6)}` : ''}
</Text>
</View>
<Text style={styles.walletSelectorArrow}></Text>
</TouchableOpacity>
<View style={styles.walletHeaderButtons}>
<TouchableOpacity
style={styles.addWalletButton}
onPress={() => navigation.navigate('WalletSetup')}
testID="add-wallet-button"
>
<Text style={styles.addWalletIcon}>+</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.scanButton}
onPress={() => showAlert('Scan', 'QR Scanner coming soon')}
testID="wallet-scan-button"
>
<Text style={styles.scanIcon}></Text>
</TouchableOpacity>
</View>
</View>
{/* Main Token Cards - HEZ and PEZ side by side */}
<View style={styles.mainTokensRow}>
{/* HEZ Card */}
<TouchableOpacity style={styles.mainTokenCard} onPress={() => handleTokenPress(tokens[0])}>
<Image source={hezLogo} style={styles.mainTokenLogo} resizeMode="contain" />
<View style={styles.mainTokenLogoContainer}>
<HezTokenLogo size={56} />
</View>
<Text style={styles.mainTokenSymbol}>HEZ</Text>
<Text style={styles.mainTokenBalance}>{balances.HEZ}</Text>
<Text style={styles.mainTokenSubtitle}>Hemuwelet Token</Text>
<Text style={styles.mainTokenSubtitle}>Welati Coin</Text>
</TouchableOpacity>
{/* PEZ Card */}
<TouchableOpacity style={styles.mainTokenCard} onPress={() => handleTokenPress(tokens[1])}>
<Image source={pezLogo} style={styles.mainTokenLogo} resizeMode="contain" />
<View style={styles.mainTokenLogoContainer}>
<PezTokenLogo size={56} />
</View>
<Text style={styles.mainTokenSymbol}>PEZ</Text>
<Text style={styles.mainTokenBalance}>{balances.PEZ}</Text>
<Text style={styles.mainTokenSubtitle}>Pezkunel Token</Text>
<Text style={styles.mainTokenSubtitle}>Pezkuwichain Token</Text>
</TouchableOpacity>
</View>
{/* Action Buttons Grid - 2x4 */}
{/* Action Buttons Grid - 1x4 */}
<View style={styles.actionsGrid}>
{/* Row 1 */}
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#22C55E'}]} onPress={handleSend}>
<Text style={styles.actionIcon}></Text>
<Text style={styles.actionLabel}>Send</Text>
@@ -494,36 +495,15 @@ const WalletScreen: React.FC = () => {
<Text style={styles.actionLabel}>Receive</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#A855F7'}]} onPress={() => Alert.alert('Scan', 'QR Scanner coming soon')}>
<Text style={styles.actionIcon}></Text>
<Text style={styles.actionLabel}>Scan</Text>
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#6B7280'}]} onPress={() => navigation.navigate('Swap')}>
<Text style={styles.actionIcon}>🔄</Text>
<Text style={styles.actionLabel}>Swap</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#6B7280'}]} onPress={() => Alert.alert('P2P', 'Navigate to P2P Platform')}>
<Text style={styles.actionIcon}>👥</Text>
<Text style={styles.actionLabel}>P2P</Text>
</TouchableOpacity>
{/* Row 2 */}
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#EF4444'}]} onPress={() => Alert.alert('Vote', 'Navigate to Governance')}>
<Text style={styles.actionIcon}>🗳</Text>
<Text style={styles.actionLabel}>Vote</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#F59E0B'}]} onPress={() => Alert.alert('Dapps', 'Navigate to Apps')}>
<Text style={styles.actionIcon}></Text>
<Text style={styles.actionLabel}>Dapps</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#10B981'}]} onPress={() => Alert.alert('Staking', 'Navigate to Staking')}>
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#10B981'}]} onPress={() => showAlert('Staking', 'Navigate to Staking')}>
<Text style={styles.actionIcon}>🥩</Text>
<Text style={styles.actionLabel}>Staking</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.actionButton, {backgroundColor: '#8B5CF6'}]} onPress={() => setNetworkSelectorVisible(true)}>
<Text style={styles.actionIcon}>🔗</Text>
<Text style={styles.actionLabel}>Connect</Text>
</TouchableOpacity>
</View>
{/* Tokens List */}
@@ -630,7 +610,7 @@ const WalletScreen: React.FC = () => {
<View style={styles.modalActions}>
<TouchableOpacity style={styles.btnCancel} onPress={() => {
Clipboard.setString(userMnemonic);
Alert.alert('Copied', 'Mnemonic copied to clipboard');
showAlert('Copied', 'Mnemonic copied to clipboard');
}}>
<Text>📋 Copy</Text>
</TouchableOpacity>
@@ -642,6 +622,103 @@ const WalletScreen: React.FC = () => {
</View>
</Modal>
{/* Wallet Selector Modal */}
<Modal visible={walletSelectorVisible} transparent animationType="slide" onRequestClose={() => setWalletSelectorVisible(false)}>
<View style={styles.modalOverlay}>
<View style={styles.modalCard}>
<Text style={styles.modalHeader}>👛 My Wallets</Text>
<Text style={{color: '#666', fontSize: 12, marginBottom: 16, textAlign: 'center'}}>
Select a wallet or create a new one
</Text>
{/* Wallet List */}
{accounts.map((account) => {
const isSelected = account.address === selectedAccount?.address;
return (
<View key={account.address} style={styles.walletOptionRow}>
<TouchableOpacity
style={[
styles.walletOption,
isSelected && styles.walletOptionSelected,
{flex: 1, marginBottom: 0}
]}
onPress={() => {
setSelectedAccount(account);
setWalletSelectorVisible(false);
}}
>
<View style={styles.walletOptionIcon}>
<Text style={{fontSize: 24}}>👛</Text>
</View>
<View style={{flex: 1}}>
<Text style={[styles.walletOptionName, isSelected && {color: KurdistanColors.kesk}]}>
{account.name}
</Text>
<Text style={styles.walletOptionAddress} numberOfLines={1}>
{account.address.slice(0, 12)}...{account.address.slice(-8)}
</Text>
</View>
{isSelected && <Text style={{fontSize: 20, color: KurdistanColors.kesk}}></Text>}
</TouchableOpacity>
<TouchableOpacity
style={styles.deleteWalletButton}
onPress={async () => {
const confirmDelete = Platform.OS === 'web'
? window.confirm(`Delete "${account.name}"?\n\nThis action cannot be undone. Make sure you have backed up your recovery phrase.`)
: await new Promise<boolean>((resolve) => {
Alert.alert(
'Delete Wallet',
`Are you sure you want to delete "${account.name}"?\n\nThis action cannot be undone. Make sure you have backed up your recovery phrase.`,
[
{ text: 'Cancel', style: 'cancel', onPress: () => resolve(false) },
{ text: 'Delete', style: 'destructive', onPress: () => resolve(true) }
]
);
});
if (confirmDelete) {
try {
await deleteWallet(account.address);
if (accounts.length <= 1) {
setWalletSelectorVisible(false);
}
} catch (err) {
if (Platform.OS === 'web') {
window.alert('Failed to delete wallet');
} else {
Alert.alert('Error', 'Failed to delete wallet');
}
}
}
}}
>
<Text style={styles.deleteWalletIcon}>🗑</Text>
</TouchableOpacity>
</View>
);
})}
{/* Add New Wallet Button */}
<TouchableOpacity
style={styles.addNewWalletOption}
onPress={() => {
setWalletSelectorVisible(false);
navigation.navigate('WalletSetup');
}}
>
<View style={styles.addNewWalletIcon}>
<Text style={{fontSize: 24, color: KurdistanColors.kesk}}>+</Text>
</View>
<Text style={styles.addNewWalletText}>Add New Wallet</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btnConfirm} onPress={() => setWalletSelectorVisible(false)}>
<Text style={{color:'white'}}>Close</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
{/* Network Selector Modal */}
<Modal visible={networkSelectorVisible} transparent animationType="slide" onRequestClose={() => setNetworkSelectorVisible(false)}>
<View style={styles.modalOverlay}>
@@ -700,6 +777,42 @@ const styles = StyleSheet.create({
scrollContent: {
flex: 1,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
marginTop: 16,
fontSize: 16,
color: '#666',
},
// Top Header with Back Button
topHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: 12,
backgroundColor: '#FFFFFF',
borderBottomWidth: 1,
borderBottomColor: '#E5E5E5',
},
backButton: {
paddingVertical: 4,
paddingRight: 8,
},
backButtonText: {
fontSize: 16,
color: KurdistanColors.kesk,
fontWeight: '500',
},
topHeaderTitle: {
fontSize: 18,
fontWeight: '600',
color: '#333',
},
// Header Styles (New Design)
headerContainer: {
@@ -725,6 +838,18 @@ const styles = StyleSheet.create({
borderRadius: 16,
overflow: 'hidden',
},
scanButton: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#F5F5F5',
justifyContent: 'center',
alignItems: 'center',
},
scanIcon: {
fontSize: 20,
color: '#333',
},
// Main Token Cards (HEZ & PEZ) - New Design
mainTokensRow: {
@@ -747,6 +872,13 @@ const styles = StyleSheet.create({
height: 56,
marginBottom: 12,
},
mainTokenLogoContainer: {
width: 56,
height: 56,
marginBottom: 12,
justifyContent: 'center',
alignItems: 'center',
},
mainTokenSymbol: {
fontSize: 18,
fontWeight: 'bold',
@@ -1071,6 +1203,140 @@ const styles = StyleSheet.create({
color: '#666',
lineHeight: 18,
},
// Wallet Selector Row
walletSelectorRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 12,
marginBottom: 8,
},
walletSelector: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderRadius: 12,
padding: 12,
marginRight: 12,
boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.05)',
elevation: 2,
},
walletSelectorInfo: {
flex: 1,
},
walletSelectorName: {
fontSize: 16,
fontWeight: '600',
color: KurdistanColors.reş,
},
walletSelectorAddress: {
fontSize: 12,
color: '#999',
marginTop: 2,
},
walletSelectorArrow: {
fontSize: 12,
color: '#666',
marginLeft: 8,
},
walletHeaderButtons: {
flexDirection: 'row',
gap: 8,
},
addWalletButton: {
width: 44,
height: 44,
borderRadius: 12,
backgroundColor: '#FFFFFF',
justifyContent: 'center',
alignItems: 'center',
boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.05)',
elevation: 2,
},
addWalletIcon: {
fontSize: 24,
color: KurdistanColors.kesk,
fontWeight: '300',
},
// Wallet Selector Modal
walletOption: {
flexDirection: 'row',
alignItems: 'center',
padding: 16,
backgroundColor: '#F8F9FA',
borderRadius: 12,
marginBottom: 8,
borderWidth: 2,
borderColor: 'transparent',
},
walletOptionSelected: {
borderColor: KurdistanColors.kesk,
backgroundColor: 'rgba(0, 143, 67, 0.05)',
},
walletOptionIcon: {
width: 48,
height: 48,
borderRadius: 24,
backgroundColor: '#FFFFFF',
justifyContent: 'center',
alignItems: 'center',
marginRight: 12,
},
walletOptionName: {
fontSize: 16,
fontWeight: '600',
color: KurdistanColors.reş,
},
walletOptionAddress: {
fontSize: 12,
color: '#999',
marginTop: 2,
},
addNewWalletOption: {
flexDirection: 'row',
alignItems: 'center',
padding: 16,
backgroundColor: 'rgba(0, 143, 67, 0.05)',
borderRadius: 12,
marginBottom: 16,
borderWidth: 2,
borderColor: KurdistanColors.kesk,
borderStyle: 'dashed',
},
addNewWalletIcon: {
width: 48,
height: 48,
borderRadius: 24,
backgroundColor: '#FFFFFF',
justifyContent: 'center',
alignItems: 'center',
marginRight: 12,
},
addNewWalletText: {
fontSize: 16,
fontWeight: '600',
color: KurdistanColors.kesk,
},
// Delete wallet
walletOptionRow: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 8,
gap: 8,
},
deleteWalletButton: {
width: 44,
height: 44,
borderRadius: 12,
backgroundColor: 'rgba(239, 68, 68, 0.1)',
justifyContent: 'center',
alignItems: 'center',
},
deleteWalletIcon: {
fontSize: 18,
},
});
export default WalletScreen;
+820
View File
@@ -0,0 +1,820 @@
import React, { useState, useEffect } from 'react';
import {
View,
Text,
TouchableOpacity,
StyleSheet,
SafeAreaView,
ScrollView,
TextInput,
ActivityIndicator,
Alert,
Platform,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { LinearGradient } from 'expo-linear-gradient';
import { KurdistanColors } from '../theme/colors';
import { usePezkuwi } from '../contexts/PezkuwiContext';
import { mnemonicGenerate, mnemonicValidate } from '@pezkuwi/util-crypto';
// Cross-platform alert helper
const showAlert = (title: string, message: string, buttons?: Array<{text: string; onPress?: () => void; style?: string}>) => {
if (Platform.OS === 'web') {
window.alert(`${title}\n\n${message}`);
if (buttons?.[0]?.onPress) buttons[0].onPress();
} else {
Alert.alert(title, message, buttons as any);
}
};
type SetupStep = 'choice' | 'create-show' | 'create-verify' | 'import' | 'wallet-name' | 'success';
const WalletSetupScreen: React.FC = () => {
const navigation = useNavigation<any>();
const { createWallet, importWallet, connectWallet, isReady } = usePezkuwi();
const [step, setStep] = useState<SetupStep>('choice');
const [mnemonic, setMnemonic] = useState<string[]>([]);
const [walletName, setWalletName] = useState('');
const [importMnemonic, setImportMnemonic] = useState('');
const [verificationIndices, setVerificationIndices] = useState<number[]>([]);
const [selectedWords, setSelectedWords] = useState<{[key: number]: string}>({});
const [isLoading, setIsLoading] = useState(false);
const [createdAddress, setCreatedAddress] = useState('');
const [isCreateFlow, setIsCreateFlow] = useState(true);
// Generate mnemonic when entering create flow
const handleCreateNew = () => {
const generatedMnemonic = mnemonicGenerate(12);
setMnemonic(generatedMnemonic.split(' '));
setIsCreateFlow(true);
setStep('create-show');
};
// Go to import flow
const handleImport = () => {
setIsCreateFlow(false);
setStep('import');
};
// After showing mnemonic, go to verification
const handleMnemonicConfirmed = () => {
// Select 3 random indices for verification
const indices: number[] = [];
while (indices.length < 3) {
const randomIndex = Math.floor(Math.random() * 12);
if (!indices.includes(randomIndex)) {
indices.push(randomIndex);
}
}
indices.sort((a, b) => a - b);
setVerificationIndices(indices);
setSelectedWords({});
setStep('create-verify');
};
// Verify selected words
const handleVerifyWord = (index: number, word: string) => {
setSelectedWords(prev => ({ ...prev, [index]: word }));
};
// Check if verification is complete and correct
const isVerificationComplete = () => {
return verificationIndices.every(idx => selectedWords[idx] === mnemonic[idx]);
};
// After verification, go to wallet name
const handleVerificationComplete = () => {
if (!isVerificationComplete()) {
showAlert('Incorrect', 'The words you selected do not match. Please try again.');
setSelectedWords({});
return;
}
setStep('wallet-name');
};
// Create wallet with name
const handleCreateWallet = async () => {
if (!walletName.trim()) {
showAlert('Error', 'Please enter a wallet name');
return;
}
if (!isReady) {
showAlert('Error', 'Crypto libraries are still loading. Please wait a moment and try again.');
return;
}
setIsLoading(true);
try {
const { address } = await createWallet(walletName.trim(), mnemonic.join(' '));
setCreatedAddress(address);
await connectWallet();
setStep('success');
} catch (error: any) {
console.error('[WalletSetup] Create wallet error:', error);
showAlert('Error', error.message || 'Failed to create wallet');
} finally {
setIsLoading(false);
}
};
// Import wallet with mnemonic or dev URI (like //Alice)
const handleImportWallet = async () => {
const trimmedInput = importMnemonic.trim();
// Check if it's a dev URI (starts with //)
if (trimmedInput.startsWith('//')) {
// Dev URI like //Alice, //Bob, etc.
setMnemonic([trimmedInput]); // Store as single-element array to indicate URI
setStep('wallet-name');
return;
}
// Otherwise treat as mnemonic
const words = trimmedInput.toLowerCase().split(/\s+/);
if (words.length !== 12 && words.length !== 24) {
showAlert('Invalid Input', 'Please enter a valid 12 or 24 word recovery phrase, or a dev URI like //Alice');
return;
}
if (!mnemonicValidate(trimmedInput.toLowerCase())) {
showAlert('Invalid Mnemonic', 'The recovery phrase is invalid. Please check and try again.');
return;
}
setMnemonic(words);
setStep('wallet-name');
};
// After naming imported wallet
const handleImportComplete = async () => {
if (!walletName.trim()) {
showAlert('Error', 'Please enter a wallet name');
return;
}
if (!isReady) {
showAlert('Error', 'Crypto libraries are still loading. Please wait a moment and try again.');
return;
}
setIsLoading(true);
try {
const { address } = await importWallet(walletName.trim(), mnemonic.join(' '));
setCreatedAddress(address);
await connectWallet();
setStep('success');
} catch (error: any) {
console.error('[WalletSetup] Import wallet error:', error);
showAlert('Error', error.message || 'Failed to import wallet');
} finally {
setIsLoading(false);
}
};
// Finish setup and go to wallet
const handleFinish = () => {
navigation.replace('Wallet');
};
// Go back to previous step
const handleBack = () => {
switch (step) {
case 'create-show':
case 'import':
setStep('choice');
break;
case 'create-verify':
setStep('create-show');
break;
case 'wallet-name':
if (isCreateFlow) {
setStep('create-verify');
} else {
setStep('import');
}
break;
default:
navigation.goBack();
}
};
// Generate shuffled words for verification options
const getShuffledOptions = (correctWord: string): string[] => {
const allWords = [...mnemonic];
const options = [correctWord];
while (options.length < 4) {
const randomWord = allWords[Math.floor(Math.random() * allWords.length)];
if (!options.includes(randomWord)) {
options.push(randomWord);
}
}
// Shuffle options
return options.sort(() => Math.random() - 0.5);
};
// ============================================================
// RENDER FUNCTIONS
// ============================================================
const renderChoiceStep = () => (
<View style={styles.stepContainer} testID="wallet-setup-choice">
<View style={styles.iconContainer}>
<Text style={styles.mainIcon}>👛</Text>
</View>
<Text style={styles.title}>Set Up Your Wallet</Text>
<Text style={styles.subtitle}>
Create a new wallet or import an existing one using your recovery phrase
</Text>
<View style={styles.choiceButtons}>
<TouchableOpacity
style={styles.choiceButton}
onPress={handleCreateNew}
testID="wallet-setup-create-button"
>
<LinearGradient
colors={[KurdistanColors.kesk, '#008f43']}
style={styles.choiceButtonGradient}
>
<Text style={styles.choiceButtonIcon}></Text>
<Text style={styles.choiceButtonTitle}>Create New Wallet</Text>
<Text style={styles.choiceButtonSubtitle}>
Generate a new recovery phrase
</Text>
</LinearGradient>
</TouchableOpacity>
<TouchableOpacity
style={styles.choiceButton}
onPress={handleImport}
testID="wallet-setup-import-button"
>
<View style={styles.choiceButtonOutline}>
<Text style={styles.choiceButtonIcon}>📥</Text>
<Text style={[styles.choiceButtonTitle, { color: KurdistanColors.reş }]}>
Import Existing Wallet
</Text>
<Text style={[styles.choiceButtonSubtitle, { color: '#666' }]}>
Use your 12 or 24 word phrase
</Text>
</View>
</TouchableOpacity>
</View>
</View>
);
const renderCreateShowStep = () => (
<View style={styles.stepContainer} testID="wallet-setup-show-seed">
<Text style={styles.title}>Your Recovery Phrase</Text>
<Text style={styles.subtitle}>
Write down these 12 words in order and keep them safe. This is the only way to recover your wallet.
</Text>
<View style={styles.warningBox}>
<Text style={styles.warningIcon}></Text>
<Text style={styles.warningText}>
Never share your recovery phrase with anyone. Anyone with these words can access your funds.
</Text>
</View>
<View style={styles.mnemonicGrid} testID="mnemonic-grid">
{mnemonic.map((word, index) => (
<View key={index} style={styles.wordCard}>
<Text style={styles.wordNumber}>{index + 1}</Text>
<Text style={styles.wordText}>{word}</Text>
</View>
))}
</View>
<TouchableOpacity
style={styles.primaryButton}
onPress={handleMnemonicConfirmed}
testID="wallet-setup-continue-button"
>
<Text style={styles.primaryButtonText}>I've Written It Down</Text>
</TouchableOpacity>
</View>
);
const renderCreateVerifyStep = () => (
<View style={styles.stepContainer} testID="wallet-setup-verify-seed">
<Text style={styles.title}>Verify Your Phrase</Text>
<Text style={styles.subtitle}>
Select the correct words to verify you've saved your recovery phrase
</Text>
<View style={styles.verificationContainer}>
{verificationIndices.map((wordIndex) => (
<View key={wordIndex} style={styles.verificationItem}>
<Text style={styles.verificationLabel}>Word #{wordIndex + 1}</Text>
<View style={styles.verificationOptions}>
{getShuffledOptions(mnemonic[wordIndex]).map((option, optIdx) => (
<TouchableOpacity
key={optIdx}
style={[
styles.verificationOption,
selectedWords[wordIndex] === option && styles.verificationOptionSelected,
selectedWords[wordIndex] === option &&
selectedWords[wordIndex] === mnemonic[wordIndex] && styles.verificationOptionCorrect,
]}
onPress={() => handleVerifyWord(wordIndex, option)}
testID={`verify-option-${wordIndex}-${optIdx}`}
>
<Text style={[
styles.verificationOptionText,
selectedWords[wordIndex] === option && styles.verificationOptionTextSelected,
]}>
{option}
</Text>
</TouchableOpacity>
))}
</View>
</View>
))}
</View>
<TouchableOpacity
style={[
styles.primaryButton,
!Object.keys(selectedWords).length && styles.primaryButtonDisabled
]}
onPress={handleVerificationComplete}
disabled={Object.keys(selectedWords).length !== 3}
testID="wallet-setup-verify-button"
>
<Text style={styles.primaryButtonText}>Verify & Continue</Text>
</TouchableOpacity>
</View>
);
const renderImportStep = () => (
<View style={styles.stepContainer} testID="wallet-setup-import">
<Text style={styles.title}>Import Wallet</Text>
<Text style={styles.subtitle}>
Enter your 12 or 24 word recovery phrase, or a dev URI like //Alice
</Text>
<View style={styles.importInputContainer}>
<TextInput
style={styles.importInput}
placeholder="Enter recovery phrase or //Alice..."
placeholderTextColor="#999"
multiline
numberOfLines={4}
value={importMnemonic}
onChangeText={setImportMnemonic}
autoCapitalize="none"
autoCorrect={false}
testID="wallet-import-input"
/>
<Text style={styles.importHint}>
Mnemonic: separate words with space | Dev URI: //Alice, //Bob, etc.
</Text>
</View>
<TouchableOpacity
style={[
styles.primaryButton,
!importMnemonic.trim() && styles.primaryButtonDisabled
]}
onPress={handleImportWallet}
disabled={!importMnemonic.trim()}
testID="wallet-import-continue-button"
>
<Text style={styles.primaryButtonText}>Continue</Text>
</TouchableOpacity>
</View>
);
const renderWalletNameStep = () => (
<View style={styles.stepContainer} testID="wallet-setup-name">
<Text style={styles.title}>Name Your Wallet</Text>
<Text style={styles.subtitle}>
Give your wallet a name to easily identify it
</Text>
<View style={styles.nameInputContainer}>
<TextInput
style={styles.nameInput}
placeholder="e.g., My Main Wallet"
placeholderTextColor="#999"
value={walletName}
onChangeText={setWalletName}
autoCapitalize="words"
maxLength={30}
testID="wallet-name-input"
/>
</View>
<TouchableOpacity
style={[
styles.primaryButton,
(!walletName.trim() || isLoading) && styles.primaryButtonDisabled
]}
onPress={isCreateFlow ? handleCreateWallet : handleImportComplete}
disabled={!walletName.trim() || isLoading}
testID="wallet-setup-finish-button"
>
{isLoading ? (
<ActivityIndicator color="#FFFFFF" />
) : (
<Text style={styles.primaryButtonText}>
{isCreateFlow ? 'Create Wallet' : 'Import Wallet'}
</Text>
)}
</TouchableOpacity>
</View>
);
const renderSuccessStep = () => (
<View style={styles.stepContainer} testID="wallet-setup-success">
<View style={styles.successIconContainer}>
<Text style={styles.successIcon}></Text>
</View>
<Text style={styles.title}>Wallet Created!</Text>
<Text style={styles.subtitle}>
Your wallet is ready to use. You can now send and receive tokens.
</Text>
<View style={styles.addressBox}>
<Text style={styles.addressLabel}>Your Wallet Address</Text>
<Text style={styles.addressText} numberOfLines={1} ellipsizeMode="middle">
{createdAddress}
</Text>
</View>
<TouchableOpacity
style={styles.primaryButton}
onPress={handleFinish}
testID="wallet-setup-done-button"
>
<Text style={styles.primaryButtonText}>Go to Wallet</Text>
</TouchableOpacity>
</View>
);
const renderStep = () => {
switch (step) {
case 'choice':
return renderChoiceStep();
case 'create-show':
return renderCreateShowStep();
case 'create-verify':
return renderCreateVerifyStep();
case 'import':
return renderImportStep();
case 'wallet-name':
return renderWalletNameStep();
case 'success':
return renderSuccessStep();
default:
return renderChoiceStep();
}
};
return (
<SafeAreaView style={styles.container} testID="wallet-setup-screen">
{/* Header */}
{step !== 'choice' && step !== 'success' && (
<View style={styles.header}>
<TouchableOpacity onPress={handleBack} style={styles.backButton} testID="wallet-setup-back">
<Text style={styles.backButtonText}> Back</Text>
</TouchableOpacity>
<View style={styles.progressContainer}>
{['create-show', 'create-verify', 'wallet-name'].includes(step) && isCreateFlow && (
<>
<View style={[styles.progressDot, step === 'create-show' && styles.progressDotActive]} />
<View style={[styles.progressDot, step === 'create-verify' && styles.progressDotActive]} />
<View style={[styles.progressDot, step === 'wallet-name' && styles.progressDotActive]} />
</>
)}
{['import', 'wallet-name'].includes(step) && !isCreateFlow && (
<>
<View style={[styles.progressDot, step === 'import' && styles.progressDotActive]} />
<View style={[styles.progressDot, step === 'wallet-name' && styles.progressDotActive]} />
</>
)}
</View>
<View style={styles.headerSpacer} />
</View>
)}
{/* Close button on choice screen */}
{step === 'choice' && (
<View style={styles.header}>
<TouchableOpacity onPress={() => navigation.goBack()} style={styles.closeButton} testID="wallet-setup-close">
<Text style={styles.closeButtonText}></Text>
</TouchableOpacity>
</View>
)}
<ScrollView
style={styles.content}
contentContainerStyle={styles.contentContainer}
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps="handled"
>
{renderStep()}
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#FFFFFF',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: '#F0F0F0',
},
backButton: {
paddingVertical: 4,
paddingRight: 16,
},
backButtonText: {
fontSize: 16,
color: KurdistanColors.kesk,
fontWeight: '500',
},
closeButton: {
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: '#F5F5F5',
justifyContent: 'center',
alignItems: 'center',
},
closeButtonText: {
fontSize: 18,
color: '#666',
},
progressContainer: {
flexDirection: 'row',
gap: 8,
},
progressDot: {
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: '#E0E0E0',
},
progressDotActive: {
backgroundColor: KurdistanColors.kesk,
},
headerSpacer: {
width: 60,
},
content: {
flex: 1,
},
contentContainer: {
padding: 24,
paddingBottom: 40,
},
stepContainer: {
flex: 1,
},
iconContainer: {
alignItems: 'center',
marginBottom: 24,
marginTop: 20,
},
mainIcon: {
fontSize: 80,
},
title: {
fontSize: 28,
fontWeight: 'bold',
color: KurdistanColors.reş,
textAlign: 'center',
marginBottom: 12,
},
subtitle: {
fontSize: 16,
color: '#666',
textAlign: 'center',
lineHeight: 24,
marginBottom: 32,
},
// Choice buttons
choiceButtons: {
gap: 16,
},
choiceButton: {
borderRadius: 16,
overflow: 'hidden',
},
choiceButtonGradient: {
padding: 24,
alignItems: 'center',
},
choiceButtonOutline: {
padding: 24,
alignItems: 'center',
borderWidth: 2,
borderColor: '#E0E0E0',
borderRadius: 16,
},
choiceButtonIcon: {
fontSize: 40,
marginBottom: 12,
},
choiceButtonTitle: {
fontSize: 18,
fontWeight: '600',
color: '#FFFFFF',
marginBottom: 4,
},
choiceButtonSubtitle: {
fontSize: 14,
color: 'rgba(255,255,255,0.8)',
},
// Warning box
warningBox: {
flexDirection: 'row',
backgroundColor: '#FFF3CD',
borderRadius: 12,
padding: 16,
marginBottom: 24,
alignItems: 'flex-start',
},
warningIcon: {
fontSize: 20,
marginRight: 12,
},
warningText: {
flex: 1,
fontSize: 14,
color: '#856404',
lineHeight: 20,
},
// Mnemonic grid
mnemonicGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
marginBottom: 32,
},
wordCard: {
width: '31%',
backgroundColor: '#F8F9FA',
borderRadius: 12,
padding: 12,
marginBottom: 12,
flexDirection: 'row',
alignItems: 'center',
},
wordNumber: {
fontSize: 12,
color: '#999',
marginRight: 8,
minWidth: 20,
},
wordText: {
fontSize: 14,
fontWeight: '600',
color: KurdistanColors.reş,
},
// Verification
verificationContainer: {
marginBottom: 32,
},
verificationItem: {
marginBottom: 24,
},
verificationLabel: {
fontSize: 16,
fontWeight: '600',
color: KurdistanColors.reş,
marginBottom: 12,
},
verificationOptions: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 10,
},
verificationOption: {
paddingHorizontal: 16,
paddingVertical: 10,
borderRadius: 20,
backgroundColor: '#F5F5F5',
borderWidth: 2,
borderColor: 'transparent',
},
verificationOptionSelected: {
borderColor: KurdistanColors.kesk,
backgroundColor: 'rgba(0, 143, 67, 0.1)',
},
verificationOptionCorrect: {
borderColor: KurdistanColors.kesk,
backgroundColor: 'rgba(0, 143, 67, 0.15)',
},
verificationOptionText: {
fontSize: 14,
color: '#333',
},
verificationOptionTextSelected: {
color: KurdistanColors.kesk,
fontWeight: '600',
},
// Import
importInputContainer: {
marginBottom: 32,
},
importInput: {
backgroundColor: '#F8F9FA',
borderRadius: 16,
padding: 16,
fontSize: 16,
color: KurdistanColors.reş,
minHeight: 120,
textAlignVertical: 'top',
borderWidth: 1,
borderColor: '#E0E0E0',
},
importHint: {
fontSize: 12,
color: '#999',
marginTop: 8,
marginLeft: 4,
},
// Wallet name
nameInputContainer: {
marginBottom: 32,
},
nameInput: {
backgroundColor: '#F8F9FA',
borderRadius: 16,
padding: 16,
fontSize: 18,
color: KurdistanColors.reş,
borderWidth: 1,
borderColor: '#E0E0E0',
textAlign: 'center',
},
// Primary button
primaryButton: {
backgroundColor: KurdistanColors.kesk,
borderRadius: 16,
padding: 18,
alignItems: 'center',
},
primaryButtonDisabled: {
opacity: 0.5,
},
primaryButtonText: {
fontSize: 18,
fontWeight: '600',
color: '#FFFFFF',
},
// Success
successIconContainer: {
alignItems: 'center',
marginBottom: 24,
marginTop: 40,
},
successIcon: {
fontSize: 80,
},
addressBox: {
backgroundColor: '#F8F9FA',
borderRadius: 16,
padding: 20,
marginBottom: 32,
alignItems: 'center',
},
addressLabel: {
fontSize: 12,
color: '#999',
marginBottom: 8,
},
addressText: {
fontSize: 14,
fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
color: KurdistanColors.reş,
},
});
export default WalletSetupScreen;
-2
View File
@@ -10,7 +10,6 @@ import {
Image,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { KurdistanColors } from '../theme/colors';
import PrivacyPolicyModal from '../components/PrivacyPolicyModal';
@@ -21,7 +20,6 @@ interface WelcomeScreenProps {
}
const WelcomeScreen: React.FC<WelcomeScreenProps> = ({ onContinue }) => {
const { t } = useTranslation();
const [agreed, setAgreed] = useState(false);
const [privacyModalVisible, setPrivacyModalVisible] = useState(false);
const [termsModalVisible, setTermsModalVisible] = useState(false);
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import BeCitizenScreen from '../BeCitizenScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const BeCitizenScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<BeCitizenScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<BeCitizenScreen />
</PezkuwiProvider>
);
describe('BeCitizenScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import EducationScreen from '../EducationScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const EducationScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<EducationScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<EducationScreen />
</PezkuwiProvider>
);
describe('EducationScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { AuthProvider } from '../../contexts/AuthContext';
import ForumScreen from '../ForumScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const ForumScreenWrapper = () => (
<LanguageProvider>
<AuthProvider>
<ForumScreen />
</AuthProvider>
</LanguageProvider>
<AuthProvider>
<ForumScreen />
</AuthProvider>
);
describe('ForumScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import GovernanceScreen from '../GovernanceScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const GovernanceScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<GovernanceScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<GovernanceScreen />
</PezkuwiProvider>
);
describe('GovernanceScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { BiometricAuthProvider } from '../../contexts/BiometricAuthContext';
import LockScreen from '../LockScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const LockScreenWrapper = () => (
<LanguageProvider>
<BiometricAuthProvider>
<LockScreen />
</BiometricAuthProvider>
</LanguageProvider>
<BiometricAuthProvider>
<LockScreen />
</BiometricAuthProvider>
);
describe('LockScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import NFTGalleryScreen from '../NFTGalleryScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const NFTGalleryScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<NFTGalleryScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<NFTGalleryScreen />
</PezkuwiProvider>
);
describe('NFTGalleryScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import P2PScreen from '../P2PScreen';
@@ -11,11 +10,9 @@ jest.mock('@react-navigation/native', () => ({
// Wrapper with required providers
const P2PScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<P2PScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<P2PScreen />
</PezkuwiProvider>
);
describe('P2PScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import ProfileScreen from '../ProfileScreen';
jest.mock('@react-navigation/native', () => ({
@@ -9,9 +8,7 @@ jest.mock('@react-navigation/native', () => ({
}));
const ProfileScreenWrapper = () => (
<LanguageProvider>
<ProfileScreen />
</LanguageProvider>
<ProfileScreen />
);
describe('ProfileScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import ReferralScreen from '../ReferralScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const ReferralScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<ReferralScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<ReferralScreen />
</PezkuwiProvider>
);
describe('ReferralScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { BiometricAuthProvider } from '../../contexts/BiometricAuthContext';
import SecurityScreen from '../SecurityScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const SecurityScreenWrapper = () => (
<LanguageProvider>
<BiometricAuthProvider>
<SecurityScreen />
</BiometricAuthProvider>
</LanguageProvider>
<BiometricAuthProvider>
<SecurityScreen />
</BiometricAuthProvider>
);
describe('SecurityScreen', () => {
@@ -1,7 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { AuthProvider } from '../../contexts/AuthContext';
import { LanguageProvider } from '../../contexts/LanguageContext';
import SignInScreen from '../SignInScreen';
jest.mock('@react-navigation/native', () => ({
@@ -11,11 +10,9 @@ jest.mock('@react-navigation/native', () => ({
// Wrapper with required providers
const SignInScreenWrapper = () => (
<LanguageProvider>
<AuthProvider>
<SignInScreen />
</AuthProvider>
</LanguageProvider>
<AuthProvider>
<SignInScreen />
</AuthProvider>
);
describe('SignInScreen', () => {
@@ -1,7 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { AuthProvider } from '../../contexts/AuthContext';
import { LanguageProvider } from '../../contexts/LanguageContext';
import SignUpScreen from '../SignUpScreen';
jest.mock('@react-navigation/native', () => ({
@@ -11,11 +10,9 @@ jest.mock('@react-navigation/native', () => ({
// Wrapper with required providers
const SignUpScreenWrapper = () => (
<LanguageProvider>
<AuthProvider>
<SignUpScreen />
</AuthProvider>
</LanguageProvider>
<AuthProvider>
<SignUpScreen />
</AuthProvider>
);
describe('SignUpScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import StakingScreen from '../StakingScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const StakingScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<StakingScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<StakingScreen />
</PezkuwiProvider>
);
describe('StakingScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import SwapScreen from '../SwapScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const SwapScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<SwapScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<SwapScreen />
</PezkuwiProvider>
);
describe('SwapScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import { PezkuwiProvider } from '../contexts/PezkuwiContext';
import WalletScreen from '../WalletScreen';
@@ -10,11 +9,9 @@ jest.mock('@react-navigation/native', () => ({
}));
const WalletScreenWrapper = () => (
<LanguageProvider>
<PezkuwiProvider>
<WalletScreen />
</PezkuwiProvider>
</LanguageProvider>
<PezkuwiProvider>
<WalletScreen />
</PezkuwiProvider>
);
describe('WalletScreen', () => {
@@ -1,6 +1,5 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import { LanguageProvider } from '../../contexts/LanguageContext';
import WelcomeScreen from '../WelcomeScreen';
// Mock navigation
@@ -13,9 +12,7 @@ jest.mock('@react-navigation/native', () => ({
// Wrapper with required providers
const WelcomeScreenWrapper = () => (
<LanguageProvider>
<WelcomeScreen />
</LanguageProvider>
<WelcomeScreen />
);
describe('WelcomeScreen', () => {
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

+62
View File
@@ -0,0 +1,62 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="71.000000pt" height="74.000000pt" viewBox="0 0 71.000000 74.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,74.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M335 680 c-4 -6 -3 -16 3 -22 6 -6 12 -6 17 2 4 6 3 16 -3 22 -6 6
-12 6 -17 -2z"/>
<path d="M180 660 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M490 660 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M221 600 c-16 -9 -6 -30 15 -30 15 0 20 25 6 34 -4 2 -14 1 -21 -4z"/>
<path d="M445 601 c-8 -15 3 -31 21 -31 9 0 14 7 12 17 -4 20 -24 28 -33 14z"/>
<path d="M327 576 c-8 -20 20 -43 35 -28 14 14 3 42 -16 42 -7 0 -16 -6 -19
-14z"/>
<path d="M95 540 c-4 -6 -3 -16 3 -22 6 -6 12 -6 17 2 4 6 3 16 -3 22 -6 6
-12 6 -17 -2z"/>
<path d="M577 544 c-8 -8 1 -24 14 -24 5 0 9 7 9 15 0 15 -12 20 -23 9z"/>
<path d="M266 504 c-19 -18 -19 -20 -6 -45 14 -25 56 -25 70 1 23 44 -29 80
-64 44z"/>
<path d="M371 506 c-7 -8 -11 -25 -9 -38 2 -18 9 -23 32 -23 36 0 56 27 40 53
-14 22 -48 27 -63 8z"/>
<path d="M173 484 c-8 -22 18 -37 36 -20 7 8 10 19 7 25 -10 16 -36 13 -43 -5z"/>
<path d="M480 480 c0 -13 7 -20 20 -20 13 0 20 7 20 20 0 13 -7 20 -20 20 -13
0 -20 -7 -20 -20z"/>
<path d="M210 410 c-15 -28 4 -60 35 -60 31 0 50 32 35 60 -6 12 -21 20 -35
20 -14 0 -29 -8 -35 -20z"/>
<path d="M420 415 c-26 -32 13 -81 48 -59 22 14 27 41 12 59 -16 19 -44 19
-60 0z"/>
<path d="M104 399 c-10 -17 13 -36 27 -22 12 12 4 33 -11 33 -5 0 -12 -5 -16
-11z"/>
<path d="M560 390 c0 -11 7 -20 15 -20 8 0 15 9 15 20 0 11 -7 20 -15 20 -8 0
-15 -9 -15 -20z"/>
<path d="M30 390 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M645 390 c3 -5 10 -10 16 -10 5 0 9 5 9 10 0 6 -7 10 -16 10 -8 0
-12 -4 -9 -10z"/>
<path d="M262 324 c-20 -36 13 -73 51 -58 22 8 31 42 17 59 -17 20 -57 19 -68
-1z"/>
<path d="M364 326 c-15 -40 21 -80 54 -60 37 24 21 74 -25 74 -13 0 -26 -6
-29 -14z"/>
<path d="M181 316 c-14 -17 -7 -36 14 -36 22 0 29 20 13 36 -13 13 -16 13 -27
0z"/>
<path d="M487 324 c-15 -15 -7 -45 11 -42 9 2 17 12 17 22 0 20 -16 31 -28 20z"/>
<path d="M95 260 c-4 -6 -3 -16 3 -22 6 -6 12 -6 17 2 4 6 3 16 -3 22 -6 6
-12 6 -17 -2z"/>
<path d="M580 255 c0 -9 5 -15 11 -13 6 2 11 8 11 13 0 5 -5 11 -11 13 -6 2
-11 -4 -11 -13z"/>
<path d="M324 225 c-4 -9 -2 -21 4 -27 15 -15 44 -1 40 19 -4 23 -36 29 -44 8z"/>
<path d="M216 201 c-7 -11 18 -33 27 -24 4 3 7 12 7 20 0 15 -26 18 -34 4z"/>
<path d="M444 199 c-7 -12 15 -31 28 -23 4 3 8 12 8 20 0 17 -26 19 -36 3z"/>
<path d="M186 131 c-4 -7 -5 -15 -2 -18 9 -9 19 4 14 18 -4 11 -6 11 -12 0z"/>
<path d="M496 131 c-4 -7 -5 -15 -2 -18 9 -9 19 4 14 18 -4 11 -6 11 -12 0z"/>
<path d="M336 123 c-11 -11 -6 -23 9 -23 8 0 15 4 15 9 0 13 -16 22 -24 14z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

+235
View File
@@ -0,0 +1,235 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="466.000000pt" height="617.000000pt" viewBox="0 0 466.000000 617.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,617.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M0 3085 l0 -3085 2330 0 2330 0 0 3085 0 3085 -2330 0 -2330 0 0
-3085z m2658 2740 c119 -24 258 -66 332 -98 34 -15 38 -14 85 9 69 35 252 81
376 94 88 10 118 10 195 -4 134 -23 244 -75 244 -116 0 -32 -16 -31 -94 6 -49
23 -108 41 -167 51 -85 15 -103 15 -210 -1 -256 -35 -513 -158 -768 -366 -139
-112 -154 -130 -141 -164 l10 -27 33 28 c19 15 69 59 113 97 170 147 419 288
604 343 85 25 110 28 245 28 144 0 152 -1 212 -29 75 -34 87 -46 70 -70 -12
-16 -15 -16 -58 2 -62 27 -139 42 -212 42 -63 0 -229 -24 -248 -35 -5 -4 21
-27 58 -52 153 -103 306 -242 401 -365 36 -47 41 -60 36 -87 -4 -17 -10 -34
-14 -36 -4 -3 -39 35 -78 83 -124 155 -306 313 -458 397 l-51 28 -102 -52
c-116 -58 -182 -101 -321 -207 -92 -70 -148 -121 -139 -127 2 -1 29 -10 59
-21 30 -10 88 -33 128 -53 l73 -34 51 32 c50 32 50 32 82 15 17 -9 60 -40 96
-70 70 -56 72 -62 56 -152 -7 -38 -5 -44 32 -87 22 -25 57 -74 79 -107 85
-136 73 -125 133 -128 59 -3 77 -13 91 -51 11 -27 11 -27 -101 -115 -96 -75
-94 -75 -121 -3 -56 155 -128 268 -240 379 -128 127 -274 213 -449 264 l-85
24 -32 -37 c-17 -21 -28 -41 -25 -44 4 -4 36 -12 72 -19 248 -47 507 -245 624
-478 36 -71 86 -214 86 -245 0 -19 13 -32 58 -59 l59 -34 54 37 c37 25 56 33
61 25 4 -6 8 -45 8 -86 l0 -75 98 -95 c116 -112 227 -244 267 -317 15 -29 32
-53 37 -53 13 0 69 128 106 240 45 137 64 256 64 395 -1 184 -34 326 -126 545
-36 84 -38 108 -11 130 32 27 156 -288 190 -484 42 -243 2 -500 -121 -786
l-55 -128 29 -63 c118 -254 146 -523 71 -671 -20 -39 -36 -47 -56 -27 -8 8 -6
24 9 58 25 58 36 169 26 269 -15 158 -127 421 -255 602 -65 91 -256 300 -274
300 -5 0 -9 -16 -9 -34 0 -28 7 -40 36 -63 20 -15 47 -43 60 -63 13 -19 55
-73 93 -120 191 -232 299 -503 289 -724 -4 -83 -25 -160 -36 -128 -2 6 -9 12
-15 12 -9 0 -12 42 -13 148 0 141 -2 151 -33 237 -40 109 -104 231 -173 328
-65 91 -118 157 -128 157 -4 0 -12 -19 -19 -42 -23 -77 -35 -88 -96 -88 -64 0
-61 3 -145 -125 -33 -49 -74 -107 -92 -127 l-31 -38 16 -57 c8 -32 12 -63 9
-69 -8 -14 -160 -134 -179 -141 -7 -3 -35 9 -63 26 l-49 30 -73 -34 c-40 -19
-77 -35 -83 -35 -5 0 -34 20 -63 45 l-54 45 34 14 c113 49 157 71 221 114 143
94 276 241 350 388 42 82 85 206 93 266 5 41 3 44 -35 71 l-41 28 0 -24 c0
-104 -103 -340 -202 -463 -106 -132 -290 -259 -439 -304 -55 -17 -59 -17 -73
-1 -22 24 -20 28 15 36 153 34 346 164 467 314 92 115 182 333 182 442 0 37
-5 41 -115 106 -44 25 -81 48 -83 49 -2 1 3 14 10 28 l14 26 88 -51 c48 -27
91 -48 93 -45 3 3 2 21 -1 41 -6 31 -15 39 -81 76 -41 22 -75 42 -75 44 0 2 4
15 10 30 l10 25 51 -25 c28 -15 53 -24 55 -22 3 2 -7 40 -20 83 -66 207 -230
391 -443 498 -66 33 -241 86 -283 86 -10 0 -33 -24 -57 -60 -38 -58 -40 -59
-61 -44 -28 19 -27 23 2 67 l24 35 -31 5 c-26 5 -37 0 -57 -23 l-25 -28 -29
20 -28 21 -77 -22 c-235 -68 -418 -211 -534 -418 -29 -51 -77 -162 -77 -178 0
-2 32 -23 70 -46 70 -42 78 -51 60 -79 -8 -13 -20 -10 -80 22 -62 33 -70 35
-70 18 0 -10 -3 -25 -6 -33 -4 -11 14 -26 60 -52 63 -35 64 -37 54 -65 l-10
-29 -76 41 c-43 23 -90 50 -107 61 -89 61 -75 59 -136 21 -30 -18 -57 -34 -62
-34 -4 0 -5 35 -1 78 l6 77 -81 69 c-138 116 -346 374 -410 509 -13 26 -26 47
-30 47 -13 0 -107 -209 -134 -295 -47 -153 -60 -259 -54 -443 8 -233 47 -395
146 -593 l48 -97 -18 -33 -17 -34 -56 115 c-62 130 -116 285 -143 410 -22 106
-25 406 -5 520 21 113 90 313 148 427 l53 103 -20 57 c-74 211 -77 448 -8 560
21 33 22 34 35 14 13 -18 12 -28 -6 -81 -29 -86 -29 -240 0 -357 56 -223 193
-457 388 -664 41 -44 78 -79 82 -79 5 0 13 12 18 28 8 25 3 33 -67 107 -183
192 -312 413 -361 619 -25 102 -26 244 -4 310 16 45 17 46 31 27 11 -16 13
-37 8 -89 -8 -81 8 -197 40 -292 31 -92 33 -95 55 -75 17 15 19 14 30 -19 9
-27 8 -39 -2 -55 -11 -19 -9 -29 17 -78 41 -79 161 -236 233 -307 58 -56 60
-57 67 -35 11 34 22 39 91 39 l61 0 48 73 c27 39 82 107 123 149 l74 76 -11
52 c-6 28 -11 57 -11 64 0 17 183 136 208 136 10 0 38 -14 61 -32 l44 -32 63
23 c35 13 88 29 116 37 l53 13 47 -46 c27 -26 48 -52 48 -58 0 -5 -45 -20 -99
-33 -296 -69 -577 -305 -692 -581 l-31 -75 28 -23 c31 -24 54 -30 54 -12 0 6
15 44 34 84 129 280 383 477 689 535 51 10 60 16 87 55 27 39 28 44 13 50 -10
4 -36 30 -59 59 l-41 52 28 17 29 16 47 -55 48 -55 18 22 c17 21 16 23 -40 86
-45 52 -55 68 -46 82 13 20 86 26 179 13 l68 -9 101 84 c88 75 275 206 344
243 l24 12 -34 15 c-44 19 -184 57 -284 78 -107 23 -390 31 -522 16 -160 -19
-322 -61 -485 -128 -33 -14 -39 -14 -67 3 -17 10 -31 21 -31 24 0 17 288 114
430 145 200 43 502 43 708 0z m-1179 -194 l33 -18 -95 -52 c-144 -80 -291
-196 -421 -332 -115 -121 -116 -122 -126 -95 -5 15 -10 32 -10 38 0 24 287
294 372 351 85 57 198 125 208 126 3 0 20 -8 39 -18z m2374 -598 c15 -26 16
-35 6 -57 -16 -33 -30 -33 -49 2 -12 20 -14 35 -6 60 11 38 24 37 49 -5z m58
-460 c6 -16 13 -41 16 -56 6 -27 4 -28 -28 -25 -28 2 -35 8 -43 36 -7 26 -5
36 9 52 24 27 34 25 46 -7z m-3179 -10 c21 -19 22 -25 7 -76 -10 -36 -13 -38
-37 -32 -36 9 -35 7 -22 56 20 79 21 80 52 52z m1366 -45 c7 -7 12 -43 12 -90
0 -75 -1 -78 -24 -78 -13 0 -29 7 -36 15 -21 25 -76 19 -99 -11 -28 -35 -26
-69 4 -99 27 -28 62 -32 91 -10 10 8 29 15 42 15 20 0 22 -5 22 -53 0 -29 -5
-58 -12 -65 -17 -17 -319 -17 -336 0 -8 8 -12 64 -12 188 0 124 4 180 12 188
8 8 60 12 168 12 108 0 160 -4 168 -12z m733 2 c18 -10 19 -23 19 -188 0 -125
-4 -182 -12 -190 -17 -17 -319 -17 -336 0 -7 7 -12 36 -12 65 0 49 2 53 23 53
13 0 32 -7 43 -15 28 -21 62 -18 89 10 30 30 32 64 4 99 -23 30 -78 36 -99 11
-7 -8 -23 -15 -36 -15 -23 0 -24 2 -24 80 0 65 3 81 18 89 23 14 298 14 323 1z
m704 -97 c6 -24 1 -33 -30 -60 -21 -18 -69 -54 -107 -79 -56 -39 -71 -45 -79
-33 -19 30 -6 49 81 113 49 37 92 71 95 76 12 19 33 10 40 -17z m419 -15 c3
-13 6 -40 6 -60 0 -36 -2 -38 -30 -38 -22 0 -30 5 -30 18 0 9 -3 33 -6 54 -5
30 -3 37 12 41 36 9 42 7 48 -15z m-3236 -22 c1 -2 -1 -24 -4 -49 -6 -44 -9
-47 -35 -47 -28 0 -29 2 -29 48 0 27 3 52 7 56 6 6 53 0 61 -8z m1707 -6 c0
-12 -13 -15 -60 -15 -50 0 -60 3 -63 18 -3 16 3 18 60 15 48 -2 63 -7 63 -18z
m-389 -45 c5 -12 25 -15 93 -15 53 0 92 5 99 12 13 13 42 -6 42 -28 0 -18 -37
-37 -45 -24 -8 13 -182 13 -190 0 -3 -5 -17 -10 -30 -10 -31 0 -50 32 -35 60
13 24 58 27 66 5z m596 -10 c8 -19 8 -28 -2 -40 -14 -17 -56 -20 -65 -5 -4 6
-58 10 -131 10 -104 0 -124 2 -124 15 0 13 20 15 124 15 98 0 126 3 136 15 19
23 49 18 62 -10z m1334 -156 c-4 -39 -10 -77 -12 -84 -7 -16 -59 -4 -58 13 1
7 2 41 3 77 l1 65 36 0 37 0 -7 -71z m-3252 -10 c8 -75 2 -88 -35 -89 -18 0
-29 44 -29 118 0 40 2 42 29 42 28 0 29 -1 35 -71z m576 -29 c0 -37 -3 -42
-61 -80 -34 -22 -64 -39 -66 -36 -3 2 -6 19 -6 37 -2 28 5 38 53 75 69 54 80
55 80 4z m1148 -37 l3 -43 70 0 c55 0 69 -3 69 -15 0 -12 -17 -15 -91 -15
l-90 0 3 43 3 42 -117 3 c-97 2 -118 5 -118 18 0 12 20 14 133 12 l132 -3 3
-42z m-1011 -29 c20 -225 93 -397 236 -550 85 -91 167 -151 278 -203 l83 -39
36 30 c46 40 144 151 183 208 16 25 31 46 33 48 1 2 14 -4 28 -13 l25 -17 -26
-41 c-35 -56 -98 -132 -150 -180 -24 -22 -43 -43 -43 -47 0 -5 14 -12 32 -15
30 -7 36 -3 76 41 23 27 70 84 104 127 33 42 64 77 69 77 5 0 18 -5 28 -12 18
-11 16 -16 -29 -82 -27 -39 -68 -92 -93 -118 -40 -44 -44 -52 -26 -50 4 1 17
-10 29 -23 26 -28 26 -28 -50 -25 -51 1 -57 -1 -89 -34 -19 -20 -32 -39 -28
-42 3 -4 66 -9 139 -12 l133 -5 54 -48 c49 -44 53 -51 43 -71 -6 -13 -20 -44
-31 -70 l-20 -48 -114 0 c-123 0 -136 5 -152 60 -14 49 -34 70 -66 70 -16 0
-50 5 -75 11 -44 11 -46 11 -107 -32 -34 -24 -87 -60 -117 -81 -74 -49 -288
-162 -336 -178 -21 -7 -43 -15 -47 -18 -19 -10 210 -221 428 -394 122 -96 249
-190 362 -266 l63 -43 107 72 c219 148 492 365 685 547 105 99 108 100 138 89
16 -6 29 -16 27 -22 -7 -19 -283 -268 -427 -384 -145 -116 -321 -246 -457
-336 l-72 -47 -108 73 c-242 163 -536 397 -726 579 l-108 103 -72 -17 c-40
-10 -126 -20 -192 -23 -144 -6 -238 11 -335 59 -55 28 -65 37 -67 61 -1 15 2
27 6 27 5 0 38 -14 75 -31 97 -45 159 -59 274 -59 220 0 472 84 717 240 116
73 165 111 159 121 -2 4 -15 10 -29 13 -20 5 -41 -4 -98 -42 -211 -141 -419
-231 -611 -263 -127 -21 -320 4 -376 49 -27 22 -18 57 14 48 12 -3 55 -15 96
-26 63 -18 91 -20 170 -15 154 10 149 5 75 91 -113 129 -279 363 -362 510 -39
69 -40 72 -24 98 8 14 19 26 23 26 8 0 10 -2 91 -140 84 -145 237 -352 379
-515 l35 -39 74 28 c41 16 106 43 145 61 77 35 274 155 274 167 0 22 -44 16
-94 -12 l-56 -32 -32 23 c-18 13 -62 46 -97 73 -69 54 -65 40 -45 149 5 29 -1
40 -54 104 -55 66 -118 162 -135 206 -5 13 -18 17 -59 17 -76 0 -93 16 -123
113 -36 120 -35 125 37 183 117 94 149 116 154 111 3 -3 10 -37 15 -77 20
-145 97 -324 192 -448 89 -115 225 -226 365 -296 l52 -27 35 28 c19 16 35 31
35 34 0 4 -24 17 -52 29 -82 35 -217 128 -286 198 -147 149 -238 343 -261 552
-6 55 -4 70 9 78 23 16 35 9 37 -24z m509 -46 c82 -86 84 -91 84 -194 l0 -94
-195 0 -195 0 0 121 0 121 29 27 c49 46 90 61 166 61 70 0 71 0 111 -42z m945
22 c77 -40 79 -45 79 -185 l0 -125 -190 0 -190 0 0 94 c0 103 2 108 84 194 40
41 41 42 108 42 50 0 80 -6 109 -20z m-523 -37 l3 -43 95 0 c77 0 94 -3 94
-15 0 -12 -19 -15 -109 -15 l-110 0 -3 43 -3 42 -152 3 c-128 2 -153 5 -153
18 0 12 24 14 168 12 l167 -3 3 -42z m-110 -55 c-3 -9 -35 -14 -101 -16 -82
-2 -97 0 -97 13 0 12 17 15 101 15 76 0 100 -3 97 -12z m82 -93 c0 -12 -15
-15 -75 -15 -60 0 -75 3 -75 15 0 12 15 15 75 15 60 0 75 -3 75 -15z m1430
-516 c12 -27 11 -36 -4 -63 -56 -103 -283 -390 -399 -505 -49 -48 -58 -52 -86
-46 -17 4 -31 9 -31 12 0 3 42 51 93 107 133 144 222 255 318 400 46 69 87
125 90 126 4 0 12 -14 19 -31z m-1317 -127 c19 -21 13 -32 -16 -32 -21 0 -57
26 -57 42 0 16 57 8 73 -10z m156 -144 c25 -23 47 -45 49 -49 2 -4 -11 -10
-28 -14 -27 -6 -38 -1 -86 41 -41 34 -52 49 -42 55 28 18 62 8 107 -33z m1908
-1582 c34 -29 39 -92 9 -125 -36 -39 -117 -40 -156 -1 -23 23 -27 87 -7 112
35 44 111 51 154 14z m-2339 -247 l2 -204 118 113 117 114 50 -6 c28 -3 68 -6
89 -6 l40 0 -114 -115 c-104 -105 -112 -117 -98 -133 42 -50 228 -291 228
-296 0 -3 -42 -6 -94 -6 l-94 0 -88 110 -88 110 -33 -32 c-32 -31 -33 -35 -33
-110 l0 -78 -85 0 -85 0 0 370 0 369 68 3 c37 2 74 3 82 2 13 -1 15 -32 18
-205z m-1651 155 c64 -22 117 -65 142 -117 65 -137 12 -289 -122 -348 -42 -18
-75 -23 -174 -27 l-123 -4 0 -99 0 -99 -85 0 -85 0 0 355 0 355 200 0 c157 0
209 -3 247 -16z m631 -146 c97 -24 182 -141 182 -249 l0 -57 -205 -7 -204 -7
15 -30 c37 -71 149 -91 234 -42 l45 25 37 -43 c21 -24 38 -49 38 -55 0 -21
-71 -61 -140 -79 -115 -29 -233 0 -311 78 -110 110 -107 308 6 407 83 72 177
91 303 59z m711 6 c30 -6 31 -9 31 -55 0 -48 -2 -52 -130 -204 -71 -86 -130
-158 -130 -160 0 -3 65 -5 145 -5 l145 0 0 -65 0 -65 -255 0 -255 0 0 54 0 53
103 119 c140 163 157 184 157 195 0 5 -57 9 -130 9 l-130 0 0 65 0 65 209 0
c115 0 223 -3 240 -6z m981 -154 c0 -206 14 -244 93 -257 44 -7 100 19 118 55
10 18 16 80 19 192 l5 165 80 0 80 0 3 -277 2 -278 -80 0 -80 0 0 36 0 36 -34
-30 c-75 -65 -218 -65 -292 0 -71 63 -79 90 -82 301 -2 104 -1 195 2 203 4 10
25 14 86 14 l80 0 0 -160z m637 148 c5 -7 33 -86 62 -175 28 -90 55 -163 59
-163 4 0 31 69 60 153 77 221 60 198 143 195 l72 -3 60 -178 c35 -101 64 -172
68 -165 4 7 30 80 58 161 69 201 58 187 141 187 38 0 71 -3 73 -7 3 -5 -39
-129 -93 -278 l-98 -270 -83 -3 -84 -3 -55 166 c-30 91 -58 165 -61 165 -4 0
-32 -74 -64 -165 l-58 -166 -85 3 -86 3 -13 35 c-6 19 -48 138 -92 263 -45
126 -81 235 -81 243 0 19 143 20 157 2z m1043 -268 l0 -280 -85 0 -85 0 0 273
c0 151 3 277 7 280 3 4 42 7 85 7 l78 0 0 -280z m-2360 -775 c0 -126 -1 -135
-19 -135 -11 0 -21 5 -23 10 -2 7 -14 6 -34 -1 -66 -25 -124 16 -124 88 0 57
33 93 85 93 20 0 45 -5 56 -10 18 -10 19 -7 19 40 0 43 3 50 20 50 19 0 20 -7
20 -135z m730 0 c0 -128 -1 -135 -20 -135 -19 0 -20 7 -20 135 0 128 1 135 20
135 19 0 20 -7 20 -135z m570 121 c0 -9 -12 -16 -27 -18 -20 -2 -29 -9 -31
-25 -3 -19 1 -23 22 -23 16 0 26 -6 26 -15 0 -9 -9 -15 -25 -15 -25 0 -25 -1
-25 -80 0 -73 -2 -80 -20 -80 -18 0 -20 7 -20 80 0 62 -3 80 -14 80 -8 0 -16
7 -20 15 -4 10 1 15 14 15 14 0 20 7 20 22 0 12 7 30 17 40 20 22 83 25 83 4z
m-2578 -18 c24 -12 33 -54 19 -84 -6 -13 -29 -44 -52 -69 l-42 -45 57 0 c49 0
56 -2 56 -20 0 -19 -7 -20 -95 -20 -114 0 -119 8 -44 71 60 50 89 92 82 120
-7 27 -51 36 -84 16 -22 -12 -31 -13 -44 -3 -15 11 -15 13 -2 25 35 28 104 33
149 9z m-224 -4 c26 -18 30 -65 7 -84 -14 -12 -13 -15 5 -32 12 -12 20 -31 20
-53 0 -49 -35 -65 -140 -65 l-80 0 0 125 0 125 83 0 c59 0 89 -5 105 -16z
m512 -4 c23 -23 25 -49 6 -75 -12 -17 -12 -22 5 -44 25 -31 24 -63 -2 -87 -17
-15 -40 -20 -110 -22 l-89 -4 0 126 0 126 85 0 c72 0 88 -3 105 -20z m378 8
c-3 -7 -23 -14 -46 -16 l-42 -3 0 -110 c0 -102 -1 -109 -20 -109 -18 0 -20 8
-22 108 l-3 107 -42 3 c-29 2 -43 8 -43 18 0 11 21 14 111 14 84 0 110 -3 107
-12z m1216 -13 c32 -29 35 -82 7 -116 -15 -19 -32 -25 -83 -29 l-63 -5 -3 -38
c-3 -29 -7 -37 -23 -37 -18 0 -19 8 -19 125 l0 125 79 0 c69 0 81 -3 105 -25z
m476 -10 c0 -20 5 -25 25 -25 16 0 25 -6 25 -15 0 -9 -9 -15 -25 -15 -24 0
-25 -3 -25 -54 0 -56 17 -83 45 -72 10 4 15 -1 15 -14 0 -16 -7 -20 -32 -20
-51 0 -68 24 -68 92 0 51 -3 61 -20 65 -11 3 -20 12 -20 19 0 8 9 14 20 14 15
0 20 7 20 25 0 18 5 25 20 25 15 0 20 -7 20 -25z m-1550 -40 c0 -17 -5 -25
-18 -25 -31 0 -42 -22 -42 -87 0 -61 -1 -63 -25 -63 -28 0 -30 15 -19 129 6
50 10 61 25 61 11 0 19 -4 19 -9 0 -6 12 -3 28 5 34 18 32 18 32 -11z m697 -8
c7 -7 17 -27 22 -45 l10 -32 -80 0 c-43 0 -79 -4 -79 -8 0 -5 6 -17 14 -27 12
-17 36 -20 100 -12 29 3 30 -18 1 -31 -51 -23 -122 -5 -145 37 -27 51 10 135
63 143 29 5 77 -8 94 -25z m1672 7 c13 -12 18 -11 32 2 24 21 85 20 110 -2 16
-14 19 -31 19 -96 0 -71 -2 -78 -20 -78 -17 0 -19 8 -22 72 -3 69 -4 73 -30
82 -22 8 -32 6 -48 -9 -16 -15 -20 -30 -20 -82 0 -56 -2 -63 -20 -63 -18 0
-20 7 -20 58 0 63 -19 102 -50 102 -36 0 -50 -27 -50 -96 0 -57 -2 -64 -19
-64 -18 0 -20 9 -23 95 -3 93 -2 95 20 95 12 0 22 -5 22 -11 0 -8 4 -8 13 -1
29 24 79 22 106 -4z m-2179 -4 c16 -16 20 -33 20 -95 0 -68 -2 -75 -20 -75
-11 0 -20 5 -20 10 0 7 -6 7 -19 0 -47 -24 -111 2 -111 45 0 33 36 55 87 55
30 0 43 4 43 14 0 25 -29 39 -70 33 -22 -3 -43 -1 -46 5 -20 32 104 40 136 8z
m1222 3 c14 -13 18 -31 18 -95 0 -71 -2 -78 -20 -78 -11 0 -20 5 -20 10 0 7
-6 7 -19 0 -48 -25 -111 0 -111 44 0 38 16 49 74 54 58 5 70 18 41 42 -9 8
-30 11 -55 7 -41 -5 -63 8 -39 24 25 15 111 10 131 -8z m552 -14 c36 -43 35
-91 -3 -130 -74 -73 -203 0 -171 97 15 45 45 64 101 64 40 0 51 -4 73 -31z
m126 19 c0 -9 3 -9 12 0 17 17 58 15 58 -3 0 -8 -7 -15 -15 -15 -34 0 -55 -38
-55 -100 0 -53 -2 -60 -19 -60 -18 0 -20 9 -23 91 -2 50 -1 93 1 95 10 9 41 3
41 -8z"/>
<path d="M2326 5074 l-38 -49 29 -6 c38 -7 44 -4 71 34 27 40 27 47 3 47 -11
0 -21 5 -23 12 -2 6 -21 -10 -42 -38z"/>
<path d="M1310 4338 c0 -7 -3 -23 -6 -34 -4 -17 2 -26 31 -44 31 -19 39 -20
46 -9 18 28 9 54 -26 77 -40 25 -45 27 -45 10z"/>
<path d="M3240 4121 c0 -34 6 -44 37 -70 21 -17 41 -31 45 -31 5 0 8 18 8 40
0 35 -4 42 -45 70 l-45 31 0 -40z"/>
<path d="M2016 3177 c-39 -33 -39 -34 -15 -40 40 -11 53 -8 87 24 38 34 38 37
-4 44 -23 5 -37 -1 -68 -28z"/>
<path d="M247 1273 c-4 -3 -7 -57 -7 -120 l0 -113 86 0 c59 0 97 5 120 16 95
45 78 185 -25 214 -41 11 -164 14 -174 3z"/>
<path d="M983 1120 c-27 -16 -63 -65 -63 -85 0 -3 56 -5 125 -5 81 0 125 4
125 10 0 28 -35 73 -65 86 -47 19 -84 18 -122 -6z"/>
<path d="M2020 210 c-11 -11 -20 -31 -20 -45 0 -30 32 -65 60 -65 28 0 60 35
60 65 0 30 -32 65 -60 65 -11 0 -29 -9 -40 -20z"/>
<path d="M512 253 l3 -38 48 1 c57 0 88 24 71 52 -8 12 -27 18 -68 20 l-57 3
3 -38z"/>
<path d="M512 143 c3 -37 5 -38 44 -41 52 -4 94 12 94 36 0 31 -22 42 -83 42
l-58 0 3 -37z"/>
<path d="M1022 253 c3 -36 5 -38 38 -39 45 -1 76 10 83 30 10 27 -21 46 -74
46 l-50 0 3 -37z"/>
<path d="M1022 143 c3 -37 4 -38 49 -41 60 -4 98 23 80 56 -10 19 -20 22 -72
22 l-60 0 3 -37z"/>
<path d="M2624 276 c-3 -8 -4 -31 -2 -52 3 -38 4 -39 45 -42 32 -2 47 2 62 17
26 26 26 46 1 71 -24 24 -98 28 -106 6z"/>
<path d="M2270 211 c-15 -30 -14 -31 45 -31 38 0 55 4 55 13 0 39 -81 53 -100
18z"/>
<path d="M1785 146 c-26 -19 -13 -46 23 -46 32 0 52 16 52 42 0 22 -47 25 -75
4z"/>
<path d="M3005 146 c-26 -19 -13 -46 23 -46 33 0 57 22 48 45 -7 19 -46 20
-71 1z"/>
<path d="M3536 211 c-46 -51 13 -133 69 -97 33 22 41 60 21 91 -20 31 -65 34
-90 6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="116.000000pt" height="128.000000pt" viewBox="0 0 116.000000 128.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,128.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
</g>
</svg>

After

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

+128
View File
@@ -0,0 +1,128 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="288.000000pt" height="382.000000pt" viewBox="0 0 288.000000 382.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,382.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M0 1910 l0 -1910 1440 0 1440 0 0 1910 0 1910 -1440 0 -1440 0 0
-1910z m1643 1655 c47 -8 118 -27 158 -41 70 -25 74 -26 104 -10 89 47 276 69
367 42 55 -16 119 -58 107 -70 -3 -4 -33 6 -65 21 -51 24 -71 28 -149 28 -56
-1 -112 -8 -150 -19 -142 -43 -303 -136 -444 -260 -48 -41 -80 -62 -90 -58
-22 8 108 125 232 209 70 47 95 69 85 74 -8 4 -48 18 -89 29 -115 33 -333 39
-462 11 -54 -11 -112 -27 -130 -34 -83 -36 -88 -37 -109 -26 -11 6 -16 15 -12
19 22 21 207 78 304 93 64 10 266 6 343 -8z m640 -89 c37 -18 56 -56 20 -41
-10 5 -44 15 -77 23 -48 13 -67 13 -102 4 -25 -7 -57 -12 -72 -12 -16 0 -32
-3 -35 -6 -3 -4 25 -29 64 -56 76 -53 215 -189 224 -219 4 -10 2 -26 -3 -35
-7 -13 -15 -7 -46 34 -48 66 -131 141 -224 204 l-75 51 -56 -28 c-81 -39 -207
-125 -280 -190 -47 -42 -66 -54 -75 -45 -24 24 227 216 360 275 144 65 292 81
377 41z m-1832 -63 c-38 -137 21 -329 158 -511 85 -112 245 -252 349 -306 32
-17 44 -46 18 -46 -7 0 -30 11 -50 25 -20 14 -39 25 -42 25 -3 0 -43 30 -88
68 -127 105 -253 248 -303 347 l-21 39 -26 -51 c-57 -113 -79 -200 -83 -333
-6 -148 8 -228 63 -357 43 -105 51 -133 35 -133 -14 0 -59 94 -98 207 -26 73
-28 88 -27 248 0 159 2 175 27 248 15 43 42 107 60 143 l33 66 -20 56 c-28 78
-30 245 -3 286 24 36 31 28 18 -21z m513 41 c9 -3 16 -9 16 -14 0 -4 -38 -30
-85 -59 -50 -30 -127 -92 -184 -147 -78 -75 -100 -91 -105 -78 -13 35 136 179
270 261 38 23 70 42 71 42 1 1 8 -2 17 -5z m-454 -123 c0 -41 8 -96 21 -135
17 -56 23 -66 38 -61 22 7 36 -21 20 -41 -7 -9 -7 -19 2 -36 34 -66 100 -149
171 -217 44 -43 85 -88 91 -101 7 -14 27 -29 47 -35 60 -19 90 -38 90 -57 0
-10 -2 -18 -5 -18 -18 0 -166 111 -237 179 -185 175 -293 401 -264 555 11 59
26 41 26 -33z m1215 -331 c143 -88 268 -169 279 -179 13 -14 17 -27 12 -45
l-6 -26 -558 2 -557 3 0 33 c0 31 6 36 270 202 149 93 277 169 285 170 8 0
132 -72 275 -160z m635 74 c0 -32 -28 -31 -36 0 -3 14 -3 30 1 36 11 17 35 -8
35 -36z m101 -214 c61 -184 50 -362 -38 -568 l-35 -83 26 -58 c58 -130 73
-304 31 -368 -23 -34 -30 -18 -16 34 41 147 -44 381 -208 568 -53 60 -158 151
-233 202 -38 24 -68 51 -68 59 0 22 12 17 96 -38 108 -72 281 -244 319 -317 8
-17 19 -31 24 -31 13 0 77 176 90 244 22 118 7 277 -35 373 -44 102 -54 136
-42 151 10 11 16 6 35 -30 12 -24 37 -86 54 -138z m-66 -52 c6 -24 4 -28 -13
-28 -25 0 -35 25 -21 52 13 23 25 15 34 -24z m-1861 -26 c-4 -13 -14 -22 -25
-22 -22 0 -23 8 -9 46 9 24 13 26 25 13 9 -8 12 -23 9 -37z m1884 -80 c3 -27
0 -32 -17 -32 -17 0 -21 6 -21 36 0 28 3 35 18 32 11 -2 18 -14 20 -36z
m-1900 -9 c-2 -17 -10 -29 -20 -31 -14 -3 -18 3 -18 27 0 25 4 31 21 31 16 0
20 -5 17 -27z m1345 8 c4 -1 6 -90 5 -198 l-3 -198 -75 0 -75 0 -3 190 c-1
104 -1 194 1 200 4 8 73 11 150 6z m-665 -198 l-3 -198 -75 0 -75 0 -3 198 -2
197 80 0 80 0 -2 -197z m220 0 l-3 -198 -54 -3 c-30 -2 -65 -1 -78 3 l-23 5 0
195 0 195 80 0 80 0 -2 -197z m223 3 c0 -104 -4 -193 -9 -198 -5 -5 -38 -8
-73 -6 l-64 3 -3 198 -2 198 75 -3 76 -3 0 -189z m-991 154 c0 -5 -7 -10 -15
-10 -18 0 -20 -26 -2 -34 10 -5 10 -7 0 -12 -20 -9 -15 -24 7 -24 11 0 20 -4
20 -8 0 -4 -15 -8 -34 -8 l-34 0 3 44 c3 43 16 62 43 62 6 0 12 -4 12 -10z
m1655 -27 c-4 -10 -7 -28 -6 -41 0 -13 -5 -29 -12 -37 -20 -20 -42 4 -43 48
-1 36 10 50 19 25 3 -10 10 -8 23 5 10 9 20 17 22 17 2 0 1 -8 -3 -17z m-1791
-19 c12 -30 7 -84 -8 -84 -17 0 -26 21 -26 59 0 41 22 57 34 25z m1904 -31
c-2 -35 -7 -48 -18 -48 -11 0 -16 13 -18 48 -3 42 -1 47 18 47 19 0 21 -5 18
-47z m-412 -58 c78 -53 210 -185 263 -263 94 -140 142 -291 127 -397 -11 -69
-32 -53 -28 21 4 74 -10 136 -50 222 -68 145 -182 280 -320 380 -50 35 -78 62
-78 74 0 21 -3 23 86 -37z m-1207 -265 c6 0 11 5 11 10 0 6 4 10 8 10 15 0 8
-74 -7 -86 -27 -21 -49 4 -48 54 0 37 2 42 12 28 7 -9 17 -16 24 -16z m1341
10 c0 -5 -9 -10 -19 -10 -28 0 -37 -20 -9 -21 23 -1 23 -1 -2 -9 l-25 -8 25
-2 c24 -3 24 -3 2 -7 -26 -5 -20 -23 9 -23 10 0 19 -4 19 -10 0 -17 -46 -11
-62 8 -25 28 -26 45 -4 69 20 23 66 32 66 13z m-202 -19 c8 -5 12 -17 10 -27
-3 -18 -23 -19 -491 -22 -427 -2 -488 0 -493 13 -4 8 -4 22 0 30 5 13 68 15
483 15 263 0 484 -4 491 -9z m-1287 -174 c82 -128 197 -267 220 -267 28 0 161
64 240 115 83 54 178 127 178 138 1 4 -84 7 -188 7 -203 0 -216 3 -209 52 l3
23 557 3 558 2 6 -26 c13 -51 -4 -54 -293 -54 l-264 0 -92 -81 c-50 -45 -124
-103 -162 -129 -61 -41 -210 -125 -255 -143 -11 -4 -2 -18 35 -52 86 -80 216
-188 315 -261 150 -111 126 -107 222 -42 110 75 297 224 378 302 42 40 71 61
83 59 9 -3 17 -8 17 -13 0 -9 -114 -118 -201 -190 -75 -62 -220 -170 -302
-225 l-57 -38 -68 45 c-89 59 -249 185 -341 267 -155 139 -150 135 -177 122
-41 -18 -217 -15 -274 5 -53 19 -98 49 -88 59 3 4 39 -5 80 -20 65 -24 83 -26
163 -22 138 8 287 64 430 160 75 51 182 136 214 171 l24 26 -30 0 c-19 0 -38
-9 -54 -26 -40 -44 -200 -158 -279 -201 -126 -68 -199 -88 -320 -88 -86 0
-111 3 -134 18 -41 28 -19 39 41 21 39 -11 69 -13 117 -7 l65 8 -87 112 c-48
61 -109 148 -136 192 -42 70 -47 83 -35 97 12 15 14 15 24 -1 5 -9 40 -63 76
-118z m1649 8 c0 -47 -243 -345 -281 -345 -10 0 -19 4 -19 9 0 5 30 42 66 82
82 91 141 168 183 237 33 53 51 59 51 17z m-360 -94 c0 -5 -7 -11 -15 -15 -21
-8 -19 -26 3 -26 15 -1 15 -2 -3 -16 -19 -14 -19 -15 3 -20 34 -9 26 -22 -12
-21 -33 1 -34 2 -30 40 2 22 9 46 15 53 13 16 39 19 39 5z m798 -1039 c16 -22
15 -42 -5 -64 -21 -24 -58 -23 -83 2 -23 23 -25 40 -7 62 24 31 70 31 95 0z
m-1368 -135 l5 -118 65 66 c61 62 67 65 112 65 26 0 48 -3 48 -6 0 -4 -27 -35
-60 -71 l-61 -64 64 -82 c89 -114 87 -107 23 -107 l-54 0 -52 65 c-50 62 -53
65 -71 49 -11 -10 -19 -33 -21 -63 l-3 -46 -47 -3 -48 -3 0 221 0 221 48 -3
47 -3 5 -118z m-969 93 c19 -5 48 -23 64 -40 23 -24 29 -41 33 -87 3 -49 0
-64 -20 -93 -32 -47 -68 -63 -158 -69 l-75 -6 0 -55 0 -55 -52 -3 -53 -3 0
210 0 211 113 0 c61 0 128 -5 148 -10z m399 -102 c48 -33 72 -70 77 -122 l6
-46 -122 0 c-66 0 -121 -4 -121 -8 0 -13 43 -49 66 -56 12 -4 40 1 63 10 41
16 43 16 66 -6 20 -18 22 -26 13 -37 -41 -50 -155 -59 -225 -18 -110 65 -104
232 9 288 49 25 128 22 168 -5z m408 -9 c2 -21 -14 -47 -72 -118 -42 -50 -76
-93 -76 -96 0 -3 36 -5 80 -5 l80 0 0 -40 0 -40 -150 0 -150 0 0 29 c0 22 20
52 80 123 l80 93 -78 5 c-71 5 -77 7 -80 28 -8 51 -3 53 145 50 l138 -3 3 -26z
m552 -65 c0 -100 7 -127 41 -145 25 -13 74 4 84 29 4 10 10 61 13 115 l5 98
46 -3 46 -3 0 -160 0 -160 -47 -3 c-38 -2 -48 0 -48 12 0 20 -9 20 -34 1 -12
-9 -42 -15 -72 -15 -42 0 -59 5 -83 26 -40 33 -51 77 -51 202 l0 102 50 0 50
0 0 -96z m400 11 c33 -102 39 -119 45 -113 3 3 20 47 39 99 l33 94 43 0 43 0
28 -80 c48 -142 41 -140 81 -24 l35 104 38 3 c21 2 41 0 46 -5 4 -4 -18 -78
-50 -163 l-57 -155 -48 0 -48 0 -30 85 c-16 47 -33 88 -36 92 -4 4 -22 -35
-41 -87 l-33 -95 -48 0 -48 0 -56 158 c-31 86 -56 161 -56 165 0 4 21 7 47 5
l47 -3 26 -80z m580 -80 l0 -165 -50 0 -50 0 0 158 c0 87 3 162 7 165 3 4 26
7 50 7 l43 0 0 -165z m-940 -419 c0 -41 4 -77 8 -80 5 -3 26 13 47 34 22 22
47 40 57 40 25 0 23 -9 -13 -46 l-31 -32 37 -49 c32 -41 34 -48 19 -52 -12 -2
-30 11 -51 35 -27 33 -35 37 -50 28 -10 -6 -19 -25 -21 -43 -3 -24 -8 -31 -20
-29 -15 3 -17 21 -20 136 -2 127 -2 132 18 132 18 0 20 -6 20 -74z m-618 42
c23 -19 29 -50 15 -78 -11 -22 -11 -29 7 -53 16 -22 18 -33 10 -55 -12 -35
-57 -51 -146 -51 l-68 -1 0 125 0 125 83 0 c51 0 89 -5 99 -12z m234 -69 c15
-17 19 -35 17 -91 -2 -76 -6 -87 -26 -69 -10 8 -22 8 -46 0 -36 -13 -85 2 -96
28 -16 42 23 73 91 73 31 0 35 3 32 23 -3 20 -8 22 -55 21 -38 -1 -53 2 -53
11 0 18 16 23 71 24 35 1 51 -4 65 -20z m129 11 c4 -7 12 -7 25 0 29 15 81 12
102 -7 14 -13 18 -31 18 -95 0 -43 -2 -78 -4 -78 -28 0 -36 16 -36 76 0 59 -2
65 -25 76 -19 8 -31 8 -50 0 -23 -11 -25 -17 -25 -77 0 -58 -2 -65 -20 -65
-19 0 -20 7 -20 90 0 72 3 90 14 90 8 0 18 -5 21 -10z"/>
<path d="M1817 2663 c-11 -11 -8 -313 3 -313 6 0 10 60 10 160 0 88 -1 160 -3
160 -2 0 -7 -3 -10 -7z"/>
<path d="M1075 2659 c-10 -26 -1 -304 10 -302 14 4 19 293 6 306 -7 7 -12 5
-16 -4z"/>
<path d="M246 824 c-8 -20 -7 -72 1 -103 5 -21 10 -23 59 -19 89 8 122 61 69
113 -19 20 -34 25 -73 25 -36 0 -52 -4 -56 -16z"/>
<path d="M665 735 c-39 -38 -32 -45 45 -45 63 0 70 2 70 19 0 24 -36 51 -68
51 -12 0 -34 -11 -47 -25z"/>
<path d="M1042 233 c3 -36 5 -38 38 -41 37 -2 81 15 87 34 8 24 -28 44 -78 44
l-50 0 3 -37z"/>
<path d="M1052 161 c-8 -5 -12 -22 -10 -42 3 -29 7 -34 32 -37 83 -10 134 31
86 70 -23 19 -85 24 -108 9z"/>
<path d="M1322 131 c-21 -13 -10 -46 16 -49 28 -4 52 14 52 39 0 14 -7 19 -27
19 -16 0 -34 -4 -41 -9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

+273
View File
@@ -0,0 +1,273 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="2048.000000pt" height="2048.000000pt" viewBox="0 0 2048.000000 2048.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,2048.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M10078 18595 c-2 -1 -86 -5 -188 -9 -354 -12 -1016 -89 -1260 -147
-47 -11 -130 -29 -185 -40 -264 -54 -436 -101 -830 -229 -505 -164 -947 -363
-1560 -704 -11 -6 -47 -29 -80 -50 -33 -22 -80 -50 -105 -64 -38 -22 -235
-151 -415 -272 -48 -33 -199 -145 -239 -177 -11 -9 -47 -37 -80 -62 -34 -25
-63 -48 -66 -51 -3 -3 -32 -27 -65 -52 -55 -43 -109 -88 -160 -136 -11 -10
-38 -31 -60 -47 -22 -16 -42 -31 -45 -34 -3 -4 -50 -46 -105 -96 -55 -49 -104
-96 -108 -103 -5 -7 -15 -18 -24 -25 -35 -26 -354 -348 -448 -452 -220 -243
-424 -492 -566 -690 -35 -49 -74 -103 -86 -120 -121 -168 -413 -628 -413 -649
0 -4 -12 -25 -27 -49 -67 -105 -235 -425 -301 -572 -88 -199 -152 -347 -186
-433 -88 -222 -132 -344 -151 -412 -7 -25 -29 -97 -50 -160 -82 -259 -107
-347 -151 -526 -25 -103 -48 -197 -50 -208 -20 -90 -75 -403 -89 -496 -9 -63
-18 -126 -20 -140 -9 -56 -50 -459 -59 -585 -19 -240 -25 -782 -11 -1000 3
-55 8 -136 11 -180 15 -246 92 -815 144 -1070 113 -551 317 -1193 536 -1682
145 -325 362 -735 529 -1003 82 -130 380 -569 394 -580 4 -3 46 -57 93 -120
48 -63 117 -153 153 -200 217 -277 695 -769 985 -1014 14 -11 59 -50 101 -86
42 -36 85 -72 95 -80 11 -8 48 -38 84 -67 485 -388 985 -707 1535 -977 433
-213 671 -312 1075 -445 309 -103 439 -140 775 -219 227 -54 502 -103 770
-137 28 -4 59 -8 70 -10 148 -22 270 -35 550 -55 118 -8 887 -5 955 4 19 2 71
7 115 10 104 7 264 24 340 36 33 5 80 12 105 15 420 56 906 156 1181 241 25 8
54 16 65 19 10 2 55 15 99 30 44 14 127 41 185 60 150 48 394 138 550 203 377
158 777 359 1105 556 33 20 77 46 98 58 96 56 532 352 622 421 370 286 477
376 774 652 170 158 510 515 585 613 11 15 36 45 55 68 44 50 68 79 103 126
15 20 34 42 41 50 91 93 472 635 630 898 159 266 346 621 449 855 20 44 54
122 77 173 165 370 389 1072 466 1457 8 39 25 124 39 190 21 102 34 180 61
370 5 35 13 105 19 155 2 19 7 46 10 60 5 25 10 66 21 190 3 36 10 115 15 175
20 220 25 346 25 660 0 286 -8 557 -20 625 -2 14 -6 61 -9 105 -6 71 -15 166
-32 305 -29 253 -82 570 -125 755 -17 72 -40 171 -51 220 -78 344 -293 991
-418 1262 -18 37 -41 91 -52 118 -29 75 -264 547 -317 639 -26 45 -74 127
-107 184 -107 187 -123 212 -181 298 -32 47 -74 111 -94 143 -53 85 -140 196
-151 193 -5 -1 -7 2 -3 8 5 8 -89 146 -153 225 -4 6 -54 69 -112 140 -57 72
-108 135 -114 140 -6 6 -36 39 -66 75 -98 117 -222 253 -360 394 -152 156
-262 262 -366 355 -27 25 -74 68 -104 95 -31 28 -76 67 -100 86 -25 19 -85 69
-135 110 -102 85 -94 78 -200 163 -241 192 -688 484 -1090 712 -242 137 -882
434 -995 461 -3 0 -14 4 -25 9 -270 106 -404 150 -780 260 -27 8 -129 33 -225
55 -96 22 -184 43 -195 45 -192 49 -632 118 -915 145 -63 6 -131 13 -150 15
-126 15 -362 27 -592 30 -147 2 -268 2 -270 0z m687 -454 c289 -20 640 -65
905 -116 69 -13 141 -27 160 -30 221 -38 696 -172 1060 -299 142 -50 142 -50
234 -90 32 -14 63 -26 69 -26 5 0 39 -13 74 -30 34 -16 65 -30 68 -30 20 0
534 -253 705 -346 47 -26 159 -92 250 -146 91 -54 174 -104 185 -111 11 -7 22
-14 25 -17 3 -3 73 -50 155 -105 83 -54 156 -105 163 -112 8 -7 22 -18 32 -23
40 -21 344 -258 470 -366 14 -12 57 -48 95 -82 39 -33 96 -81 127 -108 68 -59
515 -510 609 -615 55 -61 185 -215 236 -279 266 -332 541 -732 698 -1013 17
-30 35 -61 41 -68 6 -8 42 -72 79 -144 37 -71 82 -157 101 -190 42 -77 163
-339 221 -480 25 -60 51 -123 58 -140 73 -161 236 -651 305 -915 50 -192 94
-403 144 -690 39 -220 40 -229 65 -455 11 -99 23 -220 26 -270 4 -49 8 -106
11 -125 2 -19 6 -161 10 -315 6 -245 -4 -600 -21 -790 -13 -137 -36 -363 -40
-390 -3 -16 -14 -91 -25 -165 -66 -459 -176 -911 -335 -1385 -184 -551 -473
-1154 -788 -1645 -233 -364 -409 -604 -654 -891 -297 -349 -744 -790 -1038
-1025 -33 -26 -80 -64 -105 -84 -191 -155 -560 -412 -807 -562 -252 -153 -648
-360 -923 -482 -58 -26 -118 -53 -135 -61 -132 -60 -582 -223 -730 -265 -16
-5 -77 -22 -135 -40 -364 -107 -791 -195 -1195 -246 -22 -2 -51 -7 -65 -9 -14
-2 -54 -7 -90 -10 -36 -3 -76 -8 -90 -10 -14 -2 -77 -7 -140 -11 -63 -4 -164
-10 -225 -14 -280 -18 -989 3 -1185 35 -14 2 -50 7 -80 10 -290 31 -831 131
-1078 200 -219 62 -398 114 -462 136 -156 52 -447 159 -525 194 -16 7 -64 28
-105 45 -41 18 -154 70 -250 115 -96 45 -202 95 -235 110 -33 15 -89 44 -125
65 -36 21 -101 57 -145 80 -87 46 -496 291 -517 310 -7 6 -44 31 -83 57 -68
44 -185 128 -330 236 -63 46 -274 218 -425 344 -171 143 -599 570 -786 783
-209 239 -484 599 -645 845 -333 506 -663 1163 -834 1655 -26 74 -58 166 -71
204 -29 81 -140 472 -183 642 -65 260 -154 800 -177 1069 -3 39 -7 80 -9 93
-2 12 -7 86 -10 165 -4 78 -8 148 -11 156 -5 17 -5 717 0 751 2 14 7 77 11
140 11 195 45 529 65 645 5 28 12 68 15 90 3 22 7 47 10 55 2 8 6 33 10 55 20
147 85 448 135 630 17 61 43 157 59 215 64 233 175 543 291 815 28 66 64 152
80 190 92 229 338 688 520 975 25 39 56 89 70 110 52 83 187 276 225 325 23
27 63 81 90 119 85 119 224 293 385 480 157 183 573 594 730 722 19 16 41 34
48 41 7 7 34 29 59 50 26 21 61 51 78 67 16 15 66 56 110 89 44 34 85 65 90
69 132 103 165 127 190 143 17 11 32 22 35 25 8 9 178 123 208 140 15 8 29 18
30 23 2 4 8 7 12 7 5 0 29 14 52 31 94 66 221 147 322 204 58 33 143 82 189
108 108 63 518 265 654 322 59 25 117 50 128 55 113 54 611 230 775 274 30 8
96 26 145 40 152 41 289 78 310 82 11 2 54 11 95 19 41 8 86 17 100 20 49 10
246 46 280 51 19 3 89 14 155 24 143 22 349 47 460 55 44 4 96 8 115 10 19 2
118 7 220 11 102 4 187 8 189 10 7 6 537 -5 686 -15z"/>
<path d="M10060 17997 c-3 -2 -86 -7 -185 -10 -272 -10 -399 -21 -700 -63
-465 -65 -1007 -188 -1320 -299 -55 -20 -145 -51 -200 -70 -173 -58 -320 -116
-472 -186 -24 -10 -45 -19 -48 -19 -8 0 -199 -92 -408 -196 -186 -94 -470
-257 -462 -266 3 -3 -1 -5 -7 -5 -33 0 -548 -342 -669 -443 -9 -8 -30 -24 -45
-35 -86 -63 -355 -283 -439 -360 -55 -49 -121 -110 -148 -135 -28 -25 -57 -53
-66 -64 -9 -10 -22 -24 -30 -30 -21 -17 -289 -285 -346 -347 -83 -90 -134
-156 -127 -164 4 -5 2 -5 -5 -1 -14 8 -45 -33 -36 -47 3 -6 2 -7 -4 -4 -19 12
-294 -325 -445 -549 -30 -43 -84 -122 -121 -176 -37 -53 -67 -101 -67 -106 0
-6 -4 -12 -9 -14 -5 -1 -39 -52 -75 -113 -37 -60 -71 -117 -76 -125 -6 -8 -14
-24 -19 -36 -5 -12 -25 -45 -44 -75 -91 -143 -342 -659 -431 -889 -21 -52 -47
-117 -58 -145 -122 -294 -299 -906 -367 -1265 -62 -326 -108 -673 -126 -950
-4 -52 -9 -111 -11 -130 -9 -74 -12 -722 -4 -850 28 -418 73 -763 154 -1180
32 -160 54 -253 131 -535 36 -133 155 -498 166 -509 5 -6 9 -16 9 -23 0 -32
199 -507 308 -734 66 -137 176 -343 257 -479 18 -30 51 -86 74 -125 98 -170
344 -536 420 -627 6 -7 51 -65 99 -129 96 -127 212 -270 252 -309 14 -14 37
-41 51 -60 93 -123 506 -533 734 -729 133 -114 172 -147 260 -217 210 -166
626 -464 649 -464 3 0 27 -15 53 -34 47 -33 355 -213 461 -269 28 -16 52 -25
52 -20 0 4 4 3 8 -4 9 -14 364 -193 512 -258 165 -72 499 -202 541 -210 9 -2
30 -10 46 -18 15 -8 42 -18 58 -22 17 -5 35 -9 40 -11 6 -1 53 -17 105 -34 52
-17 136 -42 185 -56 50 -14 97 -27 105 -29 313 -88 951 -208 1225 -230 44 -4
91 -8 105 -10 158 -24 861 -37 1115 -21 99 6 343 27 485 42 46 5 258 38 375
59 438 79 436 78 762 167 45 12 79 26 76 32 -3 5 -1 6 5 2 30 -18 657 195 868
295 22 10 43 19 47 19 15 0 440 206 612 298 202 106 429 242 590 352 241 164
345 237 475 337 42 32 226 178 230 183 3 3 41 36 85 74 181 156 409 367 489
455 17 18 58 61 91 96 59 61 184 197 225 245 12 14 31 36 43 50 148 172 183
216 331 415 53 72 99 135 104 140 4 6 27 39 51 75 25 36 47 67 50 70 20 18
226 347 319 510 11 19 36 64 57 100 61 105 259 507 305 615 22 55 64 154 92
220 89 213 198 525 249 710 134 494 191 765 244 1155 3 25 10 77 15 115 5 39
12 104 15 145 4 41 8 86 10 100 32 227 38 989 10 1245 -2 22 -7 69 -10 105 -3
36 -10 103 -15 150 -6 47 -12 108 -15 135 -3 28 -10 77 -15 110 -5 33 -12 80
-15 105 -3 25 -11 70 -17 100 -6 30 -12 62 -13 70 -1 8 -5 29 -8 45 -4 17 -9
46 -12 65 -5 33 -30 170 -39 215 -30 150 -146 577 -201 740 -22 63 -88 250
-129 365 -14 38 -66 166 -96 235 -92 213 -130 294 -222 475 -101 197 -136 262
-224 412 -17 29 -47 81 -66 114 -34 60 -227 354 -238 364 -3 3 -30 41 -59 85
-127 187 -232 323 -440 565 -35 41 -75 89 -89 105 -144 171 -514 538 -732 725
-35 30 -71 62 -79 70 -15 13 -83 70 -135 110 -10 8 -39 32 -64 53 -25 21 -57
46 -71 55 -14 9 -37 27 -51 39 -14 13 -28 23 -31 23 -3 0 -22 13 -40 30 -19
16 -37 30 -41 30 -4 0 -13 6 -20 13 -18 18 -94 72 -273 192 -349 235 -748 453
-1220 665 -104 47 -365 149 -480 188 -66 23 -153 53 -192 67 -70 24 -121 39
-443 126 -185 51 -441 104 -690 144 -19 3 -57 10 -85 15 -56 11 -319 45 -410
54 -209 20 -922 45 -935 33z m575 -461 c17 -2 82 -7 145 -10 102 -6 154 -11
345 -31 74 -8 198 -25 226 -30 13 -3 51 -10 84 -16 168 -30 472 -93 579 -120
257 -65 724 -215 853 -274 17 -8 34 -15 38 -15 35 0 595 -263 805 -378 177
-97 434 -250 519 -310 417 -291 523 -372 836 -640 186 -159 590 -568 720 -728
22 -27 50 -60 63 -74 31 -34 236 -299 297 -384 113 -158 187 -265 227 -330 24
-37 55 -87 70 -110 26 -39 46 -73 119 -199 19 -32 39 -66 44 -75 95 -158 295
-563 362 -732 14 -36 35 -85 46 -110 11 -25 30 -74 43 -110 12 -36 32 -90 44
-120 115 -294 263 -838 315 -1160 3 -19 8 -48 10 -65 3 -16 10 -50 15 -75 5
-25 17 -98 25 -162 9 -65 18 -126 20 -137 2 -11 7 -51 10 -88 4 -37 9 -70 10
-73 2 -3 6 -61 10 -130 4 -69 9 -134 11 -145 2 -11 7 -153 10 -315 10 -452
-18 -894 -82 -1275 -13 -82 -27 -163 -30 -180 -14 -86 -87 -432 -108 -510 -56
-213 -143 -495 -216 -695 -83 -229 -88 -241 -132 -338 -15 -34 -28 -64 -28
-67 0 -3 -16 -40 -36 -82 -20 -43 -43 -96 -52 -118 -8 -22 -18 -44 -22 -50 -5
-5 -41 -75 -82 -155 -226 -438 -544 -931 -788 -1220 -26 -30 -91 -109 -145
-175 -196 -239 -592 -642 -781 -796 -44 -35 -88 -72 -99 -82 -43 -40 -333
-268 -415 -327 -304 -217 -605 -403 -917 -566 -60 -31 -112 -60 -118 -64 -5
-4 -48 -24 -95 -45 -47 -21 -121 -56 -165 -77 -170 -83 -738 -294 -910 -338
-16 -5 -100 -28 -186 -53 -86 -25 -194 -53 -240 -62 -46 -9 -133 -27 -194 -40
-114 -25 -362 -69 -450 -79 -27 -4 -61 -8 -75 -11 -49 -9 -337 -35 -475 -42
-308 -17 -968 -5 -1205 22 -42 5 -113 12 -195 20 -32 4 -62 8 -65 10 -3 2 -29
6 -58 10 -228 29 -684 127 -917 197 -55 16 -122 36 -150 44 -63 17 -391 131
-510 177 -490 188 -1026 473 -1499 797 -139 95 -529 393 -576 440 -3 3 -23 20
-45 39 -107 90 -246 221 -405 380 -184 185 -198 200 -350 376 -52 61 -97 112
-100 115 -8 8 -233 292 -261 330 -86 117 -247 355 -331 490 -43 69 -83 132
-88 140 -47 67 -324 612 -390 765 -88 204 -100 234 -164 407 -89 239 -182 546
-256 848 -28 110 -97 462 -109 556 -7 44 -13 89 -15 100 -5 25 -14 95 -21 169
-4 33 -8 69 -10 81 -2 11 -6 65 -10 120 -4 54 -9 102 -11 106 -6 9 -19 401
-19 548 0 129 13 482 19 520 3 14 7 68 11 120 3 52 8 104 10 115 2 11 7 49 10
85 3 36 8 79 10 95 40 296 60 412 112 655 20 91 37 172 38 180 3 23 49 180
117 398 11 34 21 68 22 75 4 21 36 119 66 197 16 41 47 127 70 190 37 101 106
259 214 495 18 39 41 89 51 113 10 23 22 42 27 42 4 0 8 9 8 19 0 11 3 21 8
23 4 2 23 35 42 73 36 72 141 257 202 355 19 30 45 75 59 100 13 25 27 49 32
55 4 5 50 74 103 153 127 192 220 319 324 446 19 24 49 60 65 82 34 44 136
167 145 174 3 3 16 18 29 35 12 16 55 64 94 106 40 41 106 113 147 158 41 46
97 104 125 129 88 83 115 112 115 123 0 5 4 8 9 4 5 -3 18 6 29 20 11 14 23
25 27 25 4 0 37 29 74 64 36 36 84 78 106 94 22 16 51 40 65 53 45 42 154 134
192 162 20 15 42 33 50 40 7 7 29 24 48 37 19 13 40 29 46 35 6 5 22 17 34 25
13 8 35 24 49 35 14 12 61 45 104 75 43 30 104 73 135 95 32 23 79 54 106 70
27 17 60 38 75 47 14 10 37 24 51 32 14 8 49 30 79 50 29 20 56 36 60 36 4 0
59 31 122 68 93 56 558 292 574 292 2 0 48 21 102 46 104 48 110 51 408 161
429 160 871 273 1370 353 132 21 141 22 365 45 85 8 175 17 200 19 25 3 104 8
175 12 72 3 132 8 134 10 5 5 596 -5 636 -10z"/>
<path d="M9965 17209 c-104 -4 -244 -12 -310 -18 -66 -6 -149 -14 -185 -17
-101 -9 -425 -58 -585 -89 -287 -55 -411 -88 -845 -224 -368 -115 -910 -357
-1246 -556 -18 -11 -53 -30 -76 -43 -24 -13 -72 -42 -108 -65 -36 -22 -98 -61
-138 -86 -40 -25 -100 -65 -132 -88 -33 -24 -90 -64 -127 -89 -104 -72 -208
-150 -317 -239 -54 -44 -110 -89 -125 -100 -33 -24 -241 -211 -291 -260 -19
-19 -38 -35 -42 -35 -5 0 -8 -7 -8 -16 0 -8 -3 -13 -8 -11 -11 7 -311 -299
-410 -418 -18 -22 -46 -56 -62 -75 -16 -19 -55 -66 -87 -105 -32 -38 -65 -77
-74 -85 -35 -34 -315 -412 -359 -485 -13 -22 -50 -80 -82 -128 -32 -48 -58
-90 -58 -93 0 -3 -13 -25 -30 -49 -16 -24 -30 -46 -30 -49 0 -4 -18 -37 -41
-74 -43 -70 -143 -256 -215 -402 -47 -95 -204 -439 -204 -448 0 -8 -60 -164
-71 -185 -13 -24 -78 -221 -119 -357 -17 -58 -40 -130 -50 -160 -27 -79 -75
-271 -99 -391 -11 -57 -34 -169 -50 -249 -27 -136 -53 -288 -65 -390 -3 -25
-8 -65 -11 -90 -3 -25 -12 -129 -20 -230 -16 -217 -14 -1077 4 -1230 6 -52 13
-120 16 -150 3 -30 7 -71 10 -90 3 -19 7 -55 10 -80 8 -63 23 -145 51 -290 14
-69 27 -136 30 -150 19 -94 89 -384 108 -448 13 -42 45 -147 70 -232 103 -350
252 -715 443 -1088 247 -483 611 -1019 936 -1382 327 -364 509 -541 857 -831
221 -184 493 -378 782 -557 200 -124 634 -351 813 -425 33 -14 109 -46 169
-71 60 -25 113 -43 118 -40 4 3 8 1 8 -5 0 -5 10 -12 23 -16 12 -3 31 -10 42
-15 72 -30 170 -64 305 -105 85 -26 180 -55 211 -66 57 -19 398 -103 454 -112
17 -3 71 -14 121 -26 102 -23 418 -77 509 -86 33 -4 70 -8 82 -10 12 -2 57 -7
100 -10 43 -4 85 -9 94 -10 52 -10 351 -20 584 -20 579 0 928 35 1410 140 11
3 34 7 50 10 377 74 958 259 1320 422 55 25 116 52 135 60 111 48 395 196 560
291 52 30 114 65 137 78 23 13 91 55 150 94 255 164 427 288 623 450 36 30 85
70 107 88 22 18 56 47 75 65 19 18 60 55 93 82 32 28 81 70 109 95 58 50 229
222 295 296 25 27 72 78 105 114 90 97 157 174 226 260 19 24 40 48 45 54 6 6
26 31 45 56 19 25 37 47 40 50 3 3 17 21 30 40 13 19 27 37 30 40 5 4 157 217
200 280 60 88 187 286 221 343 23 40 58 99 78 132 52 88 250 483 305 610 72
168 199 498 234 610 17 55 45 144 62 198 140 450 250 1047 277 1512 16 261 7
1098 -12 1158 -2 6 -6 48 -9 92 -8 106 -44 365 -61 440 -7 33 -16 78 -20 100
-7 48 -67 327 -94 440 -22 91 -61 226 -86 299 -9 26 -18 58 -21 69 -20 104
-173 508 -276 727 -22 47 -48 105 -58 130 -21 52 -134 272 -210 410 -29 52
-66 120 -83 150 -63 116 -120 200 -131 193 -5 -3 -6 -2 -3 4 4 5 -18 47 -48
93 -30 45 -55 86 -55 90 0 5 -4 10 -8 12 -5 2 -28 32 -52 68 -61 91 -139 198
-175 241 -16 20 -41 51 -55 70 -14 18 -54 67 -90 109 -36 42 -81 95 -100 119
-103 129 -191 224 -394 426 -211 209 -371 353 -586 524 -91 72 -169 135 -175
139 -59 48 -393 272 -404 272 -5 0 -11 3 -13 8 -9 22 -362 229 -568 333 -138
70 -207 103 -415 197 -196 89 -741 283 -840 299 -11 2 -31 8 -45 13 -71 27
-359 94 -584 135 -43 8 -86 17 -95 19 -29 9 -284 45 -426 60 -328 35 -681 47
-1040 35z m690 -489 c94 -5 188 -12 210 -15 22 -2 67 -7 100 -10 33 -3 71 -8
85 -10 14 -3 48 -7 75 -10 89 -10 118 -15 205 -31 104 -19 311 -62 365 -75 22
-5 49 -11 60 -14 50 -9 191 -47 345 -93 98 -29 365 -119 418 -141 26 -11 103
-42 172 -69 142 -57 219 -92 440 -199 144 -71 226 -116 405 -222 39 -23 79
-48 90 -54 105 -63 434 -287 505 -344 8 -7 69 -55 135 -108 403 -322 738 -660
1087 -1095 141 -176 321 -436 428 -617 38 -65 74 -123 80 -130 5 -7 10 -14 10
-16 0 -3 30 -58 67 -123 60 -107 115 -218 242 -488 98 -208 304 -801 337 -970
2 -10 10 -42 18 -70 8 -28 17 -62 20 -76 15 -71 47 -217 51 -230 9 -29 64
-377 74 -465 45 -397 47 -438 44 -885 -3 -753 -138 -1472 -408 -2184 -98 -260
-103 -272 -162 -396 -25 -52 -58 -126 -74 -164 -68 -162 -323 -604 -488 -846
-116 -170 -317 -431 -425 -550 -23 -25 -66 -75 -96 -110 -221 -259 -632 -634
-946 -863 -49 -36 -100 -74 -114 -85 -243 -184 -755 -479 -1081 -622 -52 -23
-116 -52 -144 -65 -27 -13 -93 -39 -145 -60 -52 -20 -108 -42 -125 -50 -93
-42 -516 -173 -690 -215 -164 -39 -474 -101 -670 -134 -242 -41 -769 -72
-1059 -62 -259 9 -553 32 -721 57 -257 37 -729 136 -925 194 -151 45 -360 113
-450 147 -237 89 -262 100 -523 222 -55 25 -101 46 -105 46 -13 0 -360 191
-517 285 -237 142 -319 198 -610 420 -609 463 -1168 1098 -1581 1795 -108 182
-206 360 -244 445 -18 39 -59 129 -92 200 -85 185 -94 206 -176 425 -75 199
-179 535 -224 725 -16 70 -99 478 -104 515 -2 19 -6 49 -9 65 -8 53 -22 164
-31 245 -3 30 -7 66 -10 80 -25 156 -25 943 0 1204 20 214 22 226 47 386 11
69 22 139 25 155 3 17 7 37 9 45 2 8 6 26 9 40 15 83 70 340 91 425 87 347
256 815 393 1090 17 33 49 101 73 150 23 50 75 149 116 222 40 72 73 136 73
141 0 6 4 12 8 14 5 2 31 41 58 88 47 82 123 202 144 227 5 7 34 47 63 90 134
197 278 386 406 534 36 42 85 98 108 125 87 103 468 481 591 587 282 241 656
514 907 661 44 26 94 55 110 65 83 49 345 189 380 203 22 9 87 39 145 66 58
28 143 66 190 85 47 20 119 50 160 67 78 33 290 108 325 116 11 2 31 8 45 14
25 10 127 42 275 85 359 105 972 203 1360 218 202 8 621 6 770 -3z"/>
<path d="M6968 11818 c-19 -24 -54 -72 -79 -108 -24 -36 -46 -67 -49 -70 -3
-3 -40 -57 -83 -120 -43 -63 -104 -151 -134 -195 -31 -44 -99 -143 -151 -220
-144 -211 -150 -220 -249 -360 -119 -169 -168 -239 -248 -355 -36 -52 -117
-169 -180 -260 -62 -91 -153 -221 -200 -290 -47 -69 -133 -190 -190 -270 -57
-80 -143 -201 -190 -270 -47 -69 -115 -168 -152 -220 -211 -303 -256 -372
-242 -380 7 -5 448 -9 979 -9 l967 0 24 40 c13 22 51 77 84 123 33 46 87 123
120 171 33 47 83 117 110 155 28 38 75 105 105 149 30 45 61 89 68 98 7 10 39
56 72 103 32 47 63 90 67 95 4 6 21 30 38 55 16 25 33 47 36 50 3 3 47 66 98
140 97 143 253 365 274 390 6 9 25 36 42 60 16 25 42 62 59 83 l29 38 -24 42
c-22 40 -82 129 -104 154 -5 6 -53 73 -105 148 -52 75 -124 177 -159 228 -36
51 -88 126 -116 167 -28 41 -110 156 -181 255 -71 99 -142 201 -159 225 -34
52 -125 181 -135 193 -4 4 -22 -11 -42 -35z"/>
<path d="M13350 11799 c-19 -28 -44 -63 -56 -77 -12 -15 -55 -76 -96 -137 -41
-60 -133 -191 -203 -290 -137 -191 -215 -302 -264 -375 -17 -25 -96 -137 -176
-249 -80 -112 -145 -207 -145 -211 0 -4 12 -25 27 -46 15 -21 63 -93 108 -159
99 -146 180 -264 254 -369 31 -43 76 -109 101 -145 25 -36 86 -122 135 -191
49 -69 120 -172 159 -229 57 -85 324 -468 353 -506 5 -6 21 -28 37 -50 62 -83
-49 -75 1043 -75 678 0 973 3 973 11 0 5 -4 7 -10 4 -5 -3 -7 0 -5 8 3 7 -16
42 -43 78 -26 35 -73 100 -103 144 -61 87 -348 498 -427 610 -27 39 -111 158
-187 265 -145 204 -210 299 -307 440 -31 47 -72 105 -89 130 -18 25 -66 95
-107 155 -42 61 -78 112 -81 115 -4 3 -15 19 -25 35 -11 17 -72 104 -136 195
-65 91 -165 235 -223 320 -58 85 -111 154 -117 152 -6 -1 -9 2 -6 7 3 4 -8 28
-25 52 -16 24 -82 121 -144 214 -115 170 -157 225 -172 225 -4 0 -24 -23 -43
-51z"/>
<path d="M7585 7681 c-2 -4 -4 -405 -4 -892 l0 -885 217 1 217 0 5 360 5 360
380 0 380 0 5 -360 5 -360 70 -1 c39 0 77 3 86 7 9 5 19 6 22 2 3 -3 63 -6
132 -7 l125 -1 0 435 c1 1112 0 1334 -10 1340 -9 5 -398 7 -422 2 -4 -1 -9
-156 -10 -344 l-3 -343 -25 -2 c-65 -4 -104 -4 -372 -3 -158 0 -291 0 -295 -1
-5 -1 -23 -1 -40 0 l-33 1 -2 348 -3 347 -213 1 c-117 1 -214 -1 -217 -5z"/>
<path d="M9699 7686 c-2 -3 -4 -404 -3 -892 l2 -888 693 -1 c382 0 700 1 707
3 9 3 12 47 12 173 l0 169 -482 2 -483 3 -2 25 c-1 14 -2 99 -3 190 l-2 165
24 3 c12 1 196 3 408 5 l385 2 3 162 2 162 -406 1 c-223 0 -409 2 -412 4 -4 2
-6 85 -4 185 l3 181 463 0 464 0 4 23 c5 25 0 296 -6 312 -4 10 -1356 21
-1367 11z"/>
<path d="M11360 7515 l0 -176 460 2 c253 2 463 0 466 -4 8 -7 -64 -96 -233
-290 -13 -15 -67 -81 -120 -145 -169 -205 -287 -346 -325 -387 -20 -22 -47
-53 -59 -70 -35 -46 -129 -155 -172 -202 l-40 -42 -1 -148 -1 -148 785 0 c432
0 792 1 800 3 13 3 15 28 13 169 -2 92 -4 168 -6 169 -2 2 -227 4 -500 4 -320
1 -497 4 -497 11 0 8 91 131 110 149 3 3 25 30 50 60 25 30 49 60 55 66 5 6
26 30 45 54 19 24 51 62 70 85 43 51 84 101 151 185 28 36 61 76 73 90 11 14
39 47 61 75 52 65 55 68 183 222 61 72 116 142 123 155 8 14 13 69 13 146 1
101 -2 125 -14 132 -8 4 -347 8 -752 9 l-738 1 0 -175z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 KiB

@@ -0,0 +1,154 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1795.000000pt" height="415.000000pt" viewBox="0 0 1795.000000 415.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,415.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M110 2115 l0 -1945 8820 0 8820 0 0 1945 0 1945 -8820 0 -8820 0 0
-1945z m17590 0 l0 -1895 -8770 0 -8770 0 0 1895 0 1895 8770 0 8770 0 0
-1895z"/>
<path d="M1870 3831 c-14 -5 -47 -9 -73 -10 -45 -1 -160 -40 -230 -78 -15 -8
-39 -20 -52 -27 -28 -15 -95 -85 -95 -100 0 -5 -8 -18 -17 -28 -24 -26 -24
-135 0 -171 9 -14 17 -32 17 -39 1 -19 54 -75 79 -83 12 -3 21 -10 21 -15 0
-4 19 -17 43 -28 148 -69 151 -70 284 -83 179 -17 319 -2 453 49 52 20 97 39
100 43 3 3 24 18 47 33 62 38 123 143 123 211 0 47 -105 205 -136 205 -4 0
-15 7 -24 15 -28 25 -192 87 -255 96 -94 14 -257 19 -285 10z"/>
<path d="M3810 2125 l0 -1685 95 0 95 0 0 1685 0 1685 -95 0 -95 0 0 -1685z"/>
<path d="M17320 2125 l0 -1685 95 0 95 0 0 1685 0 1685 -95 0 -95 0 0 -1685z"/>
<path d="M1320 3620 c0 -5 -13 -7 -30 -3 -18 3 -30 1 -30 -5 0 -6 10 -12 23
-14 20 -3 22 -9 25 -71 4 -86 22 -79 22 9 0 36 4 64 10 64 15 0 12 17 -5 24
-8 3 -15 1 -15 -4z"/>
<path d="M1283 3423 c24 -4 27 -8 28 -46 0 -23 5 -51 10 -62 6 -14 8 -2 6 42
-1 49 1 63 13 67 8 2 -7 4 -35 3 -27 0 -38 -2 -22 -4z"/>
<path d="M989 3399 c-25 -4 -66 -16 -92 -28 -25 -12 -49 -21 -53 -21 -4 0 -22
-11 -40 -25 -18 -14 -36 -25 -41 -25 -12 -1 -103 -87 -103 -98 0 -5 -11 -17
-25 -26 -14 -9 -25 -23 -25 -30 0 -7 -7 -19 -15 -26 -16 -14 -104 -172 -109
-198 -1 -9 -8 -29 -13 -43 -6 -14 -17 -60 -24 -102 -14 -84 -2 -179 27 -221 8
-11 14 -27 14 -35 0 -15 60 -75 91 -92 10 -5 54 -9 99 -9 70 0 89 4 148 32 37
18 72 37 78 43 6 5 23 19 39 30 37 26 86 76 133 134 20 25 40 48 45 49 4 2 7
12 7 22 0 10 5 22 10 25 6 4 29 46 52 93 76 162 75 369 -3 470 -48 62 -124 93
-200 81z"/>
<path d="M2848 3355 c-53 -11 -97 -48 -132 -111 -47 -84 -42 -293 9 -402 81
-170 84 -174 198 -292 37 -39 71 -70 76 -70 4 0 21 -11 37 -25 16 -14 43 -29
59 -35 17 -5 48 -16 70 -24 53 -20 138 -20 178 0 37 19 97 73 97 88 0 6 6 23
14 38 31 60 40 134 26 221 -7 45 -17 93 -23 107 -6 14 -12 34 -14 44 -2 11
-17 41 -33 68 -17 27 -30 52 -30 56 0 12 -82 120 -126 168 -120 129 -282 196
-406 169z"/>
<path d="M8337 3052 c-10 -10 -17 -25 -17 -34 0 -8 -11 -62 -25 -119 -13 -57
-29 -124 -35 -149 -11 -49 -72 -305 -125 -525 -47 -196 -84 -351 -97 -410 -6
-27 -14 -63 -19 -79 -21 -67 -23 -66 125 -66 l134 0 37 153 c20 83 43 182 52
220 9 37 21 67 27 67 6 0 17 -15 25 -32 17 -41 53 -120 86 -193 14 -31 25 -58
25 -61 0 -8 39 -95 55 -124 14 -25 16 -25 160 -28 l147 -3 -7 31 c-6 29 -22
67 -92 220 -14 30 -40 89 -58 130 -19 41 -41 89 -49 105 -9 17 -16 35 -16 41
0 5 95 104 210 218 127 126 210 215 210 227 0 18 -9 19 -142 19 l-142 0 -188
-188 c-104 -103 -190 -186 -193 -184 -2 2 0 14 5 25 5 12 20 74 35 137 14 63
30 131 35 150 12 41 52 215 81 349 27 121 27 121 -121 121 -91 0 -109 -3 -123
-18z"/>
<path d="M13100 3055 c-7 -8 -23 -61 -35 -118 -12 -56 -37 -163 -54 -237 -18
-74 -41 -173 -52 -220 -19 -81 -26 -109 -49 -197 -5 -21 -16 -67 -24 -103 -37
-163 -78 -338 -86 -370 -5 -19 -12 -59 -16 -87 l-7 -53 131 0 130 0 10 33 c11
36 23 82 51 207 52 222 92 384 100 397 4 8 29 37 55 63 87 89 177 100 204 25
15 -40 6 -106 -39 -295 -16 -69 -34 -145 -40 -170 -6 -25 -14 -61 -20 -81 -5
-20 -14 -61 -19 -90 -6 -30 -13 -62 -16 -72 -5 -16 4 -17 132 -15 l138 3 12
45 c25 98 98 416 125 545 21 101 24 210 8 269 -6 21 -28 57 -50 81 -32 35 -52
46 -104 60 -101 28 -195 3 -315 -82 -23 -18 -24 -17 -16 2 4 11 25 94 46 185
22 91 44 186 50 211 18 77 15 79 -120 79 -93 0 -120 -3 -130 -15z"/>
<path d="M11794 3036 c-69 -31 -117 -155 -84 -217 17 -31 64 -49 131 -49 116
0 179 63 179 178 0 72 -29 96 -123 99 -46 2 -83 -2 -103 -11z"/>
<path d="M15033 3034 c-41 -21 -62 -44 -79 -91 -23 -67 -18 -111 17 -144 28
-26 38 -29 101 -29 89 0 139 25 168 85 22 45 26 115 9 147 -24 45 -151 64
-216 32z"/>
<path d="M5515 2961 c-42 -18 -48 -35 -101 -261 -20 -85 -47 -200 -61 -255
-14 -55 -28 -116 -33 -135 -4 -19 -31 -132 -60 -250 -29 -118 -58 -244 -66
-280 -8 -36 -16 -75 -19 -87 l-5 -23 139 0 140 0 15 53 c14 47 23 86 57 242 5
22 15 63 22 90 l13 50 140 6 c191 8 277 34 389 114 91 64 139 130 183 248 25
66 31 229 10 288 -30 87 -92 145 -195 182 -51 18 -87 21 -303 24 -135 1 -254
-1 -265 -6z m422 -244 c62 -33 78 -107 46 -208 -22 -69 -82 -130 -148 -152
-31 -11 -81 -17 -138 -17 -78 0 -88 2 -83 16 6 17 48 191 72 303 8 35 17 68
20 73 11 17 194 5 231 -15z"/>
<path d="M6735 2676 c-310 -58 -494 -324 -483 -696 4 -124 24 -175 98 -244 57
-53 132 -82 236 -91 135 -12 338 28 390 76 19 18 44 112 44 167 0 32 -38 36
-109 13 -34 -11 -100 -28 -147 -37 -80 -16 -89 -16 -138 -1 -29 9 -62 27 -74
39 -28 31 -47 105 -38 151 l7 37 124 0 c221 0 344 28 423 96 67 57 93 111 99
202 8 118 -23 193 -102 242 -76 47 -219 67 -330 46z m122 -206 c58 -21 71
-100 24 -152 l-29 -33 -141 -3 c-163 -4 -164 -4 -110 80 60 93 167 138 256
108z"/>
<path d="M12495 2684 c-11 -2 -45 -9 -75 -15 -94 -18 -208 -80 -271 -146 -133
-140 -208 -349 -196 -546 6 -107 28 -166 83 -227 109 -121 334 -142 538 -50
75 33 87 50 109 158 13 64 13 75 0 87 -20 21 -26 20 -125 -26 -182 -84 -304
-54 -324 79 -8 49 8 188 25 219 5 10 19 39 30 64 52 113 135 173 242 174 57 0
75 -5 143 -40 72 -37 79 -39 103 -25 30 17 51 70 60 151 5 53 4 57 -23 76 -66
47 -237 83 -319 67z"/>
<path d="M14235 2676 c-206 -36 -264 -84 -265 -218 0 -56 22 -63 108 -34 85
29 212 50 251 41 56 -12 76 -65 56 -153 -7 -36 -14 -38 -165 -46 -151 -8 -269
-54 -349 -134 -61 -62 -90 -125 -97 -215 -11 -125 25 -198 121 -250 32 -18 56
-22 125 -22 96 1 143 17 223 78 26 21 49 37 52 37 2 0 5 -19 7 -42 l3 -43 108
-3 c59 -1 107 -1 107 0 0 5 29 159 45 238 8 41 23 111 34 155 11 44 27 116 36
160 9 44 21 96 26 116 23 89 -1 208 -52 260 -38 39 -97 65 -179 78 -78 13
-104 13 -195 -3z m91 -623 c-13 -73 -28 -103 -68 -137 -53 -46 -98 -66 -145
-66 -57 0 -77 25 -71 88 10 101 83 148 232 151 l58 1 -6 -37z"/>
<path d="M15800 2679 c-58 -17 -114 -45 -163 -83 -26 -20 -49 -36 -52 -36 -2
0 -5 21 -7 48 l-3 47 -96 3 c-109 3 -110 3 -126 -73 -26 -117 -65 -283 -73
-315 -10 -39 -34 -144 -75 -325 -14 -66 -30 -133 -35 -150 -5 -16 -12 -51 -15
-77 l-7 -48 130 0 129 0 11 43 c21 80 91 382 107 462 9 44 25 98 34 120 31 69
135 155 188 155 12 0 35 -11 50 -24 26 -22 28 -30 27 -88 -1 -35 -18 -133 -38
-218 -20 -85 -43 -189 -52 -230 -9 -41 -20 -88 -24 -105 -5 -16 -12 -49 -15
-72 l-7 -43 134 0 134 0 29 123 c15 67 38 163 50 212 13 50 31 126 40 170 10
44 24 105 31 135 30 119 12 241 -45 304 -52 57 -179 89 -261 65z"/>
<path d="M7334 2604 c-9 -31 -17 -77 -17 -102 l-2 -47 198 -3 c108 -1 197 -3
197 -5 0 -1 -85 -88 -188 -193 -413 -420 -387 -391 -406 -473 -28 -122 -63
-111 374 -111 350 0 378 1 385 18 14 34 34 127 35 160 l0 32 -215 0 c-118 0
-215 3 -215 6 0 4 105 115 233 248 366 379 350 361 366 438 7 37 10 72 6 77
-4 8 -124 11 -370 11 l-364 0 -17 -56z"/>
<path d="M9217 2642 c-10 -10 -17 -26 -17 -34 0 -16 -15 -84 -85 -378 -67
-282 -73 -325 -54 -413 41 -194 290 -234 486 -79 l52 42 3 -53 3 -52 106 -3
c122 -3 105 -20 139 133 12 50 25 106 30 125 14 51 119 484 136 560 8 36 20
84 26 108 7 28 7 47 1 53 -6 6 -62 8 -134 7 l-124 -3 -17 -55 c-9 -30 -42
-161 -73 -290 -64 -267 -78 -304 -132 -355 -80 -77 -154 -95 -200 -49 -24 24
-25 31 -20 87 3 34 20 121 37 192 17 72 42 180 56 240 14 61 29 126 34 146 6
20 10 48 10 63 l0 26 -123 0 c-107 0 -126 -2 -140 -18z"/>
<path d="M10177 2654 c-9 -9 -8 -342 2 -686 6 -194 11 -271 21 -282 10 -13 37
-16 146 -16 l133 0 50 103 c47 98 105 221 149 317 11 25 33 72 49 105 l28 60
5 -280 c3 -154 9 -286 13 -292 6 -9 46 -13 141 -13 114 0 135 2 148 18 8 9 87
159 175 332 89 173 193 377 232 454 40 76 71 148 69 160 -3 20 -10 21 -117 24
-81 2 -118 -1 -129 -10 -8 -7 -29 -44 -47 -83 -18 -38 -44 -95 -58 -125 -14
-30 -48 -104 -77 -165 -29 -60 -68 -148 -87 -195 -19 -47 -38 -89 -42 -93 -4
-4 -6 140 -3 320 4 286 3 330 -11 341 -10 9 -46 12 -118 10 l-104 -3 -47 -95
c-89 -178 -206 -427 -238 -504 -18 -42 -33 -76 -35 -76 -1 0 -2 152 -1 338 l1
337 -121 3 c-66 1 -123 -1 -127 -4z"/>
<path d="M11678 2643 c-8 -10 -23 -52 -32 -93 -26 -113 -66 -281 -76 -320 -5
-19 -21 -84 -35 -145 -14 -60 -36 -155 -50 -210 -13 -55 -27 -116 -30 -135 -4
-19 -9 -43 -11 -52 -5 -17 6 -18 130 -18 l134 0 11 33 c6 17 22 84 37 147 14
63 39 171 56 240 16 69 33 143 37 165 5 22 16 68 25 103 26 97 64 291 58 297
-3 3 -58 5 -122 5 -99 0 -119 -3 -132 -17z"/>
<path d="M14925 2640 c-15 -17 -36 -90 -75 -270 -12 -55 -31 -135 -60 -260
-25 -105 -33 -141 -49 -215 -5 -27 -17 -81 -25 -120 -25 -114 -35 -105 113
-105 l128 0 16 58 c8 31 27 109 42 172 14 63 35 153 46 200 27 116 43 184 74
325 15 66 31 133 36 149 5 16 9 42 9 57 l0 29 -118 0 c-106 0 -121 -2 -137
-20z"/>
<path d="M3185 2022 c-68 -17 -165 -77 -242 -148 -56 -53 -136 -158 -148 -192
-3 -12 -10 -22 -15 -22 -4 0 -15 -19 -25 -42 -9 -24 -22 -56 -29 -73 -7 -16
-18 -43 -25 -58 -17 -42 -24 -213 -13 -284 11 -64 42 -117 91 -158 58 -47 211
-46 291 3 19 12 44 26 55 31 11 5 29 18 39 30 11 11 23 21 27 21 5 0 27 21 51
46 24 26 51 55 61 65 9 11 17 23 17 27 0 5 9 18 20 30 25 26 78 120 108 192
37 86 47 139 47 240 0 95 -3 111 -28 162 -34 69 -72 107 -123 123 -66 21 -97
23 -159 7z"/>
<path d="M608 2016 c-69 -13 -114 -51 -152 -128 -23 -47 -26 -63 -26 -167 0
-124 8 -160 62 -280 16 -35 36 -70 44 -78 8 -8 14 -19 14 -24 0 -5 25 -42 55
-83 89 -120 224 -222 332 -248 60 -15 74 -14 165 8 37 8 82 56 112 117 24 46
26 62 26 169 0 113 -3 132 -40 223 -28 71 -82 175 -104 200 -14 17 -26 34 -26
40 0 12 -170 175 -195 186 -11 5 -36 19 -55 31 -19 11 -55 25 -80 30 -25 4
-52 10 -60 12 -8 2 -41 -1 -72 -8z"/>
<path d="M1869 1315 c-141 -18 -286 -79 -366 -154 -28 -26 -69 -97 -77 -133
-14 -60 30 -165 90 -218 41 -36 91 -70 104 -70 5 0 10 -4 10 -9 0 -5 13 -12
30 -16 16 -3 46 -14 67 -24 61 -29 276 -46 398 -31 98 11 190 34 210 51 5 5
18 9 30 9 12 0 42 14 68 30 26 17 50 30 54 30 13 0 79 85 92 119 23 60 24 121
4 172 -18 46 -74 119 -91 119 -5 0 -21 10 -36 23 -50 43 -182 88 -301 103
-129 16 -158 15 -286 -1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

@@ -0,0 +1,229 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="1920.000000pt" height="544.000000pt" viewBox="0 0 1920.000000 544.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,544.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M0 2720 l0 -2720 9600 0 9600 0 0 2720 0 2720 -9600 0 -9600 0 0
-2720z m1543 804 c7 -7 -25 -100 -60 -173 -45 -94 -112 -189 -196 -277 -254
-269 -527 -297 -639 -66 -31 65 -33 71 -33 192 0 116 9 177 38 270 20 64 -8
60 457 60 234 0 429 -3 433 -6z m2607 -14 c43 -86 55 -155 55 -305 0 -133 -1
-143 -28 -197 -34 -70 -101 -131 -162 -148 -48 -13 -159 -9 -192 8 -10 5 -38
20 -63 32 -160 82 -322 253 -416 440 -34 67 -73 177 -66 185 3 3 199 4 435 3
370 -3 431 -5 437 -18z m-1726 -115 c12 -119 28 -230 35 -238 8 -8 38 56 101
216 23 59 44 106 47 104 6 -7 -38 -299 -48 -319 -14 -28 0 -21 29 13 14 18 48
49 75 70 27 22 46 39 42 39 -3 0 15 27 40 60 25 33 48 60 50 60 11 0 -27 -69
-52 -93 l-28 -29 30 15 c71 36 88 40 152 40 43 -1 79 -7 98 -17 17 -9 35 -16
41 -16 6 0 39 -26 72 -57 53 -48 62 -62 62 -90 0 -43 -20 -34 -21 10 -1 18 -3
24 -6 15 -5 -19 -28 -24 -38 -8 -3 5 -11 7 -18 5 -14 -5 -41 14 -50 35 -4 12
-6 11 -6 -2 -1 -14 -10 -18 -36 -18 -19 0 -44 -5 -54 -12 -17 -10 -23 -8 -41
13 -19 21 -20 22 -8 2 11 -20 10 -25 -7 -37 -23 -18 -45 -20 -45 -6 0 6 -5 10
-11 10 -8 0 -8 -4 0 -14 10 -11 7 -17 -10 -29 -21 -15 -49 -13 -49 4 0 5 -5 9
-10 9 -6 0 -3 -11 5 -24 14 -22 14 -25 0 -40 -21 -20 -14 -21 -83 14 -33 17
-66 30 -73 30 -8 0 13 -14 46 -31 76 -38 81 -44 62 -63 -16 -16 -57 -22 -57
-8 0 12 -82 41 -125 44 -38 3 -41 1 -60 -37 -23 -45 -51 -75 -72 -75 -35 0
-88 64 -135 160 -9 19 -26 105 -38 190 -12 85 -24 166 -27 180 -11 50 14 4 47
-85 51 -141 91 -235 100 -235 8 0 17 57 41 254 14 107 22 104 33 -9z m-349
-62 c52 -74 54 -81 16 -54 -26 19 -71 85 -71 106 0 17 20 -2 55 -52z m-75 -20
c25 -10 51 -23 58 -30 7 -7 18 -13 23 -13 25 0 134 -112 178 -184 47 -77 49
-86 19 -86 -13 0 -45 -12 -73 -25 -58 -29 -90 -32 -99 -9 -4 9 -5 18 -4 19 14
12 102 45 120 45 13 0 30 5 38 10 30 19 -33 10 -105 -14 -50 -18 -73 -22 -82
-14 -22 18 -14 33 32 58 24 13 43 25 41 27 -6 6 -66 -19 -66 -27 0 -5 -9 -12
-21 -15 -28 -9 -69 32 -48 47 11 8 10 9 -3 4 -10 -3 -23 0 -30 7 -7 7 -30 23
-50 36 -39 23 -43 30 -30 47 4 5 -1 1 -10 -9 -13 -14 -21 -16 -37 -8 -11 6
-38 11 -60 11 -23 0 -41 5 -41 10 0 6 -10 2 -22 -9 -14 -14 -25 -17 -33 -11
-7 6 -15 2 -23 -11 -11 -17 -16 -18 -28 -9 -11 10 -14 9 -14 -4 0 -9 -4 -16
-10 -16 -5 0 -10 11 -10 24 0 15 18 40 54 74 102 97 213 121 336 75z m3981
-98 c102 -30 161 -60 225 -118 91 -82 133 -190 134 -338 0 -102 -16 -165 -65
-264 -26 -52 -110 -155 -127 -155 -5 0 -24 -11 -41 -24 -44 -33 -133 -74 -176
-82 -20 -4 -42 -12 -50 -18 -9 -7 -90 -12 -235 -13 l-221 -3 -7 -32 c-28 -133
-41 -198 -45 -228 -3 -19 -9 -39 -13 -45 -4 -5 -11 -31 -14 -57 -5 -36 -15
-53 -39 -74 -27 -23 -37 -25 -76 -20 -24 3 -53 13 -63 22 -17 16 -35 78 -29
99 2 6 7 33 12 60 4 28 15 86 23 130 9 44 18 96 21 115 4 19 10 44 15 55 5 11
11 36 14 55 3 19 12 71 21 115 9 44 18 94 21 110 3 17 9 39 14 50 5 11 11 36
15 55 13 75 24 130 50 245 15 66 31 138 35 160 22 103 27 121 39 142 28 53
109 70 352 72 113 1 170 -3 210 -14z m3001 -47 c26 -29 29 -39 25 -78 -5 -43
-27 -161 -47 -245 -5 -22 -16 -76 -25 -120 -9 -44 -20 -100 -25 -125 -5 -25
-20 -101 -35 -169 -14 -68 -24 -125 -22 -127 2 -2 34 22 72 54 38 31 113 91
166 132 53 41 138 110 190 152 106 86 134 100 181 91 66 -12 99 -76 68 -133
-5 -10 -95 -87 -199 -170 l-190 -152 13 -36 c23 -63 93 -224 130 -297 43 -85
47 -134 13 -171 -32 -34 -90 -41 -137 -17 -32 17 -74 79 -93 138 -26 82 -95
240 -104 240 -6 0 -49 -30 -95 -66 l-84 -66 -19 -98 c-25 -126 -48 -155 -124
-155 -43 0 -56 4 -76 26 -14 15 -25 39 -25 53 0 28 23 166 40 246 6 28 15 73
20 100 9 53 36 182 51 250 18 80 30 141 35 175 3 19 9 44 14 55 5 11 11 36 14
55 3 19 15 78 26 130 19 82 33 153 57 273 3 15 19 41 35 57 24 25 38 30 75 30
39 0 51 -5 75 -32z m5269 2 c32 -33 36 -69 18 -150 -6 -25 -14 -64 -20 -87 -5
-24 -13 -62 -19 -85 -9 -43 -26 -129 -53 -268 -8 -41 -14 -76 -12 -77 1 -2 17
18 35 45 49 67 112 125 167 151 27 13 56 27 65 32 24 12 158 11 158 -1 0 -5 7
-10 17 -10 31 0 103 -51 128 -91 60 -94 66 -198 23 -434 -11 -60 -24 -132 -28
-160 -25 -147 -39 -216 -52 -242 -18 -39 -79 -59 -131 -43 -64 19 -80 66 -57
180 6 30 17 96 25 145 8 50 20 117 27 150 6 33 12 100 12 148 1 88 1 89 -32
118 -27 24 -41 29 -87 29 -65 0 -109 -22 -179 -88 -67 -65 -156 -209 -156
-253 0 -11 -4 -27 -9 -37 -5 -9 -17 -62 -26 -117 -9 -55 -21 -110 -26 -123 -5
-13 -9 -33 -9 -46 0 -27 -18 -65 -41 -88 -21 -21 -80 -30 -116 -18 -60 21 -70
81 -39 230 10 47 22 105 26 130 5 25 12 59 15 75 4 17 17 84 30 150 13 66 26
134 30 150 3 17 10 50 15 75 5 25 21 99 35 165 15 66 30 143 35 170 5 28 14
73 20 100 6 28 13 64 16 80 14 81 58 125 123 125 36 0 49 -6 72 -30z m-12660
-41 c-5 -13 -10 -19 -10 -12 -1 15 10 45 15 40 3 -2 0 -15 -5 -28z m11228 -41
c73 -75 14 -210 -100 -225 -43 -6 -109 21 -109 44 0 7 -4 13 -10 13 -5 0 -10
24 -10 53 0 40 6 61 24 86 38 51 56 60 117 61 51 0 60 -3 88 -32z m3821 0 c30
-31 32 -36 27 -91 -4 -43 -12 -66 -28 -83 -72 -77 -179 -71 -219 12 -24 48
-24 61 -5 107 24 57 70 87 136 87 51 0 60 -3 89 -32z m-14062 -62 c18 -3 48
-16 68 -30 32 -22 34 -25 19 -40 -20 -20 -26 -20 -19 -1 4 8 1 15 -5 15 -6 0
-11 -4 -11 -8 0 -14 -35 -7 -64 11 -14 10 -40 20 -56 24 -17 3 -30 9 -30 12 0
16 25 30 44 26 12 -2 36 -6 54 -9z m-665 -13 c42 -23 117 -94 117 -110 0 -7 4
-13 8 -13 13 0 32 -63 26 -87 -8 -29 -20 -29 -35 -1 -7 13 -24 32 -37 43 -60
47 -59 46 -25 40 54 -11 45 9 -33 70 -41 32 -77 62 -80 67 -9 14 27 9 59 -9z
m1047 12 c0 -2 -37 -32 -81 -66 -70 -53 -80 -64 -66 -74 15 -10 14 -13 -1 -26
-9 -8 -27 -27 -39 -43 -25 -32 -43 -27 -43 12 0 66 138 200 208 202 12 0 22
-2 22 -5z m-668 -57 c-18 -5 -30 -13 -27 -18 4 -6 -6 -10 -22 -9 -25 0 -26 1
-8 9 11 5 16 9 10 10 -5 1 6 7 25 14 19 8 39 11 45 8 5 -3 -5 -10 -23 -14z
m-462 -49 c27 -6 50 -15 50 -20 0 -5 6 -9 14 -9 7 0 20 -7 27 -17 13 -15 12
-15 -6 -5 -37 21 -97 42 -121 42 -20 0 -22 -4 -18 -37 l4 -38 -13 40 c-20 60
-18 61 63 44z m-90 -13 c0 -9 -7 -12 -20 -9 -31 8 -34 23 -6 23 16 0 26 -6 26
-14z m1280 -7 c0 -21 -1 -21 -26 -4 -16 10 -30 13 -37 7 -7 -5 -28 -12 -47
-16 -32 -6 -33 -5 -15 8 24 16 49 23 93 25 26 1 32 -3 32 -20z m84 13 c3 -5
-10 -14 -29 -20 -39 -11 -49 3 -12 18 29 11 35 12 41 2z m-690 -63 c-5 -30 -3
-43 7 -49 11 -7 10 -10 -4 -16 -14 -5 -12 -9 15 -24 30 -16 33 -22 31 -57 -3
-42 -6 -40 50 -34 4 1 7 6 7 12 0 8 -5 8 -15 -1 -8 -7 -15 -9 -15 -6 0 13 33
56 42 56 6 0 5 -7 -3 -16 -10 -13 -10 -17 0 -24 11 -6 7 -16 -14 -44 -15 -20
-25 -39 -21 -43 3 -3 6 -1 6 5 0 7 4 12 9 12 5 0 9 -21 8 -47 -1 -29 3 -48 11
-50 15 -6 16 -49 2 -58 -8 -5 -7 -11 1 -21 9 -11 8 -19 -6 -34 -10 -11 -13
-20 -7 -20 6 0 10 -29 11 -72 1 -40 5 -100 11 -133 5 -33 10 -76 10 -96 0 -41
-29 -81 -63 -86 -12 -2 -26 -8 -31 -13 -14 -14 -42 -12 -56 4 -15 19 6 66 36
81 35 17 54 42 54 70 0 23 -4 26 -27 23 -16 -2 -28 -7 -27 -13 0 -5 -10 -21
-23 -35 l-23 -24 -38 37 c-39 38 -56 45 -67 27 -10 -16 18 -70 40 -76 36 -11
55 -36 55 -71 0 -29 -3 -33 -25 -33 -35 0 -102 35 -115 60 -8 15 -8 65 -1 173
6 84 8 162 5 175 -4 13 -2 22 5 22 7 0 6 8 -4 24 -11 17 -13 30 -6 48 6 15 5
31 -2 43 -7 14 -7 20 1 23 7 2 9 9 5 15 -4 7 0 8 12 3 14 -5 15 -3 7 6 -15 19
-22 108 -9 128 8 15 14 16 29 7 10 -7 18 -17 18 -24 0 -7 5 -13 10 -13 13 0
13 17 -1 26 -6 3 -9 17 -6 30 2 13 0 24 -4 24 -5 0 -9 5 -9 10 0 14 27 12 33
-2 5 -15 11 -3 22 47 4 17 10 24 12 17 7 -18 23 -4 23 19 0 11 4 18 9 14 5 -3
12 4 16 15 11 34 16 22 9 -21z m456 21 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10
3 6 8 10 11 10 2 0 4 -4 4 -10z m-522 -25 c-3 -3 -9 2 -12 12 -6 14 -5 15 5 6
7 -7 10 -15 7 -18z m662 5 c0 -11 -4 -20 -9 -20 -5 0 -7 9 -4 20 3 11 7 20 9
20 2 0 4 -9 4 -20z m-1210 -55 c0 -5 -5 -3 -10 5 -5 8 -10 20 -10 25 0 6 5 3
10 -5 5 -8 10 -19 10 -25z m770 -34 c0 -5 -7 -12 -16 -15 -14 -5 -15 -4 -4 9
14 17 20 19 20 6z m-762 -36 c11 -23 10 -25 -11 -21 -12 3 -48 8 -79 11 -70 8
-76 23 -10 28 26 2 56 4 68 5 14 1 25 -7 32 -23z m348 -9 c62 -62 82 -148 44
-186 -11 -11 -21 -18 -21 -15 -1 3 -2 10 -3 15 -1 14 -77 80 -91 80 -6 0 -16
-5 -22 -11 -35 -35 -44 41 -13 109 25 54 57 57 106 8z m554 14 c36 -31 43
-161 6 -131 -17 14 -61 -7 -91 -45 -35 -44 -55 -27 -55 45 0 55 3 62 41 105
46 51 65 56 99 26z m393 10 c47 0 29 -18 -25 -25 -29 -3 -66 -9 -81 -12 l-29
-5 18 27 c15 23 22 26 53 21 20 -3 48 -6 64 -6z m14371 -9 c3 -4 19 -11 35
-14 41 -8 102 -65 130 -121 39 -80 36 -236 -9 -451 -18 -83 -28 -136 -44 -220
-8 -44 -18 -92 -21 -107 -24 -97 -191 -102 -209 -6 -3 18 1 66 10 107 8 41 22
118 31 170 8 53 19 119 25 146 37 193 7 285 -95 285 -66 0 -117 -21 -173 -72
-87 -80 -163 -214 -186 -325 -4 -24 -12 -62 -17 -85 -5 -24 -14 -77 -21 -118
-7 -41 -16 -83 -21 -92 -5 -10 -9 -24 -9 -32 0 -8 -15 -24 -34 -35 -56 -35
-130 -24 -161 23 -17 26 -16 45 15 191 5 28 17 88 25 135 21 116 30 161 50
260 9 47 21 105 26 130 27 147 32 161 61 190 42 43 103 42 148 0 32 -30 33
-31 26 -98 -4 -37 -9 -78 -12 -92 -3 -15 7 -4 27 30 56 94 173 190 230 190 10
0 19 5 19 10 0 12 147 14 154 1z m-10385 -17 c133 -46 212 -164 195 -290 -9
-61 -53 -142 -98 -179 -43 -35 -163 -95 -190 -95 -8 0 -17 -4 -20 -9 -3 -5
-52 -14 -108 -20 -57 -7 -114 -15 -128 -17 -14 -3 -54 -7 -90 -10 -35 -3 -66
-7 -69 -9 -2 -3 5 -26 16 -52 13 -33 33 -57 62 -78 41 -29 48 -30 144 -30 102
0 102 0 197 48 104 52 145 58 178 27 56 -52 11 -133 -105 -189 -37 -18 -76
-37 -85 -42 -10 -5 -26 -9 -36 -9 -10 0 -23 -5 -30 -12 -8 -8 -53 -12 -134
-12 -100 -1 -131 3 -163 18 -22 10 -55 25 -73 34 -18 8 -52 34 -75 57 -37 37
-55 66 -100 163 -17 36 -12 230 7 288 23 69 53 131 89 184 34 52 146 160 165
160 6 0 12 3 12 8 0 8 56 35 130 62 61 23 248 26 309 4z m6567 -18 c27 -14 63
-39 78 -55 25 -26 28 -35 24 -75 -7 -60 -36 -85 -99 -86 -44 0 -99 18 -99 33
0 4 -9 7 -19 7 -11 0 -23 5 -26 10 -3 6 -35 10 -70 10 -35 0 -67 -4 -70 -10
-3 -5 -15 -10 -26 -10 -32 0 -128 -69 -170 -122 -67 -85 -82 -129 -83 -245 -1
-97 0 -103 29 -145 70 -99 177 -112 322 -38 129 65 193 53 193 -35 0 -34 -6
-47 -37 -77 -40 -38 -150 -98 -181 -98 -10 0 -23 -5 -29 -11 -17 -17 -210 -17
-263 1 -25 8 -47 17 -50 20 -3 3 -21 14 -40 24 -52 29 -99 83 -134 156 -29 62
-30 71 -30 192 0 87 3 131 12 140 6 6 12 21 12 32 0 30 58 138 104 195 71 87
179 160 301 205 30 11 74 14 170 12 118 -3 135 -6 181 -30z m2089 17 c11 -6
33 -17 48 -24 51 -24 124 -101 131 -138 3 -19 2 -39 -3 -45 -4 -6 -11 -31 -14
-56 -3 -25 -13 -85 -23 -135 -30 -165 -35 -199 -40 -286 -6 -82 -5 -86 16 -92
37 -10 68 13 110 79 22 35 40 67 40 71 0 5 11 21 24 37 l23 30 25 -40 c48 -76
53 -102 28 -168 -33 -87 -143 -196 -199 -196 -11 0 -23 -4 -26 -10 -3 -5 -26
-10 -50 -10 -24 0 -47 5 -50 10 -3 6 -14 10 -23 10 -28 0 -90 57 -100 93 -6
17 -13 49 -17 70 l-6 39 -28 -44 c-75 -117 -215 -187 -348 -174 -34 4 -74 13
-90 21 -15 8 -34 15 -41 15 -24 0 -122 108 -143 157 -11 26 -25 90 -31 141 -9
79 -8 103 7 170 10 42 21 84 25 92 49 108 72 142 150 221 69 70 101 93 170
126 47 23 94 43 105 46 36 10 309 2 330 -10z m-13521 -9 c3 -8 2 -12 -4 -9 -6
3 -10 10 -10 16 0 14 7 11 14 -7z m7662 -2 c39 -33 47 -58 34 -115 -6 -29 -15
-74 -20 -102 -5 -27 -16 -90 -25 -140 -9 -49 -19 -108 -22 -130 -3 -22 -9 -45
-14 -51 -5 -6 -10 -43 -11 -81 -3 -87 14 -117 73 -133 95 -26 247 68 314 193
7 12 21 38 31 57 27 47 50 128 79 275 9 44 21 94 26 111 5 17 9 40 9 51 0 12
14 35 31 52 74 75 216 7 181 -86 -6 -16 -13 -46 -16 -68 -3 -22 -12 -76 -21
-120 -25 -124 -33 -163 -50 -255 -9 -47 -20 -105 -25 -130 -5 -25 -14 -74 -20
-110 -22 -136 -49 -173 -126 -173 -41 0 -51 4 -77 33 -27 31 -29 37 -23 89 3
31 9 67 13 81 5 19 -4 12 -34 -25 -146 -183 -341 -245 -480 -152 -90 61 -118
131 -109 272 5 82 11 122 46 295 13 59 20 99 39 200 20 104 31 134 59 157 34
29 107 31 138 5z m1061 -9 c20 -19 33 -41 37 -68 22 -132 27 -166 36 -220 6
-33 15 -91 20 -130 10 -74 28 -180 40 -230 6 -29 9 -25 59 70 55 107 98 185
135 250 13 22 43 76 67 120 113 210 122 221 200 231 42 6 48 4 81 -28 28 -26
37 -44 41 -78 8 -59 28 -245 38 -345 6 -62 20 -178 28 -244 1 -4 101 160 101
165 0 2 25 42 55 89 30 46 55 87 55 89 0 3 38 69 85 148 95 160 140 208 192
208 62 0 114 -59 98 -111 -9 -27 -123 -218 -153 -254 -4 -5 -11 -17 -15 -25
-4 -8 -25 -42 -47 -75 -22 -33 -49 -76 -60 -95 -11 -19 -33 -54 -48 -78 -15
-23 -60 -95 -101 -160 -41 -64 -81 -125 -90 -136 -25 -29 -98 -59 -129 -53
-94 19 -111 44 -128 185 -7 59 -20 166 -29 237 -9 72 -19 150 -23 175 l-7 45
-17 -30 c-17 -33 -109 -201 -185 -340 -136 -247 -128 -237 -208 -262 -48 -15
-103 -2 -135 32 -21 22 -51 125 -64 215 -3 25 -15 95 -26 155 -12 61 -25 137
-31 170 -5 33 -16 96 -24 140 -9 44 -18 107 -21 140 -6 58 -5 61 27 93 44 43
101 45 146 5z m1756 15 c54 -26 56 -64 12 -298 -9 -47 -18 -101 -21 -120 -3
-19 -9 -44 -14 -55 -5 -11 -11 -38 -14 -60 -14 -115 -67 -351 -87 -383 -15
-23 -66 -52 -94 -52 -30 0 -84 31 -92 53 -9 27 -4 128 7 142 4 6 10 28 13 50
3 22 13 78 22 125 9 47 21 108 26 135 18 89 28 139 38 185 11 50 16 77 33 164
20 103 92 150 171 114z m3841 -3 c42 -28 48 -60 32 -165 -8 -52 -20 -117 -26
-145 -5 -27 -17 -88 -26 -135 -17 -93 -28 -151 -43 -220 -5 -25 -16 -79 -25
-120 -22 -109 -26 -123 -51 -147 -41 -40 -108 -39 -158 1 -21 17 -25 83 -9
161 6 28 18 86 26 130 30 161 36 191 51 265 9 41 21 100 26 130 10 59 24 126
34 175 10 45 61 85 107 85 22 0 49 -7 62 -15z m-8120 -20 c20 -26 20 -74 1
-113 -17 -34 -73 -85 -540 -493 -77 -67 -141 -126 -143 -131 -2 -4 106 -8 240
-8 134 0 253 -3 264 -6 53 -14 64 -107 19 -154 l-29 -30 -402 0 c-221 0 -410
3 -419 6 -26 10 -45 58 -38 97 4 28 22 52 82 109 81 77 388 352 452 404 21 17
68 59 105 93 l67 61 -217 0 c-240 0 -265 5 -284 59 -7 20 -7 42 -1 65 19 68
10 67 441 64 374 -3 388 -4 402 -23z m-6456 -87 c2 -5 9 -8 16 -8 28 0 47 -37
44 -85 l-3 -46 -100 -41 c-55 -22 -121 -48 -147 -59 -27 -10 -48 -17 -48 -16
0 2 42 35 93 72 50 38 98 75 105 82 7 7 16 13 20 13 4 0 20 11 36 25 23 20 26
26 13 31 -13 5 -249 -20 -276 -29 -3 -1 -8 2 -11 8 -3 5 40 28 95 51 97 40
101 41 130 25 17 -9 32 -19 33 -23z m1028 1 c139 -56 130 -66 -43 -45 -71 9
-134 16 -141 16 -27 0 -8 -22 64 -71 41 -29 79 -60 85 -71 5 -10 25 -25 44
-32 19 -8 45 -24 57 -36 l23 -22 -50 20 c-27 11 -99 41 -160 65 l-110 45 -3
43 c-1 24 1 49 5 54 13 16 106 63 129 64 12 0 57 -13 100 -30z m-2028 -13
c178 -48 385 -236 495 -451 26 -50 77 -170 77 -180 0 -3 -196 -5 -435 -5
l-435 0 -11 28 c-32 81 -42 144 -43 257 -1 154 18 219 85 286 72 73 158 94
267 65z m3079 -11 c71 -30 120 -93 149 -191 13 -46 15 -83 11 -173 -3 -64 -9
-129 -15 -146 -5 -16 -15 -49 -21 -72 l-12 -43 -440 0 -440 0 6 23 c31 102
150 296 243 398 174 190 370 266 519 204z m-1373 -107 c-7 -10 -26 -10 -43 1
-24 15 -4 30 23 18 13 -7 22 -15 20 -19z m-516 -1 c3 -13 -4 -17 -31 -17 -44
0 -59 27 -19 33 38 5 47 3 50 -16z m59 -49 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13
3 -3 4 -12 1 -19z m726 -217 c27 -29 7 -19 -56 29 -33 25 -56 55 -82 106 -19
39 -35 74 -35 79 0 4 34 -37 76 -91 42 -54 85 -110 97 -123z m-942 151 c-10
-34 -33 -72 -43 -72 -5 0 -8 -6 -8 -13 0 -15 -31 -45 -75 -73 -26 -17 -25 -13
15 36 25 30 61 76 79 103 19 26 36 47 37 47 1 0 -1 -13 -5 -28z m426 -404 c32
5 59 9 60 8 1 0 -5 -10 -13 -21 -12 -16 -26 -20 -78 -20 -60 0 -121 19 -111
35 3 5 23 3 44 -2 27 -7 59 -7 98 0z"/>
<path d="M2531 3107 c-13 -21 -12 -21 5 -5 10 10 16 20 13 22 -3 3 -11 -5 -18
-17z"/>
<path d="M1702 3248 c-7 -7 -11 -21 -11 -32 1 -21 1 -21 6 -1 3 11 10 26 15
33 13 15 6 16 -10 0z"/>
<path d="M1750 3229 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M2025 3130 c-3 -6 1 -7 9 -4 18 7 21 14 7 14 -6 0 -13 -4 -16 -10z"/>
<path d="M5680 3031 c-75 -6 -75 -6 -87 -41 -7 -19 -12 -47 -12 -63 -1 -15 -5
-35 -10 -45 -5 -9 -17 -62 -26 -117 -9 -55 -21 -109 -25 -120 -5 -11 -11 -36
-14 -55 -3 -19 -11 -65 -17 -101 -19 -106 -23 -103 149 -96 159 7 209 18 310
69 98 49 150 122 171 239 10 52 10 79 0 130 -11 56 -19 70 -64 116 -40 39 -65
55 -106 67 -67 18 -171 25 -269 17z"/>
<path d="M2381 2784 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M2262 2655 c6 -14 13 -24 14 -22 6 6 -9 47 -17 47 -5 0 -3 -11 3 -25z"/>
<path d="M6825 2533 c-73 -29 -150 -97 -188 -168 -21 -39 -46 -102 -42 -107 6
-5 188 10 243 20 96 20 178 57 211 96 19 22 26 98 11 125 -26 49 -152 67 -235
34z"/>
<path d="M15458 2536 c-184 -50 -332 -318 -273 -497 27 -79 50 -99 126 -108
35 -5 71 -5 79 0 8 4 29 13 47 19 46 17 129 106 163 175 43 89 55 122 74 210
10 44 22 97 28 117 15 51 6 65 -53 82 -62 19 -126 19 -191 2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

+157
View File
@@ -0,0 +1,157 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="211.000000pt" height="192.000000pt" viewBox="0 0 211.000000 192.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,192.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M710 1871 c-321 -70 -565 -301 -652 -617 -30 -112 -31 -315 0 -429
77 -288 299 -514 587 -601 76 -23 110 -27 220 -28 126 -1 249 16 261 36 3 5
-5 26 -19 46 -14 20 -29 54 -32 74 -4 21 -11 38 -16 38 -5 0 -9 15 -8 33 1 30
2 29 18 -18 16 -51 81 -185 81 -170 0 5 11 -6 24 -24 14 -18 35 -40 48 -49 13
-9 25 -19 29 -24 3 -4 34 -22 69 -39 60 -29 104 -41 205 -55 50 -7 189 20 233
47 18 10 39 19 45 19 7 0 27 13 45 30 18 16 35 30 38 30 7 0 44 39 44 48 0 4
14 22 30 41 17 18 30 39 30 46 0 7 12 34 27 61 26 47 27 56 27 194 0 138 -1
147 -27 198 -15 30 -27 60 -27 67 0 18 -167 185 -185 185 -7 0 -21 3 -31 7
-14 5 -16 3 -11 -11 4 -11 3 -15 -4 -11 -6 4 -8 13 -5 21 6 16 -29 38 -50 30
-10 -4 -12 -2 -8 6 5 7 -1 9 -19 4 -14 -3 -29 -2 -32 4 -9 14 -88 12 -104 -2
-11 -10 -13 -10 -7 0 9 16 -65 17 -81 1 -8 -8 -17 -8 -29 -1 -15 8 -13 10 12
15 85 16 145 17 215 3 41 -9 76 -16 78 -16 9 0 -14 145 -36 220 -81 281 -313
506 -598 581 -115 30 -276 34 -385 10z m570 -496 l0 -95 -27 0 c-25 0 -25 1
-10 18 29 31 19 34 -18 6 -20 -15 -38 -25 -40 -22 -3 2 13 18 35 34 38 28 49
44 31 44 -4 0 -28 -18 -53 -40 -45 -39 -46 -39 -134 -42 l-89 -3 -3 -57 c-3
-56 -2 -58 21 -58 39 0 87 -12 82 -20 -2 -4 -27 -5 -55 -2 l-50 5 0 -77 0 -76
-94 0 c-108 0 -106 -2 -106 92 l0 60 -77 -6 c-164 -15 -263 -42 -263 -73 0
-17 75 -52 112 -53 14 0 28 -4 30 -9 2 -5 68 -15 148 -21 113 -10 183 -10 315
0 157 11 175 14 229 42 32 16 55 25 52 19 -5 -7 -1 -8 10 -4 11 4 13 8 6 11
-7 2 -12 10 -12 17 0 20 -58 42 -147 56 -82 13 -111 29 -52 29 45 0 169 -30
210 -51 66 -33 65 -42 -9 -78 -36 -18 -73 -42 -80 -52 -7 -10 -18 -19 -24 -19
-13 0 -77 -73 -95 -107 -6 -12 -18 -35 -26 -50 -8 -15 -22 -50 -30 -78 -11
-34 -16 -42 -16 -25 -2 53 48 155 108 222 l24 27 -64 -3 c-35 -2 -83 -4 -106
-5 l-43 -1 0 -200 0 -201 -97 3 -98 3 -3 196 -2 196 -85 7 c-88 6 -200 27
-249 46 -36 13 -66 49 -63 75 5 44 141 87 320 101 l77 6 0 54 0 53 -147 3
-148 3 -3 98 -3 97 406 0 405 0 0 -95z m148 -334 c11 -6 10 -10 -4 -15 -9 -3
-19 -4 -22 -1 -3 3 1 5 9 5 11 0 11 2 -1 10 -8 5 -10 10 -5 10 6 0 16 -4 23
-9z m189 -7 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-242 -35
c-4 -5 -12 -9 -18 -8 -9 0 -8 2 1 6 6 2 9 10 6 15 -4 7 -2 8 5 4 6 -4 9 -12 6
-17z m217 6 c49 5 74 3 95 -8 15 -8 52 -26 81 -41 28 -15 52 -32 52 -38 0 -6
-11 -3 -25 6 -13 9 -28 16 -32 16 -13 0 38 -32 55 -34 9 -2 16 -7 15 -12 -2
-13 28 -44 38 -39 8 5 59 -55 59 -69 0 -5 6 -22 14 -39 52 -117 49 -248 -9
-381 -27 -62 -26 -37 2 44 45 133 32 287 -34 393 -13 20 -26 37 -29 37 -3 0
-3 -4 1 -9 3 -6 -1 -25 -10 -43 -8 -18 -13 -25 -11 -16 3 10 1 20 -4 23 -6 4
-10 2 -10 -2 0 -5 -10 -13 -22 -18 -13 -6 -31 -26 -40 -45 -34 -70 -130 -170
-162 -170 -12 0 -27 -9 -34 -20 -15 -25 -28 -25 -49 0 -10 12 -30 20 -48 20
-16 0 -25 4 -19 8 6 4 16 17 23 30 7 12 16 20 20 18 5 -3 23 -1 42 5 80 25 99
27 99 13 0 -8 -7 -14 -15 -14 -8 0 -15 -7 -15 -15 0 -35 52 3 70 51 9 22 7 27
-10 31 -21 5 -24 21 -14 61 7 25 24 30 24 7 0 -12 3 -12 20 2 14 12 16 19 8
24 -7 4 -16 5 -21 2 -5 -3 -6 4 -2 16 4 15 2 21 -8 21 -7 0 -14 6 -14 14 0 8
6 12 13 9 8 -3 11 2 7 16 -7 26 -47 53 -69 44 -12 -4 -15 -3 -10 5 4 8 -3 11
-24 9 -16 -1 -30 -6 -30 -10 0 -5 -4 -6 -8 -3 -12 7 -36 -39 -29 -56 3 -7 6
-4 6 9 1 12 6 25 13 29 8 5 9 0 5 -17 l-6 -24 16 23 c25 36 93 25 93 -16 0 -7
-4 -11 -9 -7 -6 3 -7 -6 -2 -22 5 -16 5 -37 0 -48 -4 -11 -8 -16 -8 -11 -1 5
-7 3 -15 -3 -12 -10 -14 -9 -12 6 2 10 1 12 -1 6 -3 -7 -9 -13 -14 -13 -5 0
-9 -5 -9 -11 0 -5 3 -8 8 -5 9 5 47 -22 40 -29 -3 -3 -17 0 -32 6 -25 12 -31
22 -26 44 1 5 -8 1 -20 -10 -19 -17 -20 -21 -6 -31 21 -15 20 -31 -1 -43 -27
-14 -35 -14 -43 0 -6 9 -17 3 -40 -22 -22 -23 -29 -27 -21 -11 11 20 9 22 -16
23 -15 1 -32 1 -37 0 -5 -1 -6 5 -2 14 3 9 2 13 -4 10 -13 -8 -13 -35 0 -35 6
0 15 -12 21 -27 9 -24 7 -31 -15 -50 -14 -12 -26 -29 -26 -38 0 -8 -6 -24 -12
-35 -10 -16 -10 -24 -1 -40 9 -13 9 -21 2 -26 -16 -9 -21 1 -24 48 -2 29 3 47
14 56 9 7 11 11 4 8 -6 -4 -15 -1 -19 5 -4 7 -3 9 3 6 14 -9 63 34 63 55 0 9
-7 19 -16 22 -10 4 -14 16 -12 38 2 27 8 34 29 36 31 4 44 34 27 62 -12 19
-29 14 -71 -20 -17 -13 -20 -13 -31 2 -7 10 -24 22 -38 27 -28 11 -42 52 -24
75 6 8 31 31 54 50 24 20 41 36 37 36 -6 0 -65 -46 -87 -68 -53 -52 -88 -115
-113 -202 -13 -44 -13 -44 -14 -11 -3 91 117 247 235 306 32 16 60 32 62 36 1
3 24 2 50 -3 26 -5 77 -6 114 -3z m-35 9 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6
11 1 17 -2 13 -5z m-222 -33 c-3 -6 -11 -11 -16 -11 -5 0 -4 6 3 14 14 16 24
13 13 -3z m530 -102 c11 -17 -1 -21 -15 -4 -8 9 -8 15 -2 15 6 0 14 -5 17 -11z
m-685 -244 c0 -8 5 -15 11 -17 7 -2 6 -8 -4 -16 -12 -10 -14 -8 -14 15 0 15
-6 29 -12 31 -6 2 -11 8 -11 14 0 6 6 6 15 -2 8 -7 15 -18 15 -25z m764 19 c4
-10 1 -14 -6 -12 -15 5 -23 28 -10 28 5 0 13 -7 16 -16z m-28 -33 c-4 -5 -1
-11 6 -13 6 -2 -3 -10 -20 -17 -18 -8 -32 -17 -32 -22 0 -4 -13 0 -30 9 -35
20 -34 37 3 37 20 1 24 -2 15 -12 -16 -19 -7 -22 22 -6 15 7 19 13 10 14 -10
0 -8 3 5 9 27 11 27 11 21 1z m-789 -78 c-2 -16 -4 -3 -4 27 0 30 2 43 4 28 2
-16 2 -40 0 -55z m153 56 c0 -5 -5 -9 -12 -9 -6 0 -19 -6 -27 -14 -14 -13 -19
-12 -36 1 -11 9 -13 13 -5 11 21 -7 63 10 55 22 -3 6 1 7 9 4 9 -3 16 -10 16
-15z m666 -25 c-4 -9 -9 -15 -11 -12 -3 3 -3 13 1 22 4 9 9 15 11 12 3 -3 3
-13 -1 -22z m-650 -17 c4 -4 -2 -7 -14 -7 -12 0 -22 4 -22 9 0 10 26 9 36 -2z
m504 2 c23 1 23 0 -7 -15 -26 -13 -33 -23 -34 -48 0 -26 -2 -28 -8 -11 -5 11
-7 23 -5 26 2 3 -8 12 -21 19 -31 16 -33 34 -4 25 16 -5 19 -4 14 6 -6 9 -2
10 16 5 13 -4 35 -7 49 -7z m-362 -11 c-8 -7 -18 -23 -21 -36 -5 -19 -2 -22
15 -16 26 8 68 -14 68 -37 0 -14 7 -16 43 -12 23 4 44 10 45 15 13 32 147 49
147 18 0 -10 10 -15 33 -14 17 1 30 -2 27 -6 -3 -5 1 -10 7 -13 7 -3 -6 -2
-29 0 -34 5 -42 2 -46 -13 -4 -16 -5 -16 -6 3 -1 15 -6 20 -18 18 -10 -2 -24
-4 -32 -4 -9 -1 -12 -11 -9 -36 4 -35 3 -36 -24 -30 -21 5 -28 3 -28 -8 0 -8
-8 -21 -17 -28 -15 -11 -16 -11 -5 1 18 21 15 32 -7 21 -10 -6 -22 -7 -26 -3
-4 4 -5 -3 -2 -15 3 -13 1 -23 -4 -23 -5 0 -9 13 -9 29 0 29 -27 68 -39 56 -3
-4 2 -12 12 -19 21 -16 22 -27 2 -20 -21 8 -19 -13 3 -25 19 -12 12 -14 -12
-5 -9 3 -16 14 -16 23 0 9 -5 22 -12 29 -7 7 -8 12 -2 12 5 0 10 11 10 24 1
18 -2 22 -17 19 -11 -3 -19 -10 -19 -15 0 -5 -7 -3 -15 6 -20 19 -19 28 1 24
10 -2 19 2 21 9 5 14 -23 11 -39 -5 -7 -7 -18 -12 -24 -12 -7 0 -14 -8 -17
-17 -2 -11 -7 -4 -11 18 -6 27 -3 45 9 65 17 30 17 30 -1 -38 -5 -23 -5 -23
11 -3 9 11 21 32 27 48 5 15 17 27 26 27 14 0 14 -1 0 -12z m408 -10 c4 -7 3
-8 -4 -4 -7 4 -12 0 -12 -10 0 -10 -3 -15 -6 -11 -7 6 2 37 10 37 3 0 8 -5 12
-12z m-568 -41 c2 -9 -2 -17 -8 -17 -6 0 -8 5 -4 11 3 6 0 16 -7 21 -12 8 -11
9 1 5 8 -2 16 -11 18 -20z m-115 -87 c24 -47 21 -72 -3 -32 -11 18 -23 54 -25
80 -4 37 -3 41 4 16 4 -17 15 -45 24 -64z m152 40 c-3 -5 -11 -10 -16 -10 -6
0 -7 5 -4 10 3 6 11 10 16 10 6 0 7 -4 4 -10z m395 -32 c0 -19 -2 -20 -10 -8
-13 19 -13 30 0 30 6 0 10 -10 10 -22z m-397 -61 c-3 -5 -10 -2 -15 8 -9 15
-12 15 -35 -7 -25 -22 -25 -22 -14 -1 6 12 16 23 23 26 17 5 48 -15 41 -26z
m562 -21 c6 -4 0 -3 -12 3 -12 6 -25 16 -28 21 -3 6 -11 10 -17 10 -6 0 -5 -7
3 -16 12 -15 11 -16 -9 -10 -13 5 -22 3 -22 -3 0 -10 14 -15 34 -12 4 1 17 -1
28 -5 14 -4 17 -8 8 -14 -6 -4 -11 -10 -11 -14 2 -10 -59 -59 -65 -53 -4 3
-17 -6 -30 -21 -20 -23 -25 -25 -34 -12 -9 13 -10 13 -10 0 0 -16 -38 -45 -48
-36 -3 3 0 6 6 6 7 0 12 5 12 11 0 6 -8 8 -17 5 -17 -6 -17 -5 0 8 9 7 17 16
17 20 0 11 -28 6 -33 -6 -4 -10 -6 -10 -6 -1 -1 6 4 15 9 18 15 9 12 25 -4 19
-22 -9 -26 -29 -10 -59 11 -22 11 -25 1 -16 -8 6 -17 8 -20 4 -4 -3 -7 8 -7
25 0 25 -4 32 -20 32 -14 0 -20 -7 -21 -22 -1 -16 -3 -18 -6 -7 -3 14 -42 34
-49 26 -1 -1 1 -17 3 -34 6 -35 22 -45 24 -15 1 15 2 15 6 0 2 -9 12 -19 21
-21 9 -3 1 -4 -18 -3 -28 1 -35 6 -40 26 l-6 25 -7 -24 c-5 -21 -8 -22 -21
-11 -9 7 -16 20 -16 29 1 11 5 8 15 -9 8 -14 15 -20 15 -15 0 6 3 21 7 34 5
20 3 23 -10 18 -9 -3 -18 -1 -20 6 -7 20 -18 1 -20 -36 -2 -35 -13 -38 -44
-14 -7 5 -13 6 -13 3 0 -4 -13 1 -30 10 l-29 18 30 27 c18 16 26 30 20 33 -6
4 -24 -6 -40 -23 l-29 -30 -22 24 c-19 20 -21 27 -10 40 10 12 10 15 -1 16 -8
0 -5 4 6 8 12 5 25 3 33 -6 21 -20 37 -15 18 6 -10 10 -13 22 -8 25 5 3 15 -6
22 -19 7 -14 17 -25 22 -25 5 0 6 5 2 12 -4 7 -3 8 5 4 6 -4 8 -12 5 -18 -5
-8 -1 -9 10 -5 9 4 15 3 11 -2 -8 -15 94 -44 155 -45 38 -1 68 6 99 21 24 13
47 20 52 17 5 -3 10 0 10 5 1 6 2 15 3 20 0 5 5 13 10 18 5 5 6 3 2 -5 -6 -10
-3 -13 11 -10 10 1 29 -8 41 -20 13 -13 27 -20 33 -16 5 3 -5 17 -23 32 l-33
25 25 27 25 26 25 -20 c14 -12 30 -25 35 -30z m-624 -11 c11 6 11 5 2 -5 -12
-14 -33 -6 -33 13 0 8 3 7 9 -2 5 -8 14 -10 22 -6z m348 -136 c9 -27 9 -30 -4
-19 -8 7 -15 21 -15 31 0 28 7 23 19 -12z m221 27 c0 -2 -12 -11 -27 -20 l-28
-17 24 20 c23 21 31 25 31 17z m-475 -44 c-3 -3 -11 0 -18 7 -9 10 -8 11 6 5
10 -3 15 -9 12 -12z m45 -12 c8 -5 11 -10 5 -10 -5 0 -17 5 -25 10 -8 5 -10
10 -5 10 6 0 17 -5 25 -10z m316 -9 c-8 -13 -91 -34 -112 -28 -13 3 -9 5 11 7
17 1 46 8 65 15 44 17 42 17 36 6z m-306 -27 c0 -2 -7 -4 -15 -4 -8 0 -15 4
-15 10 0 5 7 7 15 4 8 -4 15 -8 15 -10z m57 10 c-3 -3 -12 -4 -19 -1 -8 3 -5
6 6 6 11 1 17 -2 13 -5z m300 -16 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4
-12 1 -19z m-239 5 c-10 -2 -26 -2 -35 0 -10 3 -2 5 17 5 19 0 27 -2 18 -5z
m209 1 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-179 -59 c-3
-3 -9 2 -12 12 -6 14 -5 15 5 6 7 -7 10 -15 7 -18z"/>
<path d="M1280 1020 c-9 -6 -10 -10 -3 -10 6 0 15 5 18 10 8 12 4 12 -15 0z"/>
<path d="M1405 976 c-65 -32 -55 -32 20 -1 33 13 53 25 45 25 -8 0 -37 -11
-65 -24z"/>
<path d="M1655 981 c87 -31 91 -32 40 -6 -27 13 -59 25 -70 25 -11 -1 3 -9 30
-19z"/>
<path d="M1269 813 c-13 -16 -12 -17 4 -4 9 7 17 15 17 17 0 8 -8 3 -21 -13z"/>
<path d="M1440 701 c-8 -6 -18 -7 -24 -4 -5 3 -6 1 -2 -5 5 -8 13 -9 25 -2 10
5 22 6 26 2 5 -4 5 -1 1 6 -8 14 -7 14 -26 3z"/>
<path d="M1620 426 c0 -2 7 -7 16 -10 8 -3 12 -2 9 4 -6 10 -25 14 -25 6z"/>
<path d="M1561 397 c-15 -19 -2 -29 15 -12 8 7 14 16 14 19 0 11 -17 6 -29 -7z"/>
<path d="M1820 312 c0 -12 19 -26 26 -19 2 2 -2 10 -11 17 -9 8 -15 8 -15 2z"/>
<path d="M1290 295 c-11 -14 -11 -18 4 -33 17 -16 18 -16 11 8 -6 22 -6 23 6
8 9 -12 19 -15 28 -9 9 6 10 11 2 15 -6 4 -11 4 -11 0 0 -4 -6 0 -13 10 -12
16 -14 17 -27 1z"/>
<path d="M1732 288 c-7 -7 -18 -13 -25 -13 -7 0 -11 -9 -9 -20 4 -20 3 -20
-12 0 -11 15 -15 16 -15 5 0 -23 26 -54 31 -38 4 11 8 10 21 -1 20 -16 22 -8
6 21 -7 14 -8 23 0 31 7 7 12 1 17 -18 6 -22 8 -25 16 -12 5 9 15 14 23 11 20
-8 19 1 -2 26 -20 23 -34 25 -51 8z"/>
<path d="M1388 240 c-9 -16 -13 -32 -8 -35 4 -3 11 3 15 13 7 15 9 14 16 -8 7
-19 8 -16 4 15 -3 27 -1 35 5 25 7 -12 12 -12 22 -2 8 8 8 12 1 12 -6 0 -17 2
-25 5 -7 3 -20 -8 -30 -25z"/>
<path d="M1366 244 c-20 -19 -20 -25 -2 -18 8 3 17 12 20 20 7 18 1 18 -18 -2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="211.000000pt" height="273.000000pt" viewBox="0 0 211.000000 273.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,273.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M173 2490 c-67 -40 -63 33 -63 -1152 0 -1034 1 -1074 19 -1102 10
-15 32 -37 47 -47 28 -18 63 -19 889 -19 835 0 861 1 892 20 67 40 63 -33 63
1151 0 1071 0 1072 -21 1106 -41 67 11 63 -936 63 -833 0 -859 -1 -890 -20z
m998 -590 c30 -6 92 -28 138 -50 153 -73 255 -204 301 -386 24 -92 25 -145 5
-239 -68 -323 -394 -520 -708 -428 -192 56 -350 231 -388 431 -16 84 -6 221
21 299 92 264 362 423 631 373z"/>
<path d="M1035 1768 c-81 -29 -157 -108 -186 -193 -7 -22 -21 -49 -30 -60 -9
-11 -24 -34 -33 -52 -9 -18 -33 -44 -53 -59 -77 -56 -80 -78 -23 -136 22 -23
40 -47 40 -53 0 -7 6 -18 14 -24 12 -10 18 -4 32 38 19 51 32 61 86 61 52 0
122 -121 135 -234 5 -43 8 -47 19 -31 12 16 14 14 28 -20 9 -21 16 -41 16 -46
0 -39 141 48 202 125 50 63 89 145 96 201 l4 42 -46 6 c-25 4 -74 21 -108 38
-72 35 -178 101 -178 110 0 3 11 11 24 17 13 6 29 25 35 42 l11 32 -65 -4 -65
-4 33 34 c17 18 60 47 95 64 54 27 69 30 120 25 31 -3 66 -9 77 -13 38 -15 -7
28 -50 47 -93 43 -212 12 -300 -76 -25 -25 -41 -37 -36 -27 14 27 94 98 132
118 20 10 57 18 91 18 32 1 58 4 58 7 0 20 -125 25 -175 7z m-160 -298 c-3 -5
-13 -10 -21 -10 -8 0 -14 5 -14 10 0 6 9 10 21 10 11 0 17 -4 14 -10z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="105.000000pt" height="107.000000pt" viewBox="0 0 105.000000 107.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,107.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
</g>
</svg>

After

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="165.000000pt" height="171.000000pt" viewBox="0 0 165.000000 171.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,171.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
</g>
</svg>

After

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="814.000000pt" height="811.000000pt" viewBox="0 0 814.000000 811.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,811.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M3775 7969 c-361 -29 -748 -111 -1051 -224 -1194 -446 -2091 -1443
-2402 -2670 -138 -545 -158 -1074 -60 -1635 176 -1019 786 -1951 1653 -2531
611 -408 1294 -624 2040 -646 1052 -31 2070 373 2816 1117 479 478 798 1014
985 1655 94 321 154 738 154 1070 0 326 -59 742 -150 1057 -378 1310 -1395
2324 -2684 2677 -425 116 -891 163 -1301 130z m635 -2137 c443 -97 831 -360
1077 -732 190 -287 293 -626 293 -965 0 -544 -255 -1049 -695 -1375 -296 -220
-643 -335 -1010 -333 -469 1 -885 179 -1216 519 -179 185 -292 363 -380 604
-351 958 212 2015 1205 2266 148 38 202 43 426 40 162 -3 225 -8 300 -24z"/>
<path d="M4052 5449 c-202 -54 -391 -189 -519 -370 -59 -84 -128 -226 -150
-313 -14 -54 -23 -71 -44 -82 -37 -19 -75 -66 -89 -111 -33 -102 -88 -171
-204 -255 -149 -108 -184 -158 -171 -244 9 -62 46 -104 93 -105 32 -1 34 -2
12 -8 -40 -11 -29 -32 35 -65 70 -36 72 -38 81 -91 9 -54 30 -95 68 -127 40
-35 46 -35 46 3 0 17 16 63 35 102 27 55 35 83 35 127 l0 56 143 10 c107 8
154 16 192 32 45 20 48 20 27 3 -12 -11 -28 -21 -35 -24 -7 -3 6 -23 34 -53
86 -91 162 -226 224 -399 46 -127 65 -203 79 -320 l12 -100 27 46 c15 25 32
61 38 80 19 54 29 57 29 8 0 -57 30 -176 64 -251 l26 -58 67 25 c408 154 788
631 828 1040 4 39 9 77 11 86 4 14 -9 17 -83 22 -211 13 -423 104 -788 337
-66 42 -137 83 -159 92 l-38 15 58 21 c92 33 169 123 187 218 5 28 3 32 -21
37 -51 10 -295 -9 -335 -26 -35 -15 -37 -15 -28 1 18 34 187 188 258 235 241
160 494 197 721 106 41 -16 77 -28 79 -25 9 8 -69 86 -120 119 -117 77 -294
124 -427 114 -236 -19 -543 -208 -694 -430 -67 -97 -73 -91 -12 13 115 196
305 358 501 427 76 27 88 28 253 27 l173 0 -45 23 c-77 39 -151 53 -281 52
-86 0 -141 -6 -193 -20z m-553 -895 c2 -2 -1 -15 -7 -29 -8 -17 -20 -25 -36
-25 -13 0 -38 -3 -56 -7 l-33 -6 19 31 c20 35 57 53 89 45 11 -3 22 -7 24 -9z
m-342 -801 c-3 -10 -5 -2 -5 17 0 19 2 27 5 18 2 -10 2 -26 0 -35z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

@@ -0,0 +1,528 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="423.000000pt" height="637.000000pt" viewBox="0 0 423.000000 637.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,637.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M0 3185 l0 -3185 2115 0 2115 0 0 3185 0 3185 -2115 0 -2115 0 0
-3185z m602 3011 c97 -21 173 -62 242 -132 98 -97 146 -209 146 -339 0 -130
-48 -243 -146 -341 -292 -294 -788 -106 -821 311 -15 190 92 372 268 459 109
53 199 65 311 42z m1985 -388 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1
-19z m-255 -163 c4 -34 3 -35 -30 -35 -31 0 -34 2 -28 23 3 12 6 28 6 35 0 6
11 12 24 12 20 0 25 -6 28 -35z m378 -45 c6 -11 8 -20 6 -20 -3 0 -10 9 -16
20 -6 11 -8 20 -6 20 3 0 10 -9 16 -20z m-690 -14 c0 -2 -7 -7 -16 -10 -8 -3
-12 -2 -9 4 6 10 25 14 25 6z m673 -23 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5
17 0 24 -2 18 -5z m-97 -18 c-36 -19 -45 -19 -20 0 10 8 26 14 34 15 8 0 2 -7
-14 -15z m-659 -1 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m591
-54 c-7 -10 -14 -17 -17 -15 -4 4 18 35 25 35 2 0 -1 -9 -8 -20z m319 -17 c-3
-10 -5 -4 -5 12 0 17 2 24 5 18 2 -7 2 -21 0 -30z m-128 11 c1 -1 1 -7 0 -13
-3 -6 -16 -2 -34 10 l-30 20 30 -7 c17 -4 32 -8 34 -10z m-1100 -7 c-2 -1 -13
-9 -24 -17 -19 -14 -19 -14 -6 3 7 9 18 17 24 17 6 0 8 -1 6 -3z m1061 -12 c0
-8 -4 -15 -10 -15 -5 0 -10 7 -10 15 0 8 5 15 10 15 6 0 10 -7 10 -15z m-1187
-2 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5 17 0 24 -2 18 -5z m107 -30 c10 9 13
9 17 0 3 -7 11 -13 19 -13 7 0 19 -9 26 -20 13 -21 48 -28 48 -10 0 6 -4 10
-10 10 -5 0 -10 5 -10 10 0 6 25 10 58 9 52 -1 54 -2 30 -12 -35 -14 -36 -27
-2 -27 17 0 23 4 18 13 -5 8 -2 8 9 -2 21 -17 22 -65 1 -85 -14 -14 -14 -16 0
-16 21 0 49 46 43 70 -3 13 0 20 9 20 17 0 18 12 2 28 -9 9 -2 12 31 12 38 0
42 -2 31 -15 -7 -9 -10 -18 -6 -22 3 -4 12 2 20 12 9 13 29 20 60 22 40 3 46
1 46 -17 0 -16 7 -20 30 -20 34 0 40 15 10 23 -11 3 -18 1 -14 -4 3 -5 0 -9
-5 -9 -6 0 -11 7 -11 15 0 12 14 15 70 15 62 0 70 -2 70 -19 0 -32 32 -36 55
-7 24 30 31 32 39 10 5 -13 3 -14 -7 -6 -10 9 -20 -2 -45 -48 -18 -32 -38 -61
-45 -63 -6 -3 2 -5 18 -5 17 0 25 2 18 4 -7 3 -9 12 -6 20 4 12 8 12 13 4 5
-9 9 -9 14 -1 4 6 2 11 -4 11 -6 0 -4 12 6 32 l17 32 19 -38 c11 -21 17 -44
14 -52 -4 -11 7 -14 52 -13 31 0 51 3 45 6 -8 3 -13 23 -13 51 l0 46 49 -48
49 -48 4 61 c2 45 0 60 -9 57 -7 -3 -15 -1 -18 4 -4 6 8 10 26 10 26 0 30 -3
21 -12 -29 -29 -11 -33 143 -32 146 1 155 0 149 -18 -4 -12 0 -18 11 -18 11 0
15 5 11 15 -3 10 3 17 21 21 24 6 33 0 76 -47 61 -68 67 -84 67 -172 0 -91 -7
-117 -31 -117 -29 0 -35 -28 -10 -51 11 -11 21 -15 21 -9 0 6 -7 13 -15 16
-24 10 -18 34 10 34 13 0 29 8 35 18 11 16 11 16 6 -1 -5 -17 18 -77 30 -77 2
0 -2 14 -11 30 -18 35 -12 41 6 8 7 -13 12 -39 12 -58 -1 -31 -1 -32 7 -10 7
22 8 21 9 -12 1 -37 -12 -51 -22 -25 -3 7 -6 5 -6 -5 -1 -14 8 -18 37 -19 20
-1 40 -1 44 0 4 0 11 -11 14 -27 4 -15 13 -34 21 -44 8 -9 13 -30 11 -49 -2
-25 -11 -37 -35 -51 -28 -15 -33 -15 -33 -3 0 8 8 15 18 15 10 0 23 5 30 12
17 17 15 63 -3 78 -8 7 -16 22 -16 34 -1 18 -2 18 -6 3 -3 -10 3 -27 12 -37
25 -27 16 -73 -15 -80 -16 -4 -26 -14 -28 -28 -7 -46 -72 -9 -72 41 0 11 -4
15 -12 11 -7 -4 -8 -3 -4 4 14 23 -6 105 -30 127 -29 27 -32 57 -6 49 16 -5
16 -5 -1 6 -9 6 -15 15 -12 21 4 5 1 9 -5 9 -8 0 -11 -14 -8 -40 l4 -40 -66
-1 c-36 -1 -68 -1 -73 0 -4 1 -31 1 -60 1 -28 0 -61 0 -72 0 -217 0 -260 -2
-274 -13 -12 -9 -13 -9 -7 1 6 10 -35 12 -201 12 -230 -1 -233 -1 -249 19 -9
11 -13 11 -19 1 -4 -7 -2 -16 6 -22 16 -10 -52 -5 -69 6 -6 3 -13 2 -16 -2 -7
-11 -56 -3 -75 12 -11 8 -13 8 -7 -1 4 -7 3 -13 -3 -13 -5 0 -11 6 -14 13 -4
10 -7 10 -18 0 -14 -14 -279 -19 -279 -6 0 3 8 16 18 27 16 20 16 20 -1 7 -10
-8 -25 -28 -33 -45 -8 -17 -12 -23 -9 -13 4 15 -3 17 -50 17 -30 0 -55 5 -55
10 0 6 5 10 10 10 6 0 10 4 10 10 0 5 -7 7 -15 4 -8 -4 -15 -12 -15 -20 0 -12
-36 -14 -205 -14 l-205 0 36 73 c20 39 51 88 68 108 17 20 43 56 59 80 30 48
62 95 102 148 14 19 25 45 25 58 0 20 5 23 41 23 l41 0 -4 -49 c-2 -36 0 -47
10 -44 6 3 12 16 12 29 0 13 4 24 8 24 13 0 53 -46 46 -52 -3 -3 10 -6 30 -5
l35 1 -27 17 c-15 9 -35 25 -45 36 -16 19 -16 21 -1 34 9 7 31 12 50 10 19 -1
34 2 34 8 0 17 -19 22 -41 10 -15 -8 -19 -8 -15 0 14 22 -9 10 -42 -21 l-34
-33 4 33 c4 31 3 33 -19 27 -13 -3 -23 -1 -23 5 0 5 16 10 35 10 19 0 35 -4
35 -10 0 -5 -4 -10 -10 -10 -5 0 -10 -7 -10 -17 0 -14 2 -14 20 2 11 10 17 22
14 26 -3 5 27 9 65 9 43 0 71 4 71 11 0 5 5 7 10 4 18 -11 -10 -36 -31 -30
-17 6 -19 0 -19 -50 0 -50 3 -57 25 -67 18 -8 35 -9 53 -2 24 8 28 15 32 66 5
51 3 57 -14 55 -11 -1 -20 5 -21 16 -2 11 1 14 8 10 7 -5 27 -8 45 -8 25 -1
31 3 27 15 -4 12 -2 11 8 -2 11 -14 16 -15 27 -5z m805 -33 c10 -11 29 -20 42
-20 18 0 23 -5 23 -27 l0 -27 -43 42 c-23 23 -46 42 -50 42 -4 0 -7 -27 -7
-60 0 -51 -3 -60 -17 -60 -20 0 -57 56 -47 71 3 5 16 9 30 9 15 0 24 6 24 16
0 10 -6 14 -14 11 -10 -4 -13 -1 -9 9 8 20 47 17 68 -6z m-895 -54 c0 -41 -21
-60 -55 -52 -21 5 -25 12 -25 46 0 40 0 40 40 40 39 0 40 -1 40 -34z m-370
-30 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m1867 -213
c-2 -21 -4 -6 -4 32 0 39 2 55 4 38 2 -18 2 -50 0 -70z m-2657 -190 c0 -1 -8
0 -17 3 -10 4 2 -13 26 -36 37 -36 49 -41 78 -38 l33 4 -27 -23 -27 -23 -63
67 c-67 73 -84 109 -33 71 17 -12 30 -23 30 -25z m71 -30 c13 -15 12 -15 -8
-4 -24 12 -29 21 -14 21 5 0 15 -7 22 -17z m1116 -35 c-3 -8 -6 -5 -6 6 -1 11
2 17 5 13 3 -3 4 -12 1 -19z m90 0 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4
-12 1 -19z m93 2 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0
11 -4 11 -10z m348 3 c-15 -2 -42 -2 -60 0 -18 2 -6 4 27 4 33 0 48 -2 33 -4z
m254 -56 c-29 -29 -52 -59 -52 -66 0 -8 12 -30 26 -50 l26 -36 -31 33 c-17 18
-31 40 -31 49 0 16 101 132 109 126 3 -2 -19 -27 -47 -56z m559 46 c13 -16 12
-17 -3 -4 -10 7 -18 15 -18 17 0 8 8 3 21 -13z m-1515 -12 c-8 -13 -84 -51
-101 -51 -12 0 -12 5 -3 26 10 21 17 25 49 23 21 -2 41 0 45 4 10 10 16 9 10
-2z m164 -16 c5 3 11 1 15 -5 3 -5 -3 -10 -15 -10 -13 0 -19 -4 -14 -11 4 -8
0 -8 -15 0 -11 7 -21 16 -21 21 0 14 17 12 23 -2 3 -7 6 -2 7 12 2 18 4 20 7
7 2 -9 8 -15 13 -12z m413 -20 c-7 -21 -13 -19 -13 6 0 11 4 18 10 14 5 -3 7
-12 3 -20z m214 3 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m34 5
c13 -16 12 -17 -3 -4 -17 13 -22 21 -14 21 2 0 10 -8 17 -17z m722 2 c-3 -9
-8 -14 -10 -11 -3 3 -2 9 2 15 9 16 15 13 8 -4z m-2353 -15 c-27 -7 -60 -2
-60 9 0 4 19 5 43 2 35 -4 38 -5 17 -11z m1257 -2 c-3 -8 -6 -5 -6 6 -1 11 2
17 5 13 3 -3 4 -12 1 -19z m20 0 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4
-12 1 -19z m417 14 c2 -4 -4 -8 -15 -8 -10 0 -19 4 -19 8 0 4 6 8 14 8 8 0 17
-4 20 -8z m-111 -22 c3 -11 1 -18 -4 -14 -5 3 -9 12 -9 20 0 20 7 17 13 -6z
m505 -11 c-1 -17 5 -35 13 -40 10 -6 7 -9 -13 -9 -20 0 -26 -4 -22 -15 7 -17
-4 -19 -26 -5 -11 7 -11 10 -2 10 7 0 10 5 6 11 -4 8 -12 3 -20 -12 l-13 -24
-1 28 c0 20 5 27 20 27 11 0 20 -4 20 -10 0 -5 7 -7 15 -4 8 4 15 13 15 21 0
10 -6 13 -16 9 -10 -4 -14 -2 -11 6 2 7 10 12 16 11 6 -2 11 4 11 12 0 8 2 15
4 15 3 0 4 -14 4 -31z m-1091 15 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17
-2 13 -5z m-1122 -36 c-41 -26 -51 -28 -73 -19 -13 7 -23 13 -21 15 9 9 88 31
114 33 26 1 25 -1 -20 -29z m522 17 c0 -8 -4 -12 -9 -9 -5 3 -6 10 -3 15 9 13
12 11 12 -6z m1980 9 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z
m-343 -12 c3 -5 -1 -9 -9 -9 -8 0 -12 4 -9 9 3 4 7 8 9 8 2 0 6 -4 9 -8z m366
-2 c-8 -5 -22 -10 -32 -10 -9 0 -19 -6 -21 -12 -3 -8 -6 -7 -6 4 -1 15 8 19
64 26 6 1 3 -3 -5 -8z m-773 -6 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17
-2 13 -5z m254 -11 c11 -15 11 -16 -1 -6 -11 10 -17 10 -29 0 -14 -11 -14 -10
-2 6 7 9 15 17 16 17 1 0 9 -8 16 -17z m-51 -3 c0 -5 -2 -10 -4 -10 -3 0 -8 5
-11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-1549 -33 c-10 -9 -11 -8 -5 6 3
10 9 15 12 12 3 -3 0 -11 -7 -18z m531 -19 l4 -38 -39 0 c-32 0 -38 3 -33 16
3 9 6 26 6 38 0 18 6 22 29 21 27 0 30 -4 33 -37z m985 15 c0 -9 -4 -10 -14
-2 -7 6 -13 12 -13 14 0 1 6 2 13 2 8 0 14 -6 14 -14z m133 -3 c0 -5 -4 -10
-10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m177 4 c-3 -3
-12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-1786 -21 c13 -16 12 -17 -3
-4 -17 13 -23 8 -19 -13 1 -5 -4 -5 -11 1 -7 6 -20 13 -28 17 -8 3 -5 4 7 2
13 -2 26 0 29 5 7 12 10 12 25 -8z m984 7 c-3 -5 -11 -10 -16 -10 -6 0 -7 5
-4 10 3 6 11 10 16 10 6 0 7 -4 4 -10z m985 -15 c-13 -14 -31 -25 -39 -24 -11
0 -10 3 4 9 12 4 27 15 34 24 7 9 16 16 19 16 3 0 -5 -11 -18 -25z m-810 -17
c0 -5 -16 -8 -35 -8 -19 0 -35 3 -35 8 0 4 16 7 35 7 19 0 35 -3 35 -7z m998
-13 c-3 -3 -9 2 -12 12 -6 14 -5 15 5 6 7 -7 10 -15 7 -18z m52 7 c0 -5 -7 -9
-15 -9 -8 0 -12 4 -9 9 3 4 9 8 15 8 5 0 9 -4 9 -8z m-700 -46 c13 -9 19 -16
13 -16 -7 0 -15 5 -18 10 -3 6 -14 10 -23 10 -11 0 -18 8 -19 21 -2 18 0 19
10 7 7 -8 23 -22 37 -32z m394 29 c-4 -8 -8 -15 -10 -15 -2 0 -4 7 -4 15 0 8
4 15 10 15 5 0 7 -7 4 -15z m-1214 -10 c-14 -8 -34 -14 -45 -14 -13 0 -8 5 15
14 46 18 61 18 30 0z m468 -17 c3 -26 1 -28 -32 -28 -31 0 -36 3 -36 23 0 31
9 39 40 35 19 -2 26 -10 28 -30z m-621 -13 c-20 -14 -37 -29 -37 -34 0 -9 -90
-51 -111 -51 -8 0 -1 7 15 15 15 8 35 15 43 15 7 0 25 11 38 24 31 31 67 56
80 56 5 0 -7 -11 -28 -25z m1336 5 c-6 -23 -31 -46 -40 -36 -3 3 -1 6 6 6 6 0
16 11 21 25 11 30 20 33 13 5z m58 3 c13 -16 12 -17 -3 -4 -17 13 -22 21 -14
21 2 0 10 -8 17 -17z m-2121 -29 c0 -24 -8 -46 -26 -67 -30 -36 -21 -47 41
-47 45 1 74 21 96 65 8 15 19 30 26 32 18 6 -24 -69 -50 -89 -47 -37 -186 -17
-162 23 4 6 3 14 -3 18 -6 4 -2 23 11 53 17 36 27 48 45 48 19 0 22 -5 22 -36z
m1808 19 c-10 -2 -26 -2 -35 0 -10 3 -2 5 17 5 19 0 27 -2 18 -5z m83 -10 c12
-16 12 -17 -1 -7 -8 6 -22 14 -30 17 -13 5 -12 6 1 6 9 1 23 -7 30 -16z m-364
-25 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m667 -39 c-2 -4 -15
-2 -28 4 -14 7 -20 15 -14 18 7 4 7 9 -1 13 -6 4 -11 11 -11 16 0 4 13 -3 29
-18 17 -14 28 -29 25 -33z m-1739 32 c-22 -4 -52 -14 -65 -24 -17 -12 -42 -17
-80 -15 l-55 1 62 6 c40 4 69 12 80 24 11 11 31 17 58 16 l40 -2 -40 -6z
m-206 -27 c14 -12 -19 -1 -35 12 -18 14 -18 14 6 3 14 -6 27 -13 29 -15z
m1688 20 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m63 -8 c-7 -7
-13 -7 -20 0 -6 6 -3 10 10 10 13 0 16 -4 10 -10z m117 -18 c-3 -8 -6 -5 -6 6
-1 11 2 17 5 13 3 -3 4 -12 1 -19z m-640 -27 c-2 -10 0 -26 5 -35 8 -13 3 -16
-27 -16 -30 0 -35 3 -35 23 0 14 3 18 8 10 9 -14 26 -5 35 20 9 23 21 22 14
-2z m108 9 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11
-10z m55 0 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4
-10z m-585 -28 c-3 -3 -11 0 -18 7 -9 10 -8 11 6 5 10 -3 15 -9 12 -12z m1040
8 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m163
-36 c-3 -14 -5 -12 -10 9 -3 19 -2 25 4 19 6 -6 8 -18 6 -28z m-543 6 c3 -6
-1 -7 -10 -4 -33 13 -66 -7 -100 -61 -44 -69 -62 -78 -133 -71 -32 3 -110 7
-174 9 -70 1 -118 6 -118 12 0 10 158 4 293 -11 52 -5 61 -3 84 18 14 12 31
36 39 51 9 15 24 37 35 48 20 20 73 26 84 9z m-609 -28 c-4 -3 -14 2 -24 12
-16 18 -16 18 6 6 13 -6 21 -14 18 -18z m1803 -16 c-3 -3 -11 5 -18 17 -13 21
-12 21 5 5 10 -10 16 -20 13 -22z m-1419 4 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11
10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-1260 -51 c0 -5 -7 -9 -15 -9 -15 0
-20 12 -9 23 8 8 24 -1 24 -14z m910 -4 c13 -14 21 -25 18 -25 -2 0 -15 11
-28 25 -13 14 -21 25 -18 25 2 0 15 -11 28 -25z m1637 3 c-3 -8 -6 -5 -6 6 -1
11 2 17 5 13 3 -3 4 -12 1 -19z m276 -132 c16 -62 17 -80 3 -41 -9 22 -16 47
-16 56 0 8 -14 28 -31 45 -17 16 -40 43 -51 59 -12 17 3 3 33 -29 30 -33 58
-73 62 -90z m-115 66 c2 -7 -2 -10 -11 -6 -8 3 -18 1 -22 -5 -8 -14 -25 -14
-25 0 0 5 5 7 10 4 6 -3 10 1 10 10 0 19 31 17 38 -3z m-994 -24 c-5 -9 -2 -9
9 1 9 7 17 11 17 8 0 -3 3 -13 7 -23 5 -13 3 -15 -8 -10 -8 4 -6 1 4 -7 27
-23 20 -37 -19 -37 -35 0 -35 1 -29 33 8 35 13 47 21 47 3 0 2 -6 -2 -12z
m346 -2 c-7 -7 -14 -6 -21 1 -9 9 -7 12 9 10 14 -1 18 -5 12 -11z m322 -8 c-7
-7 -12 -8 -12 -2 0 6 3 14 7 17 3 4 9 5 12 2 2 -3 -1 -11 -7 -17z m-1245 -35
c-3 -10 -5 -4 -5 12 0 17 2 24 5 18 2 -7 2 -21 0 -30z m1288 27 c3 -5 1 -10
-4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-370 -9 c3 -5 2
-12 -3 -15 -5 -3 -9 1 -9 9 0 17 3 19 12 6z m-175 -38 c0 -18 -3 -34 -7 -35
-5 0 -19 -2 -33 -3 -23 -2 -25 1 -22 34 3 32 7 36 33 36 26 0 29 -3 29 -32z
m680 2 c14 -19 14 -19 -2 -6 -10 7 -18 18 -18 24 0 6 1 8 3 6 1 -2 9 -13 17
-24z m-1953 -11 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m535
-41 c-3 -16 -7 -21 -12 -12 -6 8 -9 6 -13 -7 -4 -16 -5 -16 -6 -2 0 9 4 20 9
23 6 3 10 16 10 28 0 16 3 18 9 9 4 -7 6 -25 3 -39z m-848 -34 c-3 -5 -22 -9
-42 -9 -27 0 -33 3 -22 10 12 7 13 15 3 40 l-11 30 39 -31 c21 -17 37 -35 33
-40z m351 61 c3 -5 2 -10 -4 -10 -5 0 -13 5 -16 10 -3 6 -2 10 4 10 5 0 13 -4
16 -10z m2001 -12 c-10 -6 -22 -6 -26 -2 -5 5 3 10 18 11 22 1 24 0 8 -9z
m164 8 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-1774
-101 c11 -17 14 -26 5 -21 -10 7 -12 2 -6 -25 4 -25 3 -30 -4 -19 -6 8 -11 23
-11 33 0 10 -4 16 -8 13 -5 -3 -15 10 -24 29 -8 19 -11 32 -5 28 6 -4 8 0 4
10 -23 57 -11 45 49 -48z m1725 78 c12 -16 12 -17 -1 -6 -8 6 -33 13 -55 16
l-40 4 41 1 c29 1 46 -3 55 -15z m-1434 -15 c-3 -8 -6 -5 -6 6 -1 11 2 17 5
13 3 -3 4 -12 1 -19z m1506 -45 c-10 -21 -26 -49 -35 -62 -10 -13 -18 -31 -19
-40 0 -12 -2 -13 -6 -2 -3 7 10 42 28 77 37 69 60 88 32 27z m-1155 10 c-10
-2 -28 -2 -40 0 -13 2 -5 4 17 4 22 1 32 -1 23 -4z m86 1 c16 -6 12 -24 -5
-24 -6 0 -8 4 -5 9 4 5 0 12 -6 14 -7 3 -10 6 -6 6 3 1 13 -2 22 -5z m303 -41
c-3 -10 -5 -2 -5 17 0 19 2 27 5 18 2 -10 2 -26 0 -35z m-1584 10 c-7 -2 -21
-2 -30 0 -10 3 -4 5 12 5 17 0 24 -2 18 -5z m824 -15 c-3 -8 -6 -5 -6 6 -1 11
2 17 5 13 3 -3 4 -12 1 -19z m423 15 c-8 -3 -19 -10 -25 -15 -22 -18 -119 -88
-123 -88 -2 0 11 16 30 36 35 38 93 73 118 73 13 -1 13 -1 0 -6z m-432 -82
c-4 -45 -43 -119 -56 -107 -2 3 0 11 6 18 10 13 12 18 12 39 0 5 5 7 12 3 6
-4 8 -3 4 4 -6 10 14 92 23 92 2 0 1 -22 -1 -49z m769 -3 c-3 -8 -6 -5 -6 6
-1 11 2 17 5 13 3 -3 4 -12 1 -19z m-978 -98 c-1 -41 2 -88 5 -105 6 -29 6
-29 -4 -5 -14 31 -22 219 -9 199 5 -8 8 -48 8 -89z m481 75 c0 -7 -57 -35 -72
-35 -7 0 5 9 27 19 48 23 45 22 45 16z m-863 -31 c-3 -3 -12 -4 -19 -1 -8 3
-5 6 6 6 11 1 17 -2 13 -5z m148 -3 c-3 -6 3 -15 12 -21 15 -9 14 -10 -7 -4
-14 4 -59 7 -100 6 -60 -1 -70 1 -50 10 14 5 49 7 77 5 29 -3 55 -1 58 4 4 5
8 9 11 9 3 0 3 -4 -1 -9z m187 -38 c-10 -28 -10 -28 -11 12 -1 28 2 36 10 28
8 -8 8 -19 1 -40z m365 11 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13
-5z m1426 -111 c-5 -12 -63 -36 -70 -29 -2 2 10 8 26 14 30 11 31 13 32 74 l2
63 7 -55 c4 -30 5 -60 3 -67z m-1809 71 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16
0 14 7 11 14 -7z m1132 -65 c5 0 9 -6 9 -13 0 -8 4 -18 8 -22 15 -16 6 -24
-29 -24 -35 0 -35 1 -29 33 9 42 16 52 25 37 4 -6 11 -11 16 -11z m222 -1 c8
-25 -17 -32 -47 -13 -5 3 -12 1 -16 -5 -10 -16 -25 -12 -25 8 0 15 8 18 43 17
23 0 43 -3 45 -7z m295 -35 c-38 -5 -70 -40 -79 -87 -3 -18 -16 -46 -29 -62
-23 -28 -25 -29 -122 -30 l-98 -2 93 7 c89 6 95 8 118 36 13 17 27 45 30 63
10 53 40 82 82 80 37 -1 37 -1 5 -5z m64 1 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6
6 11 1 17 -2 13 -5z m-1688 -46 c0 -31 -1 -31 -10 -10 -5 13 -7 28 -3 33 10
16 14 9 13 -23z m28 -75 c-2 -16 -4 -5 -4 22 0 28 2 40 4 28 2 -13 2 -35 0
-50z m-22 -120 c-10 -35 -21 -63 -26 -63 -4 0 -2 19 6 41 23 63 18 70 -9 14
-28 -57 -33 -48 -10 16 8 24 17 52 19 62 2 10 7 28 11 40 7 20 8 18 17 -13 6
-25 4 -51 -8 -97z m52 95 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z
m50 0 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m1166 -34 c-27
-20 -39 -17 -18 6 10 11 22 17 27 14 5 -3 1 -12 -9 -20z m-1237 -105 c-9 -34
-27 -75 -41 -91 -32 -38 -32 -24 0 22 14 21 31 65 38 101 6 35 13 56 15 47 2
-10 -4 -45 -12 -79z m907 84 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5 17 0 24 -2
18 -5z m285 1 c-3 -3 -41 -5 -83 -5 -42 0 -80 2 -83 5 -3 4 34 6 83 6 49 0 86
-2 83 -6z m-1138 -85 c-11 -38 -16 -44 -25 -30 -3 6 -1 11 4 11 6 0 11 8 11
18 0 16 8 32 16 32 1 0 -1 -14 -6 -31z m740 -19 c-8 -5 -19 -10 -25 -10 -5 0
-3 5 5 10 8 5 20 10 25 10 6 0 3 -5 -5 -10z m-850 -20 c0 -4 -6 -13 -14 -20
-12 -9 -15 -8 -13 8 1 17 27 28 27 12z m746 -45 c-24 -24 -53 -63 -65 -87 -12
-24 -18 -32 -15 -18 10 37 48 93 84 123 46 40 45 33 -4 -18z m-801 5 c-10 -11
-15 -20 -11 -20 3 0 -1 -14 -9 -31 -11 -21 -34 -39 -69 -55 -57 -26 -135 -44
-103 -24 9 6 27 13 38 15 42 8 165 95 134 95 -4 0 0 9 10 20 10 11 20 20 23
20 3 0 -3 -9 -13 -20z m11 -38 c-17 -16 -18 -16 -5 5 7 12 15 20 18 17 3 -2
-3 -12 -13 -22z m-46 14 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21
21 21 13z m975 -16 c3 -5 0 -7 -8 -4 -8 3 -17 -2 -21 -12 -5 -13 -9 -14 -21
-4 -8 6 -20 8 -27 4 -10 -5 -10 -4 -1 6 10 11 15 11 28 0 12 -10 15 -10 15 4
0 17 25 22 35 6z m-904 -27 c-5 -10 -31 -38 -58 -63 -89 -84 -98 -86 -18 -3
44 45 81 82 83 82 1 1 -2 -7 -7 -16z m108 -23 c0 -10 -3 -8 -9 5 -12 27 -12
43 0 25 5 -8 9 -22 9 -30z m833 33 c-6 -2 -10 -8 -7 -12 2 -5 -9 -21 -25 -36
-26 -25 -34 -27 -57 -19 -24 8 -31 5 -55 -21 l-28 -30 15 31 c16 32 77 71 83
53 3 -6 9 -5 18 2 11 9 14 9 14 -1 0 -10 3 -10 15 0 8 6 14 15 13 18 -2 16 3
22 15 21 9 0 9 -2 -1 -6z m-882 -60 c-11 -17 -11 -17 -6 0 3 10 7 26 7 35 1
15 2 15 6 0 2 -10 -1 -25 -7 -35z m-240 22 c-14 -8 -36 -14 -50 -14 -21 1 -19
2 8 9 18 4 36 10 39 14 4 3 11 6 17 6 6 -1 0 -7 -14 -15z m970 -5 c0 -5 -12
-10 -27 -9 -25 0 -26 1 -8 9 27 12 35 12 35 0z m-1083 -6 c-3 -3 -12 -4 -19
-1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m856 -11 c-7 -2 -21 -2 -30 0 -10 3 -4 5
12 5 17 0 24 -2 18 -5z m-411 -36 c-7 -27 -7 -27 -20 -6 -8 12 -9 18 -3 14 6
-3 14 1 17 10 10 25 14 12 6 -18z m-392 2 c19 -6 14 -7 -20 -4 -33 4 -39 2
-25 -4 19 -9 19 -10 -2 -10 -12 -1 -24 -5 -28 -11 -3 -5 -12 -7 -19 -4 -7 3
-16 -2 -19 -10 -7 -18 -31 -22 -25 -4 5 15 78 57 98 57 8 -1 26 -5 40 -10z
m893 4 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m92 -3 c3 -5 1
-10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-739 -49 c-15
-15 -31 -41 -36 -57 -7 -24 -8 -25 -9 -7 -1 20 52 93 67 93 3 0 -7 -13 -22
-29z m734 25 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10
-2 10 -4z m-1165 -26 c-27 -12 -43 -12 -25 0 8 5 22 9 30 9 10 0 8 -3 -5 -9z
m562 -32 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-297 4 c0 -4
-10 -13 -22 -21 -23 -14 -23 -14 -4 8 20 22 26 25 26 13z m1094 -3 c14 -7 27
-18 30 -26 8 -19 -11 -53 -30 -53 -19 0 -34 -40 -34 -91 0 -32 -3 -39 -20 -39
-11 0 -20 5 -20 12 0 6 -7 4 -18 -5 -25 -23 -37 -21 -56 8 -11 16 -16 46 -16
89 0 75 13 90 91 105 24 5 45 9 46 10 1 1 13 -4 27 -10z m-794 -58 c-4 -16
-13 -38 -20 -48 -11 -17 -11 -17 -5 2 3 11 9 32 12 48 3 15 9 27 14 27 4 0 4
-13 -1 -29z m-183 -23 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
m-27 -42 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16 21 21 21 13z m-47
-66 c-10 -17 -19 -26 -21 -20 -4 10 25 50 35 50 2 0 -4 -14 -14 -30z m1097 -3
c-1 -21 -1 -21 -15 -3 -8 10 -12 23 -9 28 9 14 24 -2 24 -25z m35 23 c-3 -5
-12 -10 -18 -10 -7 0 -6 4 3 10 19 12 23 12 15 0z m-1180 -40 c-3 -5 -12 -10
-18 -10 -7 0 -6 4 3 10 19 12 23 12 15 0z m960 -58 c-5 -5 -25 43 -25 61 1 7
7 -3 16 -22 8 -19 12 -36 9 -39z m-995 44 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2
-9 4 6 10 25 14 25 6z m1060 -5 c0 -5 -7 -12 -16 -15 -24 -9 -28 -7 -14 9 14
17 30 20 30 6z m-763 -73 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z
m-16 -41 c-10 -9 -11 -8 -5 6 3 10 9 15 12 12 3 -3 0 -11 -7 -18z m849 7 c0
-8 -6 -14 -12 -11 -7 2 -21 0 -30 -4 -16 -9 -68 7 -68 20 0 3 25 7 55 9 45 2
55 -1 55 -14z m-131 -120 c-19 -23 -21 -10 -7 37 l12 44 4 -33 c2 -18 -2 -40
-9 -48z m-359 46 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0
10 -4 10 -10z m450 -43 c0 -4 -11 0 -25 10 -13 10 -25 22 -25 26 0 4 11 0 25
-10 13 -10 25 -22 25 -26z m134 18 c-4 -8 -16 -15 -27 -15 -20 0 -20 0 -1 15
25 19 35 19 28 0z m-314 -10 c-7 -8 -16 -15 -20 -15 -15 0 -78 -70 -95 -106
-9 -19 -19 -33 -22 -30 -14 14 54 116 78 116 6 0 7 4 4 10 -3 5 9 16 27 24 43
19 43 19 28 1z m43 -9 c-4 -7 -23 -26 -41 -41 -17 -15 -30 -30 -27 -35 5 -9
-27 -53 -64 -88 -31 -28 -50 -14 -24 18 39 49 89 105 117 132 30 29 53 38 39
14z m120 -84 c20 -22 21 -24 4 -33 -23 -13 -23 -44 1 -34 9 4 31 13 48 19 18
6 40 18 50 26 16 13 17 13 11 0 -3 -8 -18 -44 -33 -80 -15 -36 -28 -81 -28
-102 -1 -20 -4 -34 -7 -33 -3 2 -10 -27 -17 -64 -18 -105 -25 -118 -72 -131
-47 -13 -70 -2 -70 33 0 19 -1 19 -12 4 -9 -11 -21 -15 -35 -11 -33 9 -28 27
14 55 l37 24 -1 102 c-2 79 2 114 18 160 29 82 36 89 68 61 l26 -23 -21 25
c-12 14 -25 41 -28 60 l-7 35 16 -35 c9 -19 26 -45 38 -58z m-513 26 c0 -10
-3 -10 -35 2 -14 5 -24 14 -21 19 7 10 56 -9 56 -21z m545 11 c10 -30 0 -33
-13 -4 -6 14 -7 25 -2 25 5 0 12 -9 15 -21z m-394 -26 c-6 -10 -13 -39 -16
-66 -4 -26 -10 -45 -15 -42 -6 3 -5 16 0 30 12 32 -5 43 -28 18 -9 -11 -13
-12 -7 -3 11 17 68 80 72 80 2 0 -1 -8 -6 -17z m49 2 c-7 -9 -15 -13 -17 -11
-7 7 7 26 19 26 6 0 6 -6 -2 -15z m395 -3 c-3 -3 -11 0 -18 7 -9 10 -8 11 6 5
10 -3 15 -9 12 -12z m-202 -34 c-3 -18 -10 -39 -16 -45 -5 -7 -6 -13 -2 -13 4
0 2 -7 -5 -15 -6 -8 -8 -20 -4 -27 4 -7 3 -9 -2 -5 -5 5 -15 -13 -24 -39 -14
-43 -40 -72 -40 -44 0 6 5 8 11 4 7 -4 10 -1 7 7 -3 8 -13 13 -22 13 -19 -2
-20 9 -2 59 12 33 12 39 0 44 -11 4 -12 9 -3 19 6 8 14 12 18 10 4 -3 25 11
46 29 22 19 41 34 42 35 1 0 0 -15 -4 -32z m-633 12 c0 -5 -4 -10 -10 -10 -5
0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m-224 -67 c-10 -10 -19 5
-10 18 6 11 8 11 12 0 2 -7 1 -15 -2 -18z m329 17 c3 -5 -1 -10 -10 -10 -9 0
-13 5 -10 10 3 6 8 10 10 10 2 0 7 -4 10 -10z m351 -65 c-8 -8 -18 -24 -21
-35 -4 -11 -10 -18 -15 -15 -4 3 -1 27 8 55 15 46 16 48 29 30 12 -17 12 -22
-1 -35z m-153 30 c-3 -9 -8 -14 -10 -11 -3 3 -2 9 2 15 9 16 15 13 8 -4z
m-1083 -20 c0 -8 -4 -15 -10 -15 -5 0 -10 7 -10 15 0 8 5 15 10 15 6 0 10 -7
10 -15z m400 -14 c0 -6 -4 -13 -10 -16 -5 -3 -10 1 -10 9 0 9 5 16 10 16 6 0
10 -4 10 -9z m661 -18 c-12 -20 -14 -14 -5 12 4 9 9 14 11 11 3 -2 0 -13 -6
-23z m-381 -14 c0 -6 -4 -7 -10 -4 -5 3 -10 11 -10 16 0 6 5 7 10 4 6 -3 10
-11 10 -16z m375 -39 c-4 -12 -9 -19 -12 -17 -3 3 -2 15 2 27 4 12 9 19 12 17
3 -3 2 -15 -2 -27z m-888 -16 c-9 -9 -28 6 -21 18 4 6 10 6 17 -1 6 -6 8 -13
4 -17z m1040 20 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-897
-84 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z
m1000 -10 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4
-10z m-17 -98 c-9 -15 -28 -33 -42 -40 -21 -10 -19 -5 14 28 21 22 40 40 42
40 1 0 -5 -13 -14 -28z m147 -81 c0 -5 -9 -7 -20 -4 -11 3 -20 7 -20 9 0 2 9
4 20 4 11 0 20 -4 20 -9z m-663 -7 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1
17 -2 13 -5z m-64 -31 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z
m41 -1 c3 -5 -1 -9 -9 -9 -8 0 -15 4 -15 9 0 4 4 8 9 8 6 0 12 -4 15 -8z m-94
-12 c-8 -5 -19 -10 -25 -10 -5 0 -3 5 5 10 8 5 20 10 25 10 6 0 3 -5 -5 -10z
m18 -52 c2 -12 -3 -18 -16 -18 -24 0 -36 -14 -67 -77 l-24 -48 6 38 c3 20 1
37 -4 37 -15 0 -32 -22 -27 -35 3 -7 1 -16 -5 -20 -7 -4 -11 4 -11 19 0 14 -5
28 -12 32 -6 4 -9 3 -6 -2 3 -5 -1 -22 -9 -39 -13 -30 -13 -30 -8 15 l6 45
-21 -35 c-16 -28 -19 -30 -14 -10 7 29 39 60 63 60 9 1 34 14 56 30 44 33 88
36 93 8z m1290 -45 c2 -7 -1 -13 -8 -13 -6 0 -8 6 -5 13 4 6 -1 3 -10 -8 -10
-11 -23 -35 -31 -52 -8 -18 -19 -33 -24 -33 -14 0 -12 27 3 33 7 3 4 6 -6 6
-19 1 -56 -35 -57 -55 0 -5 -6 -19 -14 -30 -13 -17 -14 -15 -11 24 1 24 9 49
16 55 9 8 8 6 -1 -8 -8 -11 10 4 40 33 40 39 61 52 79 50 14 -2 26 -9 29 -15z
m-26 -105 c-7 -7 -12 -22 -12 -34 0 -13 -5 -26 -12 -30 -8 -5 -9 2 -5 26 7 35
26 64 35 55 3 -3 0 -11 -6 -17z m-154 -14 c-7 -15 -14 -21 -16 -15 -2 7 2 18
8 26 18 22 21 18 8 -11z m88 -25 c-9 -13 -16 -31 -16 -41 0 -10 -5 -18 -10
-18 -10 0 -6 32 12 79 6 17 12 21 20 13 7 -7 6 -17 -6 -33z m-1336 27 c0 -3
-4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m1225 -56
c-3 -5 -11 -10 -16 -10 -6 0 -7 5 -4 10 3 6 11 10 16 10 6 0 7 -4 4 -10z
m-2236 -544 c-2 -2 -15 -9 -29 -15 -24 -11 -24 -11 -6 3 16 13 49 24 35 12z
m-419 -61 c25 -13 41 -24 35 -24 -5 0 -30 11 -55 24 -25 13 -40 24 -35 24 6 0
30 -11 55 -24z m547 -11 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z
m-220 -140 c543 -254 653 -307 650 -310 -2 -2 -122 52 -268 120 -647 303 -674
316 -656 316 3 0 126 -57 274 -126z m368 48 c-3 -3 -11 0 -18 7 -9 10 -8 11 6
5 10 -3 15 -9 12 -12z m205 -52 c-8 -5 -19 -10 -25 -10 -5 0 -3 5 5 10 8 5 20
10 25 10 6 0 3 -5 -5 -10z m395 -200 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0
6 2 10 4 10 3 0 8 -4 11 -10z"/>
<path d="M397 6159 c-52 -12 -134 -55 -185 -96 -124 -101 -180 -283 -136 -448
54 -210 277 -354 490 -318 298 51 461 375 321 636 -93 175 -300 271 -490 226z
m225 -29 c219 -67 345 -301 280 -517 -82 -270 -395 -386 -630 -234 -73 48
-117 99 -156 181 -29 60 -31 73 -31 170 0 97 2 110 32 172 55 116 166 210 279
237 67 16 158 12 226 -9z"/>
<path d="M405 6126 c-249 -62 -383 -334 -276 -562 122 -260 456 -320 657 -120
225 226 120 599 -191 681 -69 18 -121 18 -190 1z m193 -20 c74 -20 131 -56
190 -121 70 -77 96 -146 96 -255 -1 -112 -27 -180 -99 -258 -191 -207 -512
-158 -637 96 -30 61 -33 74 -33 162 0 86 3 101 31 160 83 175 270 264 452 216z"/>
<path d="M420 6087 c-115 -27 -202 -98 -254 -207 -27 -57 -31 -76 -31 -150 0
-76 3 -92 33 -152 65 -132 185 -209 327 -209 211 0 368 153 368 361 0 108 -29
178 -107 256 -92 92 -214 129 -336 101z m220 -43 c228 -103 274 -402 87 -569
-71 -64 -141 -88 -247 -83 -101 5 -161 32 -227 100 -85 87 -117 206 -89 319
55 213 278 322 476 233z"/>
<path d="M275 5738 c-27 -40 -51 -76 -53 -80 -2 -4 18 -8 45 -8 50 0 49 -1
105 85 3 6 -6 25 -20 43 l-27 32 -50 -72z"/>
<path d="M640 5775 l-23 -36 31 -42 c28 -39 34 -42 82 -45 l52 -3 -48 68 c-71
103 -68 100 -94 58z"/>
<path d="M360 5545 c0 -25 5 -45 10 -45 6 0 10 9 10 20 0 26 46 28 53 3 3 -10
5 2 5 27 0 25 -2 37 -5 28 -6 -22 -53 -25 -53 -3 0 8 -4 15 -10 15 -5 0 -10
-20 -10 -45z"/>
<path d="M470 5547 c0 -42 1 -43 35 -45 19 -2 35 2 35 8 0 5 -11 10 -25 10
-14 0 -25 5 -25 10 0 6 9 10 20 10 11 0 20 5 20 10 0 6 -9 10 -20 10 -30 0
-24 18 8 23 22 3 20 4 -10 6 l-38 1 0 -43z"/>
<path d="M583 5583 l27 -4 -25 -33 c-14 -18 -25 -36 -25 -40 0 -4 18 -6 40 -4
44 2 56 18 14 18 l-26 0 26 35 27 35 -43 -1 c-30 -2 -35 -3 -15 -6z"/>
<path d="M2290 5630 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1536 5403 c-11 -11 -6 -23 9 -23 8 0 15 4 15 9 0 13 -16 22 -24 14z"/>
<path d="M1570 5350 c0 -33 -4 -60 -10 -60 -5 0 -10 -7 -10 -15 0 -8 5 -15 11
-15 5 0 7 5 4 10 -4 6 6 10 22 11 15 0 22 3 16 6 -14 5 -18 53 -5 53 5 0 21
-13 37 -30 26 -27 34 -30 89 -29 34 1 51 4 39 6 -21 4 -23 10 -23 64 0 76 -18
77 -22 2 -3 -49 -6 -58 -23 -61 -28 -4 -72 53 -49 62 19 7 15 50 -6 53 -21 4
-43 -12 -38 -27 3 -9 9 -8 21 4 16 16 17 16 17 -2 0 -18 -18 -32 -41 -32 -5 0
-9 14 -9 30 0 17 -4 30 -10 30 -6 0 -10 -27 -10 -60z"/>
<path d="M1880 5351 c0 -38 -4 -61 -12 -64 -7 -3 3 -5 22 -5 19 0 29 2 23 5
-9 3 -13 26 -13 64 0 33 -4 59 -10 59 -6 0 -10 -26 -10 -59z"/>
<path d="M1944 5401 c-14 -14 2 -40 37 -60 43 -25 46 -42 8 -52 -21 -6 -21 -7
-3 -8 29 -1 59 23 51 42 -3 9 -23 25 -44 36 -37 20 -37 20 -10 21 15 0 27 6
27 13 0 8 4 7 10 -3 8 -13 10 -13 10 2 0 12 -9 16 -41 15 -22 -1 -42 -4 -45
-6z"/>
<path d="M2112 5348 c3 -54 6 -63 23 -65 11 -2 14 0 8 3 -8 4 -13 27 -13 65 0
34 -4 59 -10 59 -7 0 -10 -24 -8 -62z"/>
<path d="M2153 5403 c-17 -6 -16 -23 1 -23 8 0 16 7 20 15 6 15 1 17 -21 8z"/>
<path d="M2770 5320 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
-4 -4 -4 -10z"/>
<path d="M1940 5299 c0 -11 4 -18 10 -14 5 3 7 12 3 20 -7 21 -13 19 -13 -6z"/>
<path d="M2632 5289 c2 -6 8 -10 13 -10 5 0 11 4 13 10 2 6 -4 11 -13 11 -9 0
-15 -5 -13 -11z"/>
<path d="M1331 5254 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M1830 5251 c0 -7 -4 -9 -10 -6 -5 3 -10 1 -10 -4 0 -6 4 -11 9 -11
13 0 25 20 17 27 -3 4 -6 1 -6 -6z"/>
<path d="M2515 5253 c-11 -3 -24 -9 -29 -14 -5 -4 8 -4 29 2 27 8 41 7 49 -1
8 -8 7 -13 -4 -20 -9 -6 -10 -10 -3 -10 19 0 26 20 13 35 -13 15 -20 16 -55 8z"/>
<path d="M2616 5252 c-3 -6 -1 -14 5 -17 14 -9 20 -2 10 14 -6 8 -11 9 -15 3z"/>
<path d="M1775 5240 c-3 -5 1 -10 9 -10 9 0 16 5 16 10 0 6 -4 10 -9 10 -6 0
-13 -4 -16 -10z"/>
<path d="M2710 5240 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1408 5233 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
<path d="M1772 5208 c6 -18 28 -21 28 -4 0 9 -7 16 -16 16 -9 0 -14 -5 -12
-12z"/>
<path d="M2042 5204 c-8 -8 -22 -12 -32 -9 -10 3 -22 0 -26 -6 -4 -8 -3 -9 5
-5 6 4 19 2 27 -5 12 -10 17 -8 29 7 23 30 20 45 -3 18z"/>
<path d="M2443 5203 c4 -3 1 -13 -6 -22 -11 -14 -10 -14 6 -2 20 15 22 31 5
31 -6 0 -8 -3 -5 -7z"/>
<path d="M2531 5194 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M1540 5190 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M2326 5181 c-3 -4 6 -6 19 -3 14 2 25 6 25 8 0 8 -39 4 -44 -5z"/>
<path d="M2474 5159 c-12 -25 -13 -34 -3 -43 9 -8 10 -8 5 1 -9 16 13 61 33
66 14 4 14 5 -1 6 -10 1 -24 -12 -34 -30z"/>
<path d="M1948 5173 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M2889 5159 c0 -22 -1 -23 -9 -4 -8 18 -9 18 -9 2 -1 -10 -5 -16 -10
-13 -5 3 -11 -8 -13 -24 -4 -28 -2 -30 28 -30 32 0 32 0 27 43 -7 49 -13 61
-14 26z m-5 -44 c-4 -8 -10 -12 -15 -9 -14 8 -10 24 6 24 9 0 12 -6 9 -15z"/>
<path d="M1728 5163 c12 -2 30 -2 40 0 9 3 -1 5 -23 4 -22 0 -30 -2 -17 -4z"/>
<path d="M2101 5154 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M2150 5156 c0 -7 7 -13 15 -13 8 0 15 4 15 8 0 4 -7 9 -15 13 -9 3
-15 0 -15 -8z"/>
<path d="M2275 5160 c-3 -6 3 -22 14 -36 12 -15 21 -22 21 -16 0 6 -7 18 -17
27 -14 14 -14 18 -2 26 9 5 10 9 2 9 -6 0 -15 -5 -18 -10z"/>
<path d="M1270 5135 c0 -14 4 -25 9 -25 4 0 6 11 3 25 -2 14 -6 25 -8 25 -2 0
-4 -11 -4 -25z"/>
<path d="M1525 5150 c-4 -6 -15 -8 -26 -5 -13 4 -19 2 -19 -9 0 -9 6 -16 13
-15 18 1 54 17 42 19 -5 2 4 6 20 10 l30 8 -27 1 c-15 0 -30 -4 -33 -9z"/>
<path d="M1960 5145 c0 -8 2 -15 4 -15 2 0 6 7 10 15 3 8 1 15 -4 15 -6 0 -10
-7 -10 -15z"/>
<path d="M2070 5144 c0 -8 5 -12 10 -9 6 4 8 11 5 16 -9 14 -15 11 -15 -7z"/>
<path d="M2210 5150 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M2010 5140 c0 -5 7 -10 15 -10 8 0 15 5 15 10 0 6 -7 10 -15 10 -8 0
-15 -4 -15 -10z"/>
<path d="M2500 5134 c0 -17 22 -14 28 4 2 7 -3 12 -12 12 -9 0 -16 -7 -16 -16z"/>
<path d="M2543 5137 c0 -7 9 -14 19 -14 11 -1 18 5 17 15 0 11 -2 13 -6 4 -3
-9 -9 -10 -17 -3 -9 8 -13 7 -13 -2z"/>
<path d="M2616 5141 c-4 -7 -5 -15 -2 -18 9 -9 19 4 14 18 -4 11 -6 11 -12 0z"/>
<path d="M2400 5131 c0 -6 -6 -11 -14 -11 -32 0 -23 -17 9 -18 39 -2 42 2 20
24 -8 9 -15 11 -15 5z"/>
<path d="M2685 5130 c-3 -5 1 -10 9 -10 9 0 16 5 16 10 0 6 -4 10 -9 10 -6 0
-13 -4 -16 -10z"/>
<path d="M2166 5117 c3 -10 9 -15 12 -12 3 3 0 11 -7 18 -10 9 -11 8 -5 -6z"/>
<path d="M2320 5115 c0 -8 7 -15 15 -15 8 0 15 4 15 9 0 5 -7 11 -15 15 -9 3
-15 0 -15 -9z"/>
<path d="M1201 5112 c-1 -7 -5 -11 -10 -8 -5 3 -11 -10 -13 -29 -4 -32 -2 -35
23 -35 15 0 31 5 34 11 9 14 -3 61 -14 54 -5 -3 -12 1 -14 7 -4 10 -6 10 -6 0z"/>
<path d="M2260 5105 c-10 -13 -9 -15 9 -15 12 0 21 6 21 15 0 8 -4 15 -9 15
-5 0 -14 -7 -21 -15z"/>
<path d="M1462 5090 c0 -14 2 -19 5 -12 2 6 2 18 0 25 -3 6 -5 1 -5 -13z"/>
<path d="M1581 5094 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M1658 5103 c-24 -6 -23 -23 2 -23 11 0 20 7 20 15 0 8 -1 14 -2 14
-2 -1 -11 -3 -20 -6z"/>
<path d="M2002 5099 c2 -6 8 -10 13 -10 5 0 11 4 13 10 2 6 -4 11 -13 11 -9 0
-15 -5 -13 -11z"/>
<path d="M1337 5089 c7 -7 15 -10 18 -7 3 3 -2 9 -12 12 -14 6 -15 5 -6 -5z"/>
<path d="M1710 5090 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M2472 5065 c-27 -42 -37 -43 -69 -9 -18 19 -27 23 -37 15 -7 -6 -17
-7 -22 -2 -12 12 -114 20 -114 10 0 -5 24 -9 54 -9 30 0 58 -5 61 -10 5 -8 11
-8 20 0 9 8 17 6 29 -5 9 -9 16 -21 16 -26 0 -5 9 -9 19 -9 19 0 71 52 71 71
0 14 -4 11 -28 -26z"/>
<path d="M1545 5080 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
-8 -4 -11 -10z"/>
<path d="M2536 5082 c-3 -6 -1 -14 5 -17 14 -9 20 -2 10 14 -6 8 -11 9 -15 3z"/>
<path d="M1378 5073 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M2585 5071 c-3 -5 -2 -12 3 -15 5 -3 9 1 9 9 0 17 -3 19 -12 6z"/>
<path d="M2625 5070 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
-7 -4 -4 -10z"/>
<path d="M2826 5065 c-3 -8 -1 -15 4 -15 6 0 10 7 10 15 0 8 -2 15 -4 15 -2 0
-6 -7 -10 -15z"/>
<path d="M2928 5073 c-24 -6 -23 -23 2 -23 11 0 20 7 20 15 0 8 -1 14 -2 14
-2 -1 -11 -3 -20 -6z"/>
<path d="M2004 5048 c4 -18 28 -16 34 2 4 13 3 13 -10 2 -11 -9 -18 -9 -21 -2
-3 6 -4 5 -3 -2z"/>
<path d="M1608 5043 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M1670 5045 c0 -4 11 -20 25 -37 14 -16 25 -26 25 -23 0 4 -11 20 -25
37 -14 16 -25 26 -25 23z"/>
<path d="M1970 5040 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
-4 -4 -4 -10z"/>
<path d="M2172 5038 c6 -18 28 -21 28 -4 0 9 -7 16 -16 16 -9 0 -14 -5 -12
-12z"/>
<path d="M1140 5021 c0 -5 7 -11 15 -15 8 -3 15 -1 15 3 0 5 -7 11 -15 15 -8
3 -15 1 -15 -3z"/>
<path d="M2091 5004 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M2117 5004 c3 -7 9 -14 14 -14 14 0 10 17 -5 23 -10 4 -13 1 -9 -9z"/>
<path d="M2251 5008 c-1 -20 14 -24 25 -6 4 6 3 8 -4 4 -5 -3 -13 0 -15 6 -3
8 -6 6 -6 -4z"/>
<path d="M1801 4994 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M2150 5006 c0 -9 30 -14 35 -6 4 6 -3 10 -14 10 -12 0 -21 -2 -21 -4z"/>
<path d="M2200 5006 c0 -2 9 -6 20 -9 11 -3 20 -1 20 4 0 5 -9 9 -20 9 -11 0
-20 -2 -20 -4z"/>
<path d="M1023 4993 c-7 -3 -13 -9 -13 -14 0 -6 4 -8 9 -4 5 3 12 -3 14 -12 4
-17 5 -17 6 -1 1 12 6 15 19 11 18 -6 17 -4 -8 13 -8 6 -21 9 -27 7z"/>
<path d="M1880 4990 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1920 4990 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1955 4990 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
-8 -4 -11 -10z"/>
<path d="M2466 4983 c-11 -11 -6 -23 9 -23 8 0 15 4 15 9 0 13 -16 22 -24 14z"/>
<path d="M2810 4958 c0 -14 -3 -33 -6 -42 -5 -13 1 -16 33 -16 l38 0 -3 43
c-3 40 -6 43 -33 42 -25 0 -29 -4 -29 -27z m40 -27 c0 -6 -4 -13 -10 -16 -5
-3 -10 1 -10 9 0 9 5 16 10 16 6 0 10 -4 10 -9z"/>
<path d="M2608 4945 c-4 -34 -3 -35 30 -35 27 0 33 3 28 16 -3 9 -6 24 -6 35
0 13 -7 19 -24 19 -20 0 -25 -6 -28 -35z"/>
<path d="M1431 4953 c0 -11 3 -13 6 -5 2 6 10 9 15 6 7 -4 8 -2 4 4 -11 18
-26 14 -25 -5z"/>
<path d="M1490 4955 c-10 -12 -10 -15 2 -15 8 0 15 7 15 15 0 8 -1 15 -2 15
-2 0 -8 -7 -15 -15z"/>
<path d="M1877 4954 c-8 -8 1 -24 14 -24 5 0 9 7 9 15 0 15 -12 20 -23 9z"/>
<path d="M1000 4934 c0 -7 17 -11 44 -10 63 2 67 13 7 17 -33 3 -51 0 -51 -7z"/>
<path d="M3006 4935 c4 -8 8 -15 10 -15 2 0 4 7 4 15 0 8 -4 15 -10 15 -5 0
-7 -7 -4 -15z"/>
<path d="M2113 4925 c0 -10 4 -12 13 -4 8 7 13 6 17 -3 2 -7 8 -9 13 -5 5 4 2
12 -6 17 -22 14 -37 12 -37 -5z"/>
<path d="M2455 4930 c3 -5 12 -7 20 -3 21 7 19 13 -6 13 -11 0 -18 -4 -14 -10z"/>
<path d="M2545 4930 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
-7 -4 -4 -10z"/>
<path d="M1330 4915 c0 -6 7 -12 15 -12 8 0 15 6 15 12 0 6 -7 12 -15 12 -8 0
-15 -6 -15 -12z"/>
<path d="M2175 4920 c4 -6 11 -8 16 -5 14 9 11 15 -7 15 -8 0 -12 -5 -9 -10z"/>
<path d="M2210 4919 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M1330 4670 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1990 4600 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M2765 4211 c18 -7 18 -9 3 -12 -13 -3 -15 -8 -8 -19 10 -17 15 -14
24 18 6 18 4 22 -16 21 -22 0 -22 -1 -3 -8z"/>
<path d="M1930 4082 c6 -13 14 -21 18 -18 3 4 -2 14 -12 24 -18 16 -18 16 -6
-6z"/>
<path d="M3067 3783 c-10 -9 -9 -33 1 -33 4 0 8 9 8 20 0 23 0 22 -9 13z"/>
<path d="M1972 3590 c0 -14 2 -19 5 -12 2 6 2 18 0 25 -3 6 -5 1 -5 -13z"/>
<path d="M2785 3290 c-2 -3 5 -6 15 -7 11 -1 22 2 25 7 3 5 -4 8 -16 7 -11 -1
-22 -4 -24 -7z"/>
<path d="M2717 3084 c-4 -4 -7 -18 -7 -31 0 -20 4 -23 28 -17 21 4 24 3 12 -5
-12 -9 -10 -11 10 -11 36 0 52 14 48 41 -2 20 -9 24 -43 27 -23 2 -44 0 -48
-4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

+182
View File
@@ -0,0 +1,182 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="296.000000pt" height="222.000000pt" viewBox="0 0 296.000000 222.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,222.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1639 2085 c-32 -17 -50 -34 -57 -54 -6 -17 -35 -56 -66 -86 -53 -54
-55 -55 -111 -55 -46 0 -63 -5 -87 -25 l-30 -25 -222 4 c-121 3 -249 8 -283
11 -35 4 -86 2 -117 -5 -81 -17 -96 -42 -96 -158 0 -69 -4 -92 -16 -103 -9 -7
-23 -27 -32 -44 -19 -36 -62 -97 -109 -156 -18 -22 -49 -74 -69 -116 -30 -61
-47 -83 -93 -117 -95 -70 -131 -114 -131 -158 0 -31 4 -38 19 -38 31 0 33 -46
4 -81 -31 -36 -23 -49 31 -49 44 0 70 18 95 68 14 27 40 28 88 2 45 -24 121
-26 149 -5 21 16 109 20 119 6 3 -5 18 -12 33 -16 32 -7 81 15 131 57 25 23
39 28 60 23 16 -3 49 1 76 10 l48 17 24 -29 c13 -15 31 -42 38 -60 8 -18 25
-37 37 -44 11 -6 50 -39 85 -73 l64 -61 102 -7 c56 -4 123 -10 149 -13 45 -7
50 -5 80 27 18 19 41 47 51 61 25 37 74 37 108 0 34 -38 53 -97 40 -122 -20
-36 -12 -71 25 -116 35 -43 35 -43 89 -38 69 7 109 -14 99 -52 -11 -43 13 -80
69 -110 62 -33 107 -73 107 -94 0 -35 58 -163 91 -201 19 -23 27 -25 102 -23
45 1 83 6 85 11 1 5 43 7 96 4 90 -4 95 -4 119 21 14 13 30 43 36 64 16 59 41
77 104 74 30 -1 65 3 80 8 25 10 27 15 27 65 0 30 -5 58 -10 61 -6 4 -17 23
-25 42 -14 33 -14 38 2 62 32 47 43 73 43 100 0 49 -26 100 -80 158 -30 32
-62 70 -71 84 -14 22 -26 27 -74 31 -50 4 -61 9 -96 46 -22 22 -61 55 -87 71
-26 17 -51 35 -56 40 -4 5 -17 19 -28 31 -12 13 -29 20 -46 19 -65 -5 -84 11
-37 33 34 15 32 28 -2 19 -18 -5 -29 -15 -31 -29 -7 -44 -62 -8 -62 40 0 36
-28 111 -45 120 -19 11 -16 65 4 73 13 5 12 9 -9 25 l-25 20 25 1 c14 1 30 2
36 2 16 0 18 180 3 209 -7 13 -36 52 -66 88 -30 36 -56 76 -59 90 -9 43 -19
54 -68 79 -31 15 -57 38 -73 65 -14 23 -36 54 -49 69 -13 15 -29 47 -35 70
-16 55 -26 66 -74 88 -53 25 -91 23 -146 -6z m-27 -179 c3 2 8 -7 10 -21 3
-14 1 -28 -3 -31 -5 -3 -9 2 -9 10 0 9 -4 16 -10 16 -5 0 -10 -7 -10 -15 0 -8
-5 -15 -11 -15 -7 0 -9 9 -5 23 3 12 6 28 6 36 0 10 3 11 13 2 8 -6 16 -8 19
-5z m275 -102 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m40 -76
c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m43 14 c0 -13 -12 -22
-22 -16 -10 6 -1 24 13 24 5 0 9 -4 9 -8z m-965 -83 c5 -14 2 -25 -6 -30 -19
-12 -29 -11 -29 1 0 6 7 10 16 10 9 0 14 5 12 11 -2 6 -6 9 -9 7 -3 -2 -13 3
-22 10 -13 11 -16 6 -19 -48 -2 -43 1 -60 10 -60 6 0 12 11 12 25 0 14 4 25
10 25 5 0 17 -11 26 -25 9 -14 25 -25 36 -25 16 0 15 4 -12 26 -29 25 -29 27
-13 40 16 11 16 15 4 36 -13 22 -13 23 6 6 24 -22 47 -23 39 -3 -3 8 -1 15 5
15 7 0 10 -22 7 -60 l-3 -60 35 0 c47 0 80 24 80 59 0 15 -5 32 -12 39 -9 9
-5 9 16 0 24 -12 27 -17 24 -55 -2 -33 0 -43 12 -43 12 0 14 10 12 45 -3 31 0
45 8 45 7 0 19 8 26 18 12 16 13 16 19 0 8 -20 40 -24 51 -6 4 6 3 8 -2 5 -6
-3 -16 -2 -23 2 -9 6 -5 10 13 13 23 5 26 2 27 -21 0 -25 0 -26 9 -3 9 22 44
30 54 13 4 -5 -2 -7 -13 -4 -11 3 -21 -2 -25 -12 -5 -14 -2 -16 20 -12 25 4
26 3 22 -39 -3 -39 -1 -44 17 -43 11 0 14 3 8 6 -15 6 -18 99 -3 108 6 3 7 -1
4 -9 -9 -22 22 -21 35 2 9 15 10 14 11 -6 0 -21 4 -23 35 -19 19 3 35 3 35 2
0 -2 3 -10 6 -19 4 -11 0 -16 -15 -16 -15 0 -19 5 -15 18 3 9 -2 4 -11 -13
-10 -16 -24 -36 -33 -42 -14 -12 -13 -13 6 -13 12 0 21 3 21 8 -4 26 3 33 34
30 23 -2 32 -8 31 -20 -1 -12 5 -18 17 -18 19 0 19 1 -2 43 -12 23 -18 39 -14
35 3 -3 20 -2 37 2 l30 9 -4 -44 c-2 -26 1 -45 7 -45 6 0 9 20 7 48 l-4 47 46
-45 46 -44 0 37 0 37 140 0 c99 0 139 -3 137 -11 -1 -6 4 -14 12 -17 10 -3 12
0 8 12 -6 14 -1 17 25 14 25 -2 42 -15 75 -56 42 -51 43 -55 43 -125 0 -90 -7
-117 -31 -117 -27 0 -32 -17 -9 -33 18 -12 18 -15 5 -20 -9 -4 -15 -19 -15
-42 l0 -35 -52 -1 c-29 -1 -57 -1 -62 0 -6 1 -89 2 -185 1 -127 0 -177 -4
-183 -13 -6 -9 -8 -9 -8 1 0 9 -46 12 -195 12 -123 0 -195 4 -195 10 0 6 -7
10 -15 10 -8 0 -15 -4 -15 -10 0 -6 -30 -10 -70 -10 -40 0 -70 4 -70 10 0 6
-7 10 -15 10 -8 0 -15 -4 -15 -10 0 -6 -132 -10 -365 -10 -201 0 -365 3 -365
5 0 16 67 135 91 163 16 18 29 37 29 41 0 5 18 31 40 57 22 27 40 54 40 60 0
6 11 23 25 38 14 15 25 35 25 45 0 14 9 20 36 23 l36 4 -4 -43 c-2 -34 0 -43
13 -43 12 0 15 7 11 25 -2 14 0 25 6 25 6 0 19 -11 30 -25 11 -14 30 -25 43
-25 20 0 17 4 -19 31 -51 37 -44 61 14 52 28 -5 34 -2 34 12 0 13 -6 16 -23
11 -16 -4 -24 -1 -24 7 0 9 10 12 29 9 26 -4 28 -7 28 -51 0 -26 5 -52 12 -59
18 -18 64 -15 79 6 13 15 12 16 -3 4 -9 -8 -27 -12 -40 -10 -20 3 -23 9 -26
56 -2 28 1 52 7 52 5 0 7 -9 4 -20 -5 -18 -1 -20 51 -17 37 1 56 6 56 15 0 6
-7 12 -15 12 -8 0 -15 5 -15 11 0 5 3 8 8 6 4 -3 16 -1 27 3 26 10 52 -4 60
-31z m-105 11 c0 -5 -7 -7 -15 -4 -8 4 -12 10 -9 15 6 11 24 2 24 -11z m764 7
c-3 -8 -11 -14 -19 -14 -21 0 -19 15 3 20 9 3 18 5 19 6 1 0 0 -5 -3 -12z
m-934 -5 c0 -5 -11 -19 -25 -32 l-25 -23 0 31 c0 27 4 32 25 32 14 0 25 -4 25
-8z m424 -2 c-9 -8 -54 -7 -54 2 0 5 13 7 30 6 16 -1 27 -5 24 -8z m106 6 c0
-3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m-92
-55 c5 -29 -15 -51 -44 -51 -21 0 -24 5 -24 38 0 35 1 37 32 36 26 -1 34 -6
36 -23z m582 2 c0 -13 -1 -23 -3 -23 -2 0 -13 10 -25 23 l-21 22 25 0 c18 0
24 -5 24 -22z m351 -444 l24 -20 -30 17 c-39 24 -40 24 -28 24 6 0 21 -9 34
-21z m-1366 -29 c3 -5 -8 -16 -24 -25 -36 -18 -41 -19 -41 -2 0 29 50 51 65
27z m139 -15 c-4 -8 -8 -15 -10 -15 -2 0 -4 7 -4 15 0 8 4 15 10 15 5 0 7 -7
4 -15z m26 -15 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11
-4 11 -10z m1295 -20 c3 -5 -1 -10 -9 -10 -8 0 -18 5 -21 10 -3 6 1 10 9 10 8
0 18 -4 21 -10z m-52 -15 c-3 -9 -8 -14 -10 -11 -3 3 -2 9 2 15 9 16 15 13 8
-4z m-283 -12 c0 -5 -5 -15 -10 -23 -8 -12 -10 -11 -10 8 0 12 5 22 10 22 6 0
10 -3 10 -7z m-1090 -45 c0 -36 -2 -38 -33 -38 -32 0 -32 1 -29 38 3 33 6 37
33 37 27 0 29 -3 29 -37z m852 -31 c9 -4 10 -6 1 -6 -12 -1 -63 59 -63 75 0 5
11 -8 25 -28 13 -20 30 -38 37 -41z m280 66 c-12 -2 -20 -9 -17 -14 4 -5 -1
-9 -9 -9 -9 0 -16 4 -16 9 0 12 19 20 45 19 17 -1 16 -1 -3 -5z m178 -48 c-7
-8 -17 -15 -23 -15 -6 0 -2 7 9 15 25 19 30 19 14 0z m-718 -47 c3 -37 3 -38
-30 -38 -33 0 -33 1 -27 33 8 34 17 44 40 44 8 0 15 -15 17 -39z m679 -5 c13
-17 13 -17 -6 -3 -11 8 -22 16 -24 17 -2 2 0 3 6 3 6 0 17 -8 24 -17z m-62
-36 c-2 -1 -14 -10 -26 -20 -16 -14 -23 -15 -29 -6 -4 7 -3 10 3 6 6 -4 16 0
23 8 7 8 17 15 23 15 6 0 8 -1 6 -3z m110 -19 c11 -15 11 -18 -1 -18 -7 0 -14
10 -15 21 -1 12 -1 20 0 18 2 -2 9 -12 16 -21z m-621 -96 c-5 -2 -16 -1 -25 2
-14 6 -14 8 3 21 17 12 20 11 25 -3 4 -9 2 -19 -3 -20z m711 -6 c-1 -20 -2
-20 -6 -1 -3 11 -10 27 -17 35 -10 13 -9 13 7 1 9 -7 16 -23 16 -35z m594
-120 c4 -10 1 -13 -8 -9 -8 3 -12 9 -9 14 7 12 11 11 17 -5z m-583 -26 c9 -16
8 -18 -5 -14 -8 4 -15 12 -15 20 0 20 7 17 20 -6z m-282 -30 c-12 -16 -25 -30
-28 -30 -4 0 -5 14 -2 30 3 24 9 30 28 30 l25 0 -23 -30z m18 -27 c-11 -11
-19 6 -11 24 8 17 8 17 12 0 3 -10 2 -21 -1 -24z m71 -20 c-3 -10 -5 -4 -5 12
0 17 2 24 5 18 2 -7 2 -21 0 -30z m40 -5 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2
-7 2 -19 0 -25z m96 -225 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5 17 0 24 -2 18
-5z m313 -112 c27 10 48 4 39 -11 -3 -4 -21 -8 -40 -7 -29 1 -35 5 -34 21 1
17 2 17 6 4 3 -14 9 -15 29 -7z m-151 -1 c-3 -5 -1 -19 5 -30 7 -13 7 -20 0
-20 -5 0 -10 7 -10 15 0 8 -4 15 -10 15 -5 0 -10 -7 -10 -15 0 -8 -4 -15 -10
-15 -5 0 -10 6 -10 14 0 28 12 46 32 46 10 0 16 -4 13 -10z"/>
<path d="M1280 1653 c0 -14 12 -28 36 -42 40 -24 36 -45 -7 -39 -18 3 -26 1
-21 -4 5 -5 22 -8 38 -6 42 5 45 42 5 62 -16 9 -35 24 -40 33 -9 16 -10 16
-11 -4z"/>
<path d="M1892 1571 c4 -13 18 -16 19 -4 0 4 -5 9 -11 12 -7 2 -11 -2 -8 -8z"/>
<path d="M1800 1536 c0 -2 9 -6 20 -9 11 -3 18 -1 14 4 -5 9 -34 13 -34 5z"/>
<path d="M1742 1523 c-17 -3 -22 -10 -20 -26 2 -17 -4 -23 -27 -28 -27 -6 -28
-7 -5 -8 32 -1 54 13 48 30 -3 9 7 19 26 26 31 11 21 14 -22 6z"/>
<path d="M1130 1490 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1790 1484 c-30 -16 -50 -42 -50 -63 1 -9 7 -1 15 17 9 20 21 32 33
32 11 0 22 7 26 15 3 8 4 15 3 14 -1 -1 -13 -7 -27 -15z"/>
<path d="M1340 1470 c0 -5 7 -10 15 -10 8 0 15 5 15 10 0 6 -7 10 -15 10 -8 0
-15 -4 -15 -10z"/>
<path d="M1596 1464 c-20 -12 -25 -19 -17 -27 8 -8 2 -18 -22 -38 l-32 -28 52
-1 c28 0 55 -5 59 -11 4 -8 9 -8 17 0 8 8 19 3 40 -17 l29 -27 24 30 c13 17
24 37 24 45 0 9 -6 5 -13 -9 -6 -13 -20 -29 -29 -35 -14 -9 -21 -6 -34 12 -9
13 -23 22 -32 21 -34 -3 -116 4 -94 8 12 2 22 8 22 12 0 4 27 5 60 3 43 -3 60
-1 60 8 0 8 -10 11 -30 8 -16 -3 -30 0 -30 5 0 5 -7 4 -15 -3 -11 -9 -15 -9
-15 -1 0 7 -4 10 -9 7 -5 -3 -14 1 -21 9 -7 8 -11 15 -9 15 17 1 79 29 64 29
-11 0 -33 -7 -49 -15z"/>
<path d="M1450 1450 c-13 -8 -12 -10 3 -10 9 0 17 5 17 10 0 12 -1 12 -20 0z"/>
<path d="M2120 1450 c0 -5 -3 -9 -7 -9 -24 4 -33 -4 -33 -26 0 -20 5 -25 25
-25 22 0 25 4 25 35 0 19 -2 35 -5 35 -3 0 -5 -4 -5 -10z m0 -34 c0 -3 -4 -8
-10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z"/>
<path d="M682 1430 c0 -14 2 -19 5 -12 2 6 2 18 0 25 -3 6 -5 1 -5 -13z"/>
<path d="M893 1443 c-13 -2 -23 -11 -23 -19 0 -18 14 -18 30 0 6 8 24 17 38
19 26 4 26 4 2 4 -14 0 -35 -2 -47 -4z"/>
<path d="M1776 1442 c-3 -6 -1 -14 5 -17 15 -10 25 3 12 16 -7 7 -13 7 -17 1z"/>
<path d="M613 1403 c-7 -3 -13 -16 -13 -29 0 -19 5 -24 25 -24 21 0 25 5 25
28 0 28 -10 34 -37 25z"/>
<path d="M1330 1400 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1060 1390 c-12 -7 -10 -9 8 -7 12 0 22 5 22 9 0 11 -12 10 -30 -2z"/>
<path d="M2031 1374 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M1826 1372 c-2 -4 4 -9 15 -9 10 -1 19 2 19 8 0 11 -27 12 -34 1z"/>
<path d="M1870 1368 c0 -4 7 -8 15 -8 8 0 15 4 15 8 0 5 -7 9 -15 9 -8 0 -15
-4 -15 -9z"/>
<path d="M1300 1344 c0 -8 5 -12 10 -9 6 4 8 11 5 16 -9 14 -15 11 -15 -7z"/>
<path d="M1485 1340 c3 -5 10 -10 16 -10 5 0 9 5 9 10 0 6 -7 10 -16 10 -8 0
-12 -4 -9 -10z"/>
<path d="M560 1322 c0 -5 7 -9 15 -9 8 0 15 4 15 9 0 4 -7 8 -15 8 -8 0 -15
-4 -15 -8z"/>
<path d="M1550 1310 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
-4 -4 -4 -10z"/>
<path d="M1206 1298 c3 -4 9 -8 15 -8 5 0 9 4 9 8 0 5 -7 9 -15 9 -8 0 -12 -4
-9 -9z"/>
<path d="M1270 1300 c0 -5 7 -10 16 -10 8 0 12 5 9 10 -3 6 -10 10 -16 10 -5
0 -9 -4 -9 -10z"/>
<path d="M460 1285 c0 -8 2 -15 4 -15 2 0 6 7 10 15 3 8 1 15 -4 15 -6 0 -10
-7 -10 -15z"/>
<path d="M2048 1265 c-4 -34 14 -51 25 -22 4 10 6 10 6 0 1 -7 8 -13 17 -13
13 0 15 6 9 27 -8 33 -5 29 -31 37 -19 6 -22 2 -26 -29z"/>
<path d="M1740 1280 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1870 1260 c0 -26 4 -30 28 -30 26 0 28 3 24 30 -3 24 -9 30 -28 30
-20 0 -24 -5 -24 -30z"/>
<path d="M821 1264 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M1220 1260 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1460 1240 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
-4 -4 -4 -10z"/>
<path d="M1810 1240 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
-4 -4 -4 -10z"/>
<path d="M688 1233 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M690 1654 c0 -14 3 -14 15 -4 8 7 15 14 15 16 0 2 -7 4 -15 4 -8 0
-15 -7 -15 -16z"/>
<path d="M730 1010 c0 -5 5 -10 10 -10 6 0 10 5 10 10 0 6 -4 10 -10 10 -5 0
-10 -4 -10 -10z"/>
<path d="M1326 961 c-4 -7 -5 -15 -2 -18 9 -9 19 4 14 18 -4 11 -6 11 -12 0z"/>
<path d="M2230 1300 c6 -11 13 -20 16 -20 2 0 0 9 -6 20 -6 11 -13 20 -16 20
-2 0 0 -9 6 -20z"/>
<path d="M2250 1261 c0 -4 -14 -7 -32 -5 -32 4 -34 -5 -1 -10 10 -2 19 -13 21
-24 3 -17 10 -22 32 -22 16 0 31 -5 33 -10 3 -6 4 -5 3 2 -1 7 -15 14 -30 16
-25 3 -28 7 -22 33 3 16 3 29 1 29 -3 0 -5 -4 -5 -9z"/>
<path d="M2310 1156 c0 -2 8 -10 18 -17 15 -13 16 -12 3 4 -13 16 -21 21 -21
13z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 KiB

+963
View File
@@ -0,0 +1,963 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="790.000000pt" height="784.000000pt" viewBox="0 0 790.000000 784.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,784.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M320 7751 c-83 -26 -141 -74 -181 -151 l-24 -45 0 -3640 0 -3640 27
-50 c31 -59 67 -94 128 -126 l45 -24 3640 0 3640 0 50 27 c59 31 94 67 126
128 l24 45 0 3640 0 3640 -24 45 c-32 61 -67 97 -126 128 l-50 27 -3625 2
c-1994 1 -3636 -2 -3650 -6z m3847 -675 c161 -72 716 -304 745 -311 13 -3 70
1 128 9 58 9 106 12 108 8 2 -4 38 -59 80 -122 l77 -115 95 -27 c52 -15 196
-58 318 -95 l224 -68 92 -245 c130 -343 180 -450 277 -587 45 -65 97 -138 114
-163 l31 -45 -8 -100 c-37 -464 -36 -453 -17 -616 9 -85 23 -199 29 -254 6
-55 22 -136 36 -180 61 -203 66 -248 38 -330 -15 -46 -74 -153 -97 -177 -6 -7
-30 -36 -51 -63 -67 -86 -207 -215 -232 -215 -9 0 -12 -4 -9 -10 3 -5 2 -10
-4 -10 -6 0 -31 -32 -56 -70 -25 -38 -66 -103 -92 -142 -51 -79 -321 -509
-325 -519 -3 -6 -501 -206 -648 -259 -94 -35 -358 -144 -755 -313 -143 -60
-265 -110 -271 -110 -12 0 -60 19 -459 188 -455 192 -490 205 -845 325 l-335
113 -114 191 c-169 283 -344 556 -353 550 -4 -3 -5 1 -2 9 3 8 -2 20 -11 27
-8 7 -15 10 -15 7 0 -3 -10 4 -23 16 -12 12 -49 45 -82 72 -32 28 -70 60 -82
73 -13 12 -27 22 -31 22 -4 0 -14 8 -23 18 -8 9 -31 31 -50 47 -47 42 -120
131 -112 138 3 4 -1 9 -10 13 -22 8 -40 97 -34 164 6 70 33 188 47 205 18 22
29 72 55 250 59 413 59 414 40 690 -9 137 -20 297 -25 354 l-9 105 166 173
c112 117 173 173 187 173 28 0 231 41 243 49 5 3 68 87 140 186 71 99 183 253
247 343 65 90 128 174 140 187 15 16 92 47 261 103 132 44 404 138 605 210
462 164 513 181 526 182 6 0 65 -24 131 -54z m2490 -5305 c141 -6 143 -6 170
-35 16 -16 22 -25 14 -21 -7 4 -17 2 -21 -5 -6 -9 -14 -8 -36 6 -27 18 -70 19
-1099 15 -649 -2 -1076 -7 -1085 -12 -11 -7 -8 -8 10 -4 17 4 21 3 11 -3 -7
-5 -47 -10 -88 -11 -42 -1 -80 -4 -85 -7 -5 -3 -44 -8 -86 -10 -80 -4 -103 -7
-162 -17 -81 -15 -231 -16 -335 -2 -60 8 -150 17 -200 20 -49 2 -106 7 -125
10 -19 3 -43 6 -52 7 -10 1 -18 6 -18 10 0 4 -9 5 -20 3 -11 -2 -22 0 -25 5
-6 9 -539 13 -1720 15 -509 0 -510 0 -552 -22 -24 -13 -43 -22 -44 -20 -20 62
4 71 206 77 240 8 5170 9 5342 1z m-4749 -210 c38 -1 57 -6 72 -21 26 -26 26
-76 1 -92 -19 -12 -19 -13 5 -35 34 -31 33 -84 -2 -112 -22 -17 -41 -21 -109
-21 -66 0 -84 3 -89 16 -3 9 -6 69 -6 134 0 103 2 120 18 129 9 5 26 8 37 6
11 -2 44 -4 73 -4z m322 -16 c46 -41 29 -106 -46 -175 -24 -22 -44 -42 -44
-43 0 -2 27 -1 60 1 59 4 60 4 60 -22 l0 -26 -105 0 c-129 0 -132 7 -41 91 71
66 96 110 76 134 -18 21 -58 19 -72 -5 -14 -21 -68 -29 -68 -9 0 6 16 27 35
46 33 33 39 35 81 30 25 -2 53 -12 64 -22z m229 14 c52 -18 69 -79 32 -113
-18 -17 -18 -18 5 -41 44 -44 24 -104 -42 -125 -102 -34 -198 57 -131 124 23
23 23 24 5 46 -22 27 -23 49 -2 78 28 40 76 51 133 31z m401 -18 c34 -24 46
-72 30 -111 -16 -38 -56 -60 -110 -60 l-40 0 0 -45 c0 -43 -1 -45 -30 -45
l-30 0 0 139 0 140 33 3 c59 7 122 -2 147 -21z m511 -106 c27 -71 48 -136 49
-142 0 -8 -12 -13 -29 -13 -23 0 -31 6 -40 30 -9 28 -13 30 -65 30 -51 0 -55
-2 -65 -30 -8 -24 -16 -30 -40 -30 l-30 0 30 83 c17 45 37 98 44 117 33 89 32
87 66 86 32 -1 33 -1 80 -131z m274 105 c0 -22 -5 -25 -42 -28 l-43 -3 0 -115
0 -114 -30 0 -30 0 0 115 0 115 -40 0 c-38 0 -40 2 -40 30 l0 31 113 -3 112
-3 0 -25z m245 0 l0 -30 -70 0 -70 0 0 -35 0 -35 66 0 c62 0 65 -1 62 -22 -3
-21 -9 -23 -65 -26 l-63 -3 0 -54 c0 -54 0 -55 -30 -55 l-30 0 0 138 c0 76 3
142 7 145 3 4 48 7 100 7 l93 0 0 -30z m241 13 c16 -10 39 -37 50 -61 65 -133
-65 -271 -190 -204 -91 49 -94 204 -5 262 37 25 106 26 145 3z m278 6 c61 -21
80 -101 34 -147 l-26 -26 26 -48 c15 -26 27 -51 27 -54 0 -3 -14 -4 -32 -2
-26 2 -37 12 -58 48 -29 50 -69 67 -71 31 -1 -12 -3 -25 -4 -31 -1 -5 -3 -19
-4 -30 -1 -14 -8 -20 -26 -20 l-25 0 0 145 0 145 64 0 c34 0 77 -5 95 -11z
m221 -81 c19 -47 38 -89 41 -93 4 -3 22 34 42 82 l35 88 42 3 43 3 -6 -83 c-4
-46 -7 -109 -7 -140 0 -55 -1 -58 -25 -58 -25 0 -25 1 -25 87 0 47 -3 83 -7
79 -4 -4 -21 -42 -38 -84 -43 -106 -58 -104 -105 8 l-35 85 -3 -87 -3 -88 -29
0 -30 0 0 138 c0 76 3 142 7 146 4 4 21 6 37 4 28 -3 33 -10 66 -90z m805 68
c77 -50 76 -202 -1 -253 -38 -24 -116 -23 -151 3 -86 63 -81 212 9 258 39 20
106 16 143 -8z m327 -15 c33 -37 35 -48 8 -56 -14 -4 -30 2 -52 20 -58 49
-123 9 -123 -76 0 -43 4 -54 28 -75 34 -29 56 -30 91 -3 37 29 34 49 -9 49
-28 0 -35 4 -35 20 0 18 7 20 66 20 l67 0 -6 -46 c-17 -155 -239 -146 -263 11
-9 60 26 132 76 158 52 27 117 18 152 -22z m-2762 -86 l0 -114 68 -3 c61 -3
67 -5 70 -25 3 -23 1 -23 -97 -23 l-101 0 0 140 0 140 30 0 30 0 0 -115z
m2060 1 c0 -128 -2 -126 88 -126 35 0 42 -3 42 -20 0 -19 -7 -20 -95 -20 l-95
0 0 140 0 140 30 0 30 0 0 -114z m840 -26 l0 -140 -25 0 -25 0 0 140 0 140 25
0 25 0 0 -140z m182 53 l63 -88 3 88 3 87 29 0 30 0 0 -140 0 -140 -27 0 c-24
1 -38 15 -93 92 l-65 91 -3 -92 -3 -91 -27 0 -27 0 2 137 c0 76 2 139 2 141 1
1 12 2 25 2 19 0 38 -19 88 -87z m-3106 -378 c38 -51 1 -115 -66 -115 -39 0
-40 -1 -40 -35 0 -24 -5 -35 -15 -35 -12 0 -15 18 -15 106 l0 106 61 -4 c45
-3 65 -10 75 -23z m194 10 c0 -11 -12 -15 -50 -15 -49 0 -50 -1 -50 -29 0 -28
2 -30 48 -33 59 -4 58 -22 -3 -26 -42 -3 -45 -5 -45 -33 0 -28 1 -29 50 -29
38 0 50 -4 50 -15 0 -12 -14 -15 -70 -15 l-70 0 0 105 0 105 70 0 c56 0 70 -3
70 -15z m194 6 c3 -5 -19 -43 -49 -86 -30 -42 -55 -78 -55 -80 0 -2 23 -5 52
-7 30 -2 53 -8 56 -15 3 -10 -18 -13 -82 -13 -47 0 -86 3 -86 8 1 4 27 43 59
87 l59 80 -54 3 c-39 2 -54 7 -54 17 0 12 16 15 74 15 41 0 77 -4 80 -9z m76
-36 c0 -25 2 -45 5 -45 2 0 23 20 46 45 23 25 50 45 61 45 17 0 13 -8 -21 -46
l-41 -47 33 -46 c50 -70 51 -71 28 -71 -13 0 -32 17 -51 46 -26 36 -34 43 -46
33 -8 -6 -14 -27 -14 -45 0 -24 -5 -34 -15 -34 -12 0 -15 18 -15 105 0 87 3
105 15 105 11 0 15 -12 15 -45z m200 -26 c0 -85 11 -109 49 -109 41 0 50 17
53 100 2 59 6 75 18 75 23 0 27 -138 5 -172 -23 -34 -60 -46 -102 -32 -45 14
-63 53 -63 132 0 66 4 77 27 77 10 0 13 -18 13 -71z m227 -6 l20 -78 24 78
c30 100 47 100 73 -1 21 -81 27 -79 47 12 11 52 30 78 46 63 3 -4 -7 -52 -23
-107 -25 -85 -32 -100 -48 -98 -14 2 -24 19 -37 67 -10 35 -20 65 -22 68 -3 2
-12 -28 -22 -67 -15 -62 -20 -71 -38 -68 -17 2 -26 20 -49 98 -33 114 -33 110
-9 110 15 0 23 -15 38 -77z m283 -28 c0 -82 -3 -105 -14 -105 -16 0 -26 50
-26 136 0 63 4 74 27 74 10 0 13 -24 13 -105z m206 80 c25 -25 25 -45 1 -45
-7 0 -20 9 -30 20 -37 43 -97 8 -97 -57 0 -64 58 -96 101 -57 11 10 25 14 35
10 16 -6 15 -10 -9 -34 -40 -40 -99 -38 -138 6 -33 36 -37 74 -15 126 17 41
39 55 89 56 27 0 45 -7 63 -25z m92 -23 l3 -42 50 0 49 0 0 46 c0 38 3 45 18
42 15 -3 17 -17 20 -106 3 -97 2 -102 -18 -102 -17 0 -20 6 -20 45 l0 45 -50
0 -50 0 0 -45 c0 -38 -3 -45 -20 -45 -19 0 -20 7 -20 106 0 95 2 105 18 102
12 -2 18 -15 20 -46z m324 -52 c44 -113 43 -110 18 -110 -13 0 -22 9 -26 25
-5 22 -12 25 -48 25 -36 0 -45 -4 -54 -25 -7 -14 -20 -25 -31 -25 -18 0 -17 4
9 68 16 37 35 84 44 105 25 61 45 47 88 -63z m106 -8 c3 -97 2 -102 -18 -102
-19 0 -20 6 -20 106 0 95 2 105 18 102 15 -3 17 -17 20 -106z m129 38 c56 -78
63 -76 63 17 0 39 4 54 13 51 8 -3 13 -36 15 -106 2 -92 1 -102 -15 -102 -11
0 -38 29 -68 72 l-50 71 -3 -72 c-3 -63 -5 -71 -22 -71 -19 0 -20 7 -20 98 0
140 12 146 87 42z m-462 -340 c109 0 201 -3 204 -5 2 -3 -245 -4 -550 -3 -305
1 -502 4 -439 7 63 3 215 6 337 6 123 0 223 4 223 9 0 5 6 4 13 -2 7 -6 89
-11 212 -12z m-967 -7 c-10 -2 -26 -2 -35 0 -10 3 -2 5 17 5 19 0 27 -2 18 -5z"/>
<path d="M4130 6898 c-45 -23 -85 -48 -88 -56 -3 -8 5 -23 19 -34 20 -17 21
-19 4 -13 -63 22 -89 17 -200 -35 -60 -29 -151 -71 -201 -95 -84 -40 -175
-105 -146 -105 23 0 2 -20 -50 -46 -46 -24 -52 -24 -60 -9 -6 9 -18 19 -28 23
-16 6 -7 17 54 64 105 83 272 244 263 254 -4 5 -11 4 -15 -1 -4 -6 -27 -11
-52 -12 -25 -1 -115 -15 -200 -30 -141 -24 -167 -32 -280 -86 -69 -32 -141
-66 -160 -75 -19 -9 -47 -25 -62 -36 -26 -19 -29 -19 -115 -2 -154 29 -146 29
-139 10 3 -9 13 -53 22 -99 l17 -83 61 -8 c40 -5 52 -9 34 -12 -31 -4 -37 -17
-12 -26 12 -5 15 -13 10 -34 -4 -15 -9 -39 -11 -53 l-4 -27 42 13 c58 18 183
84 179 96 -2 8 45 3 56 -6 1 -1 -27 -14 -63 -29 l-64 -28 -3 -111 -3 -112
-100 -1 -100 0 90 3 c83 4 104 11 105 36 0 4 -6 7 -12 6 -42 -5 -78 2 -78 16
0 11 12 15 43 16 l42 2 -35 6 c-45 9 -60 4 -60 -20 0 -10 -7 -19 -15 -19 -9 0
-15 9 -15 23 -1 22 -1 22 -15 -3 l-14 -25 1 33 1 32 74 0 c58 0 73 3 73 15 0
12 -14 15 -65 15 -74 0 -87 -6 -169 -75 -56 -47 -58 -50 -35 -56 22 -6 21 -7
-7 -8 -16 -1 -39 -9 -50 -18 -55 -50 -56 -50 -50 -10 4 23 2 37 -5 37 -5 0 -8
4 -5 9 10 16 -6 42 -21 36 -12 -4 -14 0 -10 15 3 11 3 20 1 20 -10 0 -134 -88
-232 -164 -146 -114 -164 -126 -186 -126 -10 0 -66 -10 -123 -22 l-103 -21 -2
-41 c-3 -74 1 -125 9 -140 7 -12 18 -8 60 24 31 24 58 38 67 34 14 -5 13 -10
-5 -32 -19 -25 -19 -27 -2 -33 10 -3 24 -4 32 -1 9 3 12 1 7 -6 -12 -20 19
-14 44 8 13 11 37 20 56 20 22 0 32 4 30 13 -3 6 -7 27 -10 46 -9 50 7 28 20
-27 5 -26 15 -46 21 -45 6 1 8 -8 5 -22 -2 -14 -8 -25 -13 -25 -9 0 -109 -97
-150 -146 -15 -17 -30 -40 -33 -52 -4 -11 -16 -22 -26 -25 -11 -3 -20 -4 -20
-3 0 1 42 51 94 111 52 60 92 115 89 122 -7 17 -40 16 -136 -2 -43 -8 -80 -15
-82 -15 -2 0 -17 -14 -34 -31 l-31 -31 0 -118 c0 -65 4 -121 9 -124 4 -3 25
13 45 35 20 22 36 37 36 32 0 -5 -4 -13 -9 -18 -19 -20 -51 -86 -51 -105 0
-10 -4 -22 -10 -25 -5 -3 -10 -43 -11 -88 l-1 -82 -12 60 c-13 62 -17 61 -35
-15 -54 -224 -88 -423 -106 -622 l-7 -77 113 -3 114 -3 14 -117 c13 -114 13
-120 -8 -176 -36 -101 -33 -113 77 -302 84 -144 185 -305 194 -308 4 -2 8 -8
8 -13 0 -28 341 -499 398 -549 23 -21 70 -48 105 -60 34 -13 107 -45 162 -71
55 -26 172 -73 260 -104 88 -31 207 -73 265 -95 327 -121 393 -145 473 -176
111 -44 131 -42 317 29 344 131 794 310 980 391 91 40 185 78 208 86 29 9 55
27 77 54 39 49 239 342 278 408 39 67 126 288 120 305 -3 8 2 19 11 26 21 16
78 174 71 197 -4 12 1 19 14 23 11 3 22 17 26 37 4 17 31 78 61 135 54 102 54
103 54 194 l0 91 171 0 171 0 -7 88 c-12 144 -29 255 -40 258 -5 2 -32 -28
-60 -66 -27 -38 -53 -66 -56 -62 -4 4 -12 57 -18 117 -15 143 -33 289 -37 294
-4 5 -34 -26 -34 -35 0 -18 -83 -155 -90 -147 -5 4 -5 35 -1 68 5 46 9 55 15
38 4 -13 13 -23 21 -23 13 0 45 67 45 95 0 8 5 15 11 15 5 0 7 5 4 11 -5 7
-14 4 -26 -7 -17 -16 -19 -16 -19 -1 0 10 3 17 8 17 7 0 33 89 35 122 1 9 5
14 9 12 4 -3 8 -1 8 5 0 5 -20 17 -45 26 -34 14 -48 15 -59 6 -7 -6 -21 -8
-31 -5 -14 6 -16 3 -12 -12 3 -10 8 -38 12 -61 l7 -42 -44 22 c-24 11 -62 21
-85 22 -24 0 -48 6 -55 13 -9 9 2 12 53 12 36 0 68 2 71 6 3 3 -7 28 -23 57
-33 61 -36 79 -11 70 14 -5 15 -4 6 8 -15 19 -28 93 -15 85 5 -3 12 -20 16
-36 8 -36 21 -46 40 -30 23 19 85 136 85 160 0 12 -22 97 -50 189 -27 91 -52
178 -55 193 -5 20 -27 38 -95 77 -48 28 -92 51 -98 51 -6 0 -8 -16 -5 -37 l4
-38 -18 35 c-10 19 -24 34 -31 32 -7 -1 -12 2 -12 8 0 5 5 10 11 10 8 0 7 5
-1 15 -7 9 -25 37 -39 63 -73 133 -69 129 -151 151 l-75 19 71 -5 c67 -5 73
-4 84 16 8 15 17 20 31 16 31 -10 42 5 17 25 -13 11 -17 19 -10 20 6 0 12 -4
12 -10 0 -5 6 -10 14 -10 8 0 17 -6 20 -12 4 -7 4 -3 2 10 -3 14 1 22 11 22 8
0 11 -4 8 -10 -3 -5 -1 -10 4 -10 6 0 11 7 11 15 0 8 4 15 10 15 5 0 9 -3 9
-7 -3 -20 2 -34 10 -29 9 6 9 31 0 40 -2 3 -70 12 -149 21 -118 13 -171 25
-281 61 l-135 46 -97 -46 c-53 -25 -98 -50 -101 -55 -3 -5 9 -11 26 -15 21 -4
34 -2 40 6 6 10 8 9 8 -2 0 -12 -16 -15 -85 -16 -63 0 -85 3 -85 13 0 7 -12
20 -26 30 -26 17 -26 17 -5 25 20 7 21 9 7 42 -8 19 -33 62 -56 95 l-41 61
-74 0 c-43 0 -75 4 -75 10 0 6 26 10 59 10 55 0 88 13 59 22 -6 2 4 14 23 26
19 12 46 30 61 40 l28 19 -23 11 c-52 27 -555 167 -565 158 -2 -2 24 -25 57
-51 34 -27 61 -50 61 -52 0 -2 -44 26 -97 62 -54 36 -103 65 -110 65 -6 0 -48
-19 -93 -42z m0 -229 c0 -5 -7 -9 -15 -9 -15 0 -20 12 -9 23 8 8 24 -1 24 -14z
m-130 1 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11
-10z m61 -136 c30 -36 61 -74 69 -84 8 -9 33 -29 55 -44 21 -15 51 -48 65 -73
18 -34 32 -47 49 -48 13 -1 29 -9 36 -18 7 -10 17 -17 24 -17 6 0 61 -25 122
-55 86 -42 119 -54 145 -50 25 3 34 0 34 -11 0 -12 4 -12 20 -4 11 6 20 20 20
31 0 12 5 19 13 16 6 -2 18 3 25 12 11 14 11 14 6 -1 -5 -14 -1 -18 15 -18 14
0 21 -6 21 -19 0 -37 19 -31 23 6 l4 38 1 -42 c1 -26 -2 -43 -9 -43 -6 0 -9
-7 -5 -15 4 -12 -5 -15 -47 -15 -38 -1 -48 -3 -36 -10 9 -5 27 -11 40 -13 13
-2 24 -10 24 -18 0 -16 41 -39 72 -39 12 0 24 -4 27 -9 3 -4 20 -11 38 -15 19
-4 50 -25 77 -52 45 -46 85 -69 102 -58 5 3 9 0 9 -7 0 -6 8 -1 18 11 22 27
46 19 36 -12 -4 -14 -2 -18 5 -14 6 4 11 2 11 -5 0 -6 -8 -9 -18 -7 -10 3 -23
-1 -29 -7 -15 -17 3 -35 34 -35 16 0 23 -6 23 -20 0 -13 10 -24 26 -30 35 -14
37 -13 31 10 -3 11 0 20 6 20 6 0 8 2 5 5 -8 9 -38 -6 -32 -16 3 -5 0 -9 -5
-9 -6 0 -11 2 -11 4 0 2 -3 11 -6 20 -5 14 5 16 72 15 44 0 74 -3 67 -5 -7 -3
-9 -12 -6 -20 4 -11 -5 -14 -38 -15 l-44 -2 50 -6 c28 -3 74 -6 103 -6 28 0
52 -3 52 -7 0 -5 -4 -9 -10 -9 -5 -1 -14 -3 -20 -4 -5 -1 -19 -3 -30 -4 -23
-1 -29 -41 -6 -41 8 0 16 -7 20 -15 3 -8 9 -15 13 -14 21 3 33 -2 33 -15 0
-17 30 -30 31 -13 1 7 4 1 8 -13 4 -14 12 -25 18 -25 6 0 15 -3 19 -7 4 -4 18
-5 32 -1 17 4 23 2 18 -6 -5 -8 40 -12 171 -13 l178 -2 -152 -3 c-84 -2 -153
-6 -153 -10 0 -3 8 -11 17 -18 15 -11 15 -14 -6 -36 -12 -13 -17 -25 -11 -27
5 -2 8 -8 5 -13 -3 -5 -1 -17 5 -28 11 -22 3 -54 -12 -45 -5 3 -12 -3 -15 -15
-8 -30 -33 -27 -33 4 0 15 -7 28 -17 32 -10 4 -24 14 -31 22 -11 14 -12 13 -3
-4 5 -11 16 -29 24 -40 17 -23 2 -69 -20 -61 -14 6 -18 -10 -4 -18 5 -3 11
-18 13 -34 4 -26 2 -28 -27 -24 -17 2 -25 0 -19 -5 39 -30 2 -92 -64 -102 -29
-5 -37 -11 -36 -28 0 -15 -5 -20 -18 -18 -23 5 -23 -4 0 -22 16 -12 15 -13 -7
-11 -19 2 -31 -5 -47 -29 -12 -18 -24 -29 -28 -26 -3 4 -6 1 -6 -5 0 -6 -10
-14 -22 -18 -12 -3 -28 -13 -36 -20 -7 -8 -24 -14 -37 -14 -13 0 -31 -8 -41
-17 -10 -10 -27 -23 -38 -28 -12 -6 -20 -19 -18 -28 3 -20 -14 -23 -21 -4 -4
9 -7 9 -15 -1 -5 -7 -17 -14 -26 -16 -10 -1 -21 -7 -24 -12 -7 -10 -36 -24
-49 -23 -3 1 -10 -6 -15 -14 -4 -8 -27 -25 -50 -37 -24 -13 -54 -30 -68 -37
-23 -14 -24 -15 -2 -10 12 3 22 2 22 -1 0 -12 -51 -31 -67 -25 -9 4 -19 -1
-25 -10 -5 -10 -18 -17 -29 -17 -11 0 -30 -5 -42 -12 -12 -7 -33 -14 -47 -16
-14 -2 -29 -7 -35 -13 -5 -5 -17 -9 -27 -9 -10 0 -21 -6 -24 -13 -3 -8 -18
-14 -34 -15 -16 0 -38 -6 -50 -12 -12 -6 -28 -9 -35 -6 -8 3 -17 1 -20 -4 -3
-5 -12 -7 -21 -3 -8 3 -14 2 -13 -3 4 -22 -2 -34 -18 -34 -13 0 -14 -3 -6 -11
6 -6 9 -17 6 -24 -2 -7 4 -16 15 -19 11 -4 30 -20 42 -36 13 -17 32 -30 43
-30 11 0 18 -3 14 -6 -3 -4 0 -13 8 -21 8 -8 13 -22 12 -31 -6 -35 -42 -101
-54 -97 -13 4 -7 -20 9 -42 5 -7 5 -14 -2 -18 -5 -3 -10 -17 -10 -31 0 -13 -6
-24 -12 -24 -10 0 -10 -2 0 -9 8 -4 13 -11 13 -15 -3 -19 1 -25 19 -31 11 -3
20 -11 20 -16 0 -6 -5 -7 -12 -3 -7 4 -8 3 -4 -5 9 -14 26 -5 26 15 0 8 7 14
15 14 8 0 15 7 15 15 0 8 7 15 15 15 8 0 15 5 15 10 0 6 21 34 48 62 47 51 93
78 131 78 20 0 21 -7 23 -172 l3 -172 35 -4 c19 -2 42 -8 52 -13 10 -5 18 -6
18 -2 0 5 17 8 37 7 36 -2 68 -27 57 -45 -3 -5 -2 -9 3 -9 4 0 6 -60 3 -134
-5 -132 -5 -135 -34 -165 -17 -17 -40 -31 -52 -31 -30 0 -34 -8 -25 -49 8 -41
37 -64 51 -41 8 13 10 12 10 -2 0 -10 -8 -18 -17 -19 -45 -2 -99 -19 -60 -19
10 0 17 -5 17 -11 0 -6 -6 -9 -12 -6 -7 2 -21 0 -30 -4 -12 -7 -18 -4 -23 12
-10 30 -25 10 -27 -33 -1 -26 -5 -35 -15 -31 -13 5 -17 16 -14 41 1 6 -5 12
-14 12 -18 0 -21 20 -2 21 6 0 2 4 -10 9 -17 7 -23 18 -23 40 l0 30 -59 0
c-33 0 -63 5 -66 11 -5 7 13 10 56 8 50 -2 64 0 64 12 0 16 -111 33 -177 27
-21 -2 -38 0 -38 4 0 8 16 12 33 9 4 0 7 37 7 84 0 81 -1 85 -22 85 -13 0 -33
3 -45 6 -22 6 -23 4 -23 -56 0 -51 3 -61 15 -56 8 3 15 1 15 -4 0 -6 -7 -10
-15 -10 -11 0 -15 -12 -15 -49 0 -28 5 -53 10 -56 6 -4 7 -12 3 -18 -4 -7 -6
-22 -4 -34 1 -14 -3 -23 -11 -23 -10 0 -9 -3 2 -10 21 -13 11 -19 -51 -27 -54
-8 -54 -8 -60 -48 l-6 -40 -2 48 c-1 40 -5 50 -21 54 -11 3 -20 9 -20 15 0 5
8 5 18 -1 17 -9 19 -6 17 42 -1 29 -3 150 -4 269 l-1 216 -32 10 c-18 6 -46
13 -62 17 l-29 6 8 -208 c5 -114 9 -218 9 -230 1 -17 7 -23 24 -23 12 0 22 5
22 11 0 8 4 8 15 -1 12 -10 14 -8 13 12 -2 46 2 78 10 78 9 0 8 -117 -1 -127
-4 -3 -7 -1 -7 5 0 7 -9 12 -20 12 -22 0 -26 -10 -9 -27 9 -9 7 -11 -9 -6 -11
3 -23 11 -26 19 -12 30 -23 11 -25 -43 -1 -31 -6 -64 -11 -74 -6 -10 -7 -31
-4 -48 6 -27 4 -31 -15 -31 -17 0 -21 6 -22 33 0 33 -11 70 -19 66 -3 -2 -14
2 -25 8 -16 10 -18 14 -7 24 9 10 12 10 12 1 0 -7 7 -12 15 -12 20 0 20 58 0
84 -8 11 -15 18 -16 15 -8 -46 -14 -57 -26 -45 -4 4 -1 11 7 16 13 8 12 10 -3
10 -38 0 -49 -26 -52 -131 -4 -99 -15 -153 -15 -71 0 37 -3 42 -23 42 -13 0
-28 5 -35 12 -9 9 -12 7 -12 -9 0 -11 -7 -26 -15 -33 -25 -21 -43 5 -50 76 -8
68 -20 88 -40 61 -10 -14 -28 -17 -91 -15 l-79 2 78 3 c80 4 104 19 40 26
l-38 4 43 1 c41 2 42 3 42 36 0 33 -1 34 -50 40 -28 4 -55 4 -60 1 -13 -8 -50
4 -50 16 0 5 7 9 15 9 22 0 21 76 -1 84 -31 12 -34 5 -34 -93 0 -54 -3 -113
-6 -130 -6 -28 -8 -30 -19 -14 -12 15 -12 14 -8 -11 4 -20 2 -27 -6 -22 -7 5
-11 -4 -11 -28 0 -29 -4 -36 -19 -36 -10 0 -21 -6 -24 -14 -4 -10 18 -25 78
-50 46 -20 87 -36 92 -36 5 0 17 -6 27 -13 15 -11 15 -17 6 -42 -7 -17 -12
-51 -11 -78 1 -43 -1 -47 -18 -38 -12 7 -22 6 -29 -1 -14 -14 -14 -13 -16 25
-1 19 3 27 15 27 9 0 22 7 29 15 11 13 8 15 -14 15 -20 0 -26 5 -27 23 l0 22
-11 -22 c-16 -32 -56 -36 -75 -6 -15 23 -16 23 -29 5 -13 -19 -69 -29 -58 -10
3 5 14 6 24 3 12 -4 19 1 24 17 12 46 9 48 -59 48 -57 0 -67 3 -90 28 -29 30
-116 204 -136 270 l-13 44 -13 -27 c-8 -14 -18 -23 -23 -20 -13 8 -13 45 1 45
6 0 9 14 7 32 -2 27 -8 34 -33 39 -16 4 -22 7 -12 8 10 0 15 6 12 11 -3 6 1
10 9 10 22 0 18 69 -4 72 -8 0 -19 2 -25 3 -5 2 -20 3 -32 4 -33 1 -28 21 7
34 l31 12 -3 100 -3 100 -50 1 c-27 1 -55 -1 -62 -3 -13 -5 -23 -66 -22 -142
0 -71 -24 -67 -27 5 -2 85 -19 53 -19 -38 0 -48 -4 -90 -8 -94 -4 -4 -7 -65
-7 -136 l0 -129 -105 3 -105 3 0 -27 c0 -23 -4 -28 -24 -28 -13 0 -31 10 -39
23 -14 19 -18 20 -26 7 -9 -13 -11 -12 -11 3 0 10 -4 15 -10 12 -5 -3 -10 1
-10 10 0 9 -5 13 -10 10 -6 -3 -12 0 -15 7 -10 24 -12 88 -3 89 4 1 13 2 18 3
19 2 11 18 -16 32 l-26 14 4 -70 c2 -39 0 -70 -4 -70 -4 0 -8 33 -8 74 0 68
-2 74 -22 80 -17 4 -28 -1 -40 -17 l-18 -22 0 27 c0 14 -3 33 -6 41 -4 12 0
14 18 11 16 -3 13 0 -9 11 -18 8 -33 19 -33 23 0 13 -147 75 -159 67 -8 -4
-11 29 -12 102 -1 311 1 437 10 446 5 5 41 7 80 5 l71 -3 0 34 c0 49 6 35 14
-31 4 -37 2 -58 -4 -58 -5 0 -10 9 -10 20 0 18 -7 20 -70 20 -66 0 -70 -1 -70
-22 0 -20 5 -23 40 -23 51 0 52 12 3 18 -23 2 -14 4 20 3 73 0 78 -22 7 -32
-28 -4 -50 -12 -50 -18 0 -6 -4 -5 -9 2 -13 21 -17 -21 -10 -103 3 -38 7 -56
8 -40 2 20 5 24 8 12 3 -11 11 -16 19 -13 8 3 14 1 14 -4 0 -6 9 -10 20 -10
11 0 20 -4 20 -10 0 -5 9 -10 20 -10 15 0 20 -7 21 -27 l1 -28 7 30 c5 19 12
29 22 27 59 -15 79 -14 79 2 0 9 5 16 10 16 6 0 10 4 10 10 0 5 -17 12 -37 15
-66 11 -69 13 -47 35 18 18 34 19 209 19 213 0 234 -1 233 -9 -1 -17 3 -30 11
-30 5 0 7 9 4 20 -3 11 0 20 6 20 6 0 11 -20 12 -47 1 -46 15 -122 18 -95 1 9
6 10 19 4 19 -10 68 -9 79 1 11 12 43 8 43 -5 0 -9 3 -9 9 1 6 9 30 15 63 17
29 1 59 3 66 3 7 1 12 14 12 31 0 44 20 37 21 -7 0 -21 3 -32 6 -25 2 6 15 12
28 12 31 0 56 10 50 20 -3 5 -1 11 5 15 5 3 10 1 10 -4 0 -19 29 -12 40 9 7
13 10 85 9 188 -1 134 2 167 13 167 7 0 11 -7 8 -15 -3 -8 -5 -64 -5 -125 0
-88 3 -110 14 -110 8 0 16 -6 19 -12 2 -7 -3 -13 -12 -13 -12 0 -16 -11 -16
-47 0 -63 12 -82 39 -66 11 7 27 10 35 7 9 -3 23 1 31 10 9 9 23 16 32 16 8 0
27 9 43 20 15 11 30 17 34 13 3 -3 6 1 6 11 0 9 5 14 10 11 19 -12 8 69 -12
88 -23 22 -23 33 0 42 15 6 15 8 -5 16 -15 5 -21 14 -17 24 4 8 1 21 -5 29
-18 21 -10 78 11 84 10 2 18 8 18 13 0 4 14 23 30 41 17 18 30 27 30 20 0 -10
3 -10 13 0 15 13 11 48 -5 48 -6 0 -7 7 -4 16 4 10 1 14 -6 12 -7 -3 -37 8
-67 24 -40 21 -63 27 -88 23 -28 -4 -33 -2 -33 14 0 11 -9 23 -20 26 -11 3
-20 10 -20 15 0 4 -20 15 -45 23 -25 9 -45 13 -45 11 0 -3 -7 1 -15 10 -9 8
-22 13 -30 10 -8 -4 -17 1 -21 9 -3 9 -12 13 -20 10 -8 -3 -14 1 -14 11 0 9
-8 16 -20 16 -11 0 -20 5 -20 10 0 6 -10 10 -22 10 -13 0 -33 13 -47 30 -25
33 -71 42 -71 14 0 -8 -5 -12 -10 -9 -6 4 -8 15 -5 24 3 10 0 23 -7 28 -14 11
-68 27 -80 25 -5 -1 -8 5 -8 13 0 8 -7 15 -15 15 -7 0 -18 7 -23 16 -10 17
-92 37 -92 23 0 -5 -5 -9 -12 -9 -9 0 -9 3 0 12 16 16 15 48 -1 48 -7 0 -29
12 -50 26 -29 19 -36 30 -32 45 4 12 2 19 -6 19 -14 0 -59 39 -59 51 0 5 8 6
18 2 13 -5 15 -3 5 7 -6 7 -22 14 -35 15 -36 4 -37 4 -36 23 0 9 -3 25 -7 35
-5 13 -2 17 11 17 16 0 17 2 4 10 -8 5 -11 10 -5 10 5 0 -1 7 -14 16 -13 9
-30 31 -37 48 -8 17 -24 45 -35 62 -20 32 -17 64 6 64 7 0 26 26 41 58 16 31
32 59 37 60 4 2 7 14 7 27 0 31 28 54 42 34 8 -12 9 -11 5 2 -6 18 -2 25 36
59 16 13 26 18 23 10 -4 -8 5 -28 19 -44 14 -16 25 -36 25 -43 0 -11 8 -8 29
9 18 14 28 29 25 39 -6 21 24 33 43 18 7 -7 17 -9 20 -5 4 4 1 11 -7 16 -18
11 -21 28 -23 138 -2 87 -1 93 18 90 11 -1 27 2 35 7 8 5 33 19 55 30 26 13
39 26 37 37 -2 13 9 18 55 23 32 4 84 20 116 36 32 16 63 29 70 29 30 0 153
72 172 100 14 20 31 32 55 36 111 19 164 54 214 139 14 23 48 62 76 85 32 26
49 48 46 57 -3 8 -2 11 4 8 5 -3 31 22 57 55 26 33 53 60 59 60 5 0 35 -30 65
-66z m-311 -54 c0 -5 -7 -10 -16 -10 -8 0 -12 5 -9 10 3 6 10 10 16 10 5 0 9
-4 9 -10z m708 -114 c-2 -13 -10 -21 -23 -21 -23 0 -33 34 -14 45 20 13 40 -1
37 -24z m764 -68 c-9 -9 -12 -7 -12 12 0 19 3 21 12 12 9 -9 9 -15 0 -24z
m-1924 -177 c-4 -20 -48 -28 -48 -9 0 20 20 37 37 31 8 -3 13 -13 11 -22z
m1552 -1 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z
m-2336 -34 c-6 -15 -24 -23 -24 -11 0 8 24 34 28 30 1 -1 0 -10 -4 -19z m500
15 c3 -5 -1 -11 -9 -14 -9 -4 -12 -1 -8 9 6 16 10 17 17 5z m134 -59 c-4 -2
-6 -8 -2 -13 3 -5 -2 -9 -12 -9 -11 0 -15 6 -11 20 3 11 2 18 -3 15 -11 -7
-21 22 -14 40 5 11 12 7 28 -18 12 -17 19 -34 14 -35z m-75 -14 c8 -5 7 -8 -3
-8 -21 0 -39 19 -34 36 14 45 18 48 22 14 2 -19 9 -38 15 -42z m-92 19 c-10
-9 -11 -8 -5 6 3 10 9 15 12 12 3 -3 0 -11 -7 -18z m30 -4 c-12 -20 -14 -14
-5 12 4 9 9 14 11 11 3 -2 0 -13 -6 -23z m99 -13 c0 -5 -5 -10 -11 -10 -5 0
-7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m77 -6 c-3 -3 -12 -4 -19 -1 -8 3
-5 6 6 6 11 1 17 -2 13 -5z m1683 -4 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3
6 8 10 11 10 2 0 4 -4 4 -10z m867 -6 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11
1 17 -2 13 -5z m-2957 -14 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10
10 10 6 0 10 -4 10 -10z m2907 -16 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1
17 -2 13 -5z m46 -1 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z
m-593 -17 c0 -8 -7 -16 -15 -20 -15 -5 -21 14 -8 27 11 12 23 8 23 -7z m545
-26 c-10 -11 -21 -17 -24 -14 -3 3 3 12 13 20 28 20 32 17 11 -6z m-62 3 c-7
-2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m202 -43 c4 -7 -45 -9 -142
-8 l-148 2 140 6 c77 3 141 7 142 8 1 1 5 -2 8 -8z m-3251 -31 c-7 -11 -34
-12 -34 -1 0 14 11 21 26 15 8 -3 11 -9 8 -14z m2669 14 c-24 -2 -43 -8 -43
-14 0 -5 19 -9 43 -10 23 0 36 -3 30 -6 -25 -9 -14 -30 13 -25 18 3 22 7 13
13 -10 6 -8 8 6 7 13 -1 21 -9 21 -20 0 -14 -8 -18 -36 -19 -19 0 -50 -2 -67
-3 -33 -4 -33 -3 -33 40 l0 44 48 -2 47 -1 -42 -4z m-2349 -57 c-16 -19 -36
-34 -44 -33 -9 1 -16 -8 -18 -25 -2 -16 -8 -25 -15 -22 -17 6 -134 -126 -143
-160 -4 -18 -25 -39 -62 -62 -73 -47 -93 -55 -68 -26 18 21 18 22 -9 32 -14 5
-31 8 -36 5 -5 -4 -4 6 1 20 6 15 10 28 10 31 0 12 -23 1 -55 -27 -24 -21 -41
-29 -53 -24 -15 6 -13 9 11 21 15 8 27 19 27 24 0 6 5 10 11 10 17 0 50 42 45
57 -7 18 11 26 34 13 11 -6 20 -7 20 -2 0 5 6 9 13 9 19 0 147 64 147 74 0 5
5 9 11 9 5 0 7 -4 4 -10 -3 -5 -4 -10 0 -10 3 0 10 12 15 26 6 16 16 24 24 21
10 -4 12 0 9 14 -3 10 0 19 6 19 6 0 12 -8 12 -17 1 -17 2 -17 6 0 2 10 10 17
16 16 21 -2 57 13 57 24 0 6 3 7 7 4 3 -4 13 2 21 14 8 11 16 18 19 15 3 -3
-7 -21 -23 -40z m-94 9 c0 -8 -4 -15 -10 -15 -5 0 -10 7 -10 15 0 8 5 15 10
15 6 0 10 -7 10 -15z m2680 4 c0 -4 3 -16 6 -26 6 -14 4 -16 -6 -6 -7 6 -18 9
-25 6 -9 -3 -12 2 -9 15 5 17 34 27 34 11z m245 1 c-3 -5 -14 -10 -23 -10 -15
0 -15 2 -2 10 20 13 33 13 25 0z m-3795 -10 c0 -5 -2 -10 -4 -10 -3 0 -8 5
-11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m3487 4 c-3 -3 -12 -4 -19 -1 -8 3
-5 6 6 6 11 1 17 -2 13 -5z m1 -19 c-9 -9 -68 -12 -68 -4 0 5 17 9 37 9 20 0
34 -2 31 -5z m65 -31 c-7 -3 -9 -12 -6 -20 4 -11 -8 -14 -63 -13 -66 1 -68 1
-39 14 l30 13 -30 5 c-16 2 4 4 45 5 41 0 70 -2 63 -4z m47 -9 c0 -8 -7 -15
-15 -15 -16 0 -20 12 -8 23 11 12 23 8 23 -8z m43 -1 c11 -11 -3 -24 -18 -18
-8 4 -12 10 -9 15 6 11 18 12 27 3z m-3003 -34 c0 -5 -7 -10 -16 -10 -8 0 -12
5 -9 10 3 6 10 10 16 10 5 0 9 -4 9 -10z m2997 -23 c-1 -5 -7 -8 -12 -7 -5 1
-12 -7 -16 -17 -7 -17 -8 -17 -8 0 -1 10 -9 17 -20 17 -11 0 -22 4 -25 9 -3 5
14 8 39 7 25 0 44 -5 42 -9z m156 -44 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14
0 19 -2 13 -5z m-3285 -24 c-2 -6 -8 -10 -13 -10 -5 0 -11 4 -13 10 -2 6 4 11
13 11 9 0 15 -5 13 -11z m3095 -60 c-35 -7 -39 -4 -22 14 11 11 18 12 32 3 16
-10 15 -12 -10 -17z m186 -8 c-15 -5 -22 6 -14 19 6 9 10 9 16 -1 5 -8 4 -15
-2 -18z m67 -98 c-10 -10 -19 5 -10 18 6 11 8 11 12 0 2 -7 1 -15 -2 -18z
m-3666 -53 c0 -16 -2 -30 -4 -30 -2 0 -6 14 -8 30 -3 17 -1 30 4 30 4 0 8 -13
8 -30z m75 10 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4
11 -10z m42 -55 c-32 -30 -60 -55 -62 -55 -16 0 -1 42 20 56 14 9 22 20 19 25
-3 5 2 6 10 3 9 -3 16 -1 16 4 0 10 18 18 45 21 5 0 -16 -24 -48 -54z m-115
-20 c3 -13 1 -22 -3 -19 -9 5 -13 44 -5 44 2 0 6 -11 8 -25z m3548 -17 c0 -6
-7 -5 -15 2 -8 7 -15 17 -15 22 0 6 7 5 15 -2 8 -7 15 -17 15 -22z m-3595 12
c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m3795
-71 c-25 -66 -40 -92 -40 -69 0 8 -22 26 -49 39 -48 22 -130 95 -86 75 11 -5
55 -9 97 -11 62 -1 78 1 82 14 4 9 9 14 12 11 2 -3 -4 -30 -16 -59z m-3742
-234 l-1 -50 -4 45 c-3 24 -9 50 -14 56 -5 6 -6 14 -2 18 13 12 23 -19 21 -69z
m366 -41 c10 -25 -1 -29 -14 -5 -6 12 -7 21 -1 21 5 0 12 -7 15 -16z m-339
-14 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-7
-83 c8 -28 8 -37 0 -35 -6 2 -13 21 -15 43 -3 46 1 43 15 -8z m606 2 c-3 -5
-10 -7 -15 -3 -5 3 -7 10 -3 15 3 5 10 7 15 3 5 -3 7 -10 3 -15z m-50 -50 c-8
-14 -24 -10 -24 6 0 9 6 12 15 9 8 -4 12 -10 9 -15z m-474 -12 c49 -24 57 -41
59 -129 1 -33 5 -47 14 -45 7 1 13 -12 15 -33 3 -25 14 -44 39 -67 27 -25 34
-38 29 -55 -3 -13 -6 -67 -6 -120 0 -75 -3 -96 -13 -92 -9 3 -13 36 -16 112
-1 58 -5 110 -7 114 -3 5 2 8 11 8 10 0 3 13 -23 38 -34 32 -41 47 -52 107 -8
39 -15 79 -16 90 -1 11 -3 21 -4 23 -2 1 -3 7 -4 13 0 6 -21 22 -46 35 -57 29
-40 30 20 1z m380 9 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6
0 10 -2 10 -4z m345 -6 c3 -5 -1 -10 -10 -10 -9 0 -13 5 -10 10 3 6 8 10 10
10 2 0 7 -4 10 -10z m75 -20 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10
4 10 6 0 11 -4 11 -10z m2249 -51 c-7 -14 -14 -18 -21 -11 -13 13 -2 32 18 32
12 0 13 -4 3 -21z m-249 -9 c13 -8 13 -10 -2 -10 -9 0 -20 5 -23 10 -8 13 5
13 25 0z m808 -147 c-2 -156 -2 -156 -5 -33 -3 138 -13 169 -52 171 l-26 1 25
8 c62 20 60 25 58 -147z m-703 138 c3 -5 1 -12 -5 -16 -5 -3 -10 1 -10 9 0 18
6 21 15 7z m572 3 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z
m-314 -11 c-31 -3 -44 -9 -48 -24 -8 -24 -25 -25 -25 -1 0 28 9 32 64 30 50
-1 50 -2 9 -5z m-2433 -53 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10
10 10 6 0 10 -4 10 -10z m-486 -8 c-6 -4 -14 -14 -17 -22 -4 -10 -6 -8 -6 8
-1 15 5 22 17 22 10 0 13 -3 6 -8z m323 -34 c-3 -7 -5 -2 -5 12 0 14 2 19 5
13 2 -7 2 -19 0 -25z m503 12 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1
10 4 10 6 0 11 -4 11 -10z m1550 -25 c0 -8 -4 -15 -10 -15 -5 0 -10 7 -10 15
0 8 5 15 10 15 6 0 10 -7 10 -15z m100 -5 c0 -5 -4 -10 -10 -10 -5 0 -10 5
-10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m-1915 -10 c3 -5 1 -10 -4 -10 -6 0
-11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m2955 -15 c-7 -8 -18 -15 -24
-15 -6 0 -2 7 8 15 25 19 32 19 16 0z m-2595 -5 c-3 -5 -11 -10 -16 -10 -6 0
-7 5 -4 10 3 6 11 10 16 10 6 0 7 -4 4 -10z m2298 3 c-7 -2 -19 -2 -25 0 -7 3
-2 5 12 5 14 0 19 -2 13 -5z m-165 -33 c11 -18 10 -20 -10 -20 -13 0 -33 -3
-45 -6 -18 -5 -23 -2 -24 12 0 15 -2 15 -6 4 -3 -8 -11 -18 -17 -22 -16 -11
-56 -10 -56 2 0 6 10 10 23 11 21 1 21 1 -3 8 -21 6 -16 9 29 15 41 6 55 5 62
-5 7 -11 9 -10 9 4 0 23 22 22 38 -3z m150 3 c-10 -2 -28 -2 -40 0 -13 2 -5 4
17 4 22 1 32 -1 23 -4z m282 -8 c-7 -9 -15 -13 -17 -11 -7 7 7 26 19 26 6 0 6
-6 -2 -15z m-910 -25 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2
0 4 -4 4 -10z m610 -32 c0 -23 -3 -29 -9 -19 -7 11 -9 11 -14 0 -3 -8 -6 1 -6
19 -1 22 4 32 14 32 10 0 15 -10 15 -32z m-3013 16 c-3 -3 -12 -4 -19 -1 -8 3
-5 6 6 6 11 1 17 -2 13 -5z m56 -1 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5 17 0
24 -2 18 -5z m2872 -3 c-3 -5 -2 -10 4 -10 5 0 12 6 14 13 7 17 27 -11 20 -29
-7 -19 -33 -26 -33 -8 0 13 -2 13 -16 -1 -14 -13 -19 -14 -25 -3 -7 10 -11 10
-21 0 -21 -21 -40 -15 -32 11 9 31 14 34 24 17 6 -9 10 -10 10 -3 0 10 11 15
53 22 5 0 5 -3 2 -9z m372 -42 c-2 -13 -4 -5 -4 17 -1 22 1 32 4 23 2 -10 2
-28 0 -40z m-3340 26 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z
m1853 -4 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10
-10z m1008 -13 c-3 -19 -10 -22 -50 -23 -39 -1 -46 1 -45 16 1 10 4 17 7 15 3
-2 12 0 19 4 7 4 26 8 42 9 26 1 30 -3 27 -21z m-578 3 c0 -5 -4 -10 -10 -10
-5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m-2377 -7 c-7 -2 -19 -2
-25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m50 0 c-7 -2 -19 -2 -25 0 -7 3 -2 5
12 5 14 0 19 -2 13 -5z m54 1 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2
13 -5z m943 -2 c0 -13 -12 -22 -22 -16 -10 6 -1 24 13 24 5 0 9 -4 9 -8z
m1590 -2 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10
-10z m-2157 -7 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m1537
-3 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z
m-1953 -6 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m90 0 c-3 -3
-12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m2013 -4 c0 -5 -5 -10 -11 -10
-5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m-1160 -20 c0 -5 -2 -10 -4
-10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m2200 -20 c-14 -4
-38 -8 -55 -8 -25 -1 -27 1 -10 8 11 5 36 8 55 8 32 0 33 -1 10 -8z m-3050
-10 c0 -12 -98 -12 -155 -1 -32 7 -21 9 58 10 59 1 97 -3 97 -9z m1950 -4 c0
-3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m998
-17 c2 -11 -8 -15 -35 -17 l-38 -2 25 20 c27 21 43 21 48 -1z m62 1 c0 -5 -8
-10 -17 -10 -15 0 -16 2 -3 10 19 12 20 12 20 0z m225 0 c3 -6 -1 -7 -9 -4
-18 7 -21 14 -7 14 6 0 13 -4 16 -10z m61 -21 c-4 -29 -26 -65 -26 -44 0 12
23 75 28 75 2 0 1 -14 -2 -31z m-2638 3 c2 -7 -3 -12 -12 -12 -9 0 -16 7 -16
16 0 17 22 14 28 -4z m2478 -87 c-3 -8 -37 -13 -116 -14 -61 -1 -166 -6 -233
-11 -67 -5 -125 -10 -129 -10 -5 0 -8 16 -8 35 0 42 6 43 40 10 l27 -26 146 7
c124 6 144 9 129 20 -15 12 -13 13 18 14 26 0 31 -3 20 -10 -11 -7 -4 -10 25
-10 28 0 36 3 26 9 -12 8 -12 12 -2 25 7 9 17 13 22 10 5 -3 9 2 9 11 0 9 5
13 10 10 6 -3 11 2 12 12 1 10 3 -2 5 -26 3 -24 2 -49 -1 -56z m-321 75 c-3
-5 -14 -10 -23 -10 -15 0 -15 2 -2 10 20 13 33 13 25 0z m-67 -55 c0 -14 -4
-25 -9 -25 -10 0 -11 12 -3 34 9 22 12 20 12 -9z m-288 5 c0 -5 -4 -10 -10
-10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m-2476 -15 c-4 -9 -1
-15 7 -15 8 0 9 -3 4 -8 -6 -4 -53 -5 -105 -2 -57 3 -90 8 -82 13 7 5 19 6 27
3 8 -3 15 -1 15 4 0 5 -12 11 -27 13 -16 2 16 5 69 6 83 1 97 -1 92 -14z m136
5 c0 -10 -105 -8 -116 3 -4 4 20 7 54 7 34 0 62 -4 62 -10z m2190 -4 c0 -3 -4
-8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m-1715 -25 c7
-12 -12 -24 -25 -16 -11 7 -4 25 10 25 5 0 11 -4 15 -9z m1295 -1 c0 -5 -5
-10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m-995 -30 c17
-34 18 -40 6 -40 -5 0 -11 8 -14 18 -2 9 -8 25 -12 35 -12 28 3 19 20 -13z
m940 16 c8 -7 11 -16 8 -19 -5 -6 -33 17 -33 27 0 10 11 7 25 -8z m1425 4 c0
-5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-3360
-18 c0 -10 -9 -13 -35 -10 -19 2 -35 0 -35 -4 0 -4 63 -8 140 -8 87 0 140 -4
140 -10 0 -6 -58 -10 -155 -10 -97 0 -155 4 -155 10 0 6 6 10 13 11 10 0 10 2
0 6 -7 2 -13 11 -13 19 0 11 12 14 50 13 36 -2 50 -6 50 -17z m195 -2 c-3 -5
-44 -9 -90 -9 -75 1 -95 6 -81 20 8 8 176 -3 171 -11z m325 4 c0 -8 -4 -12
-10 -9 -5 3 -10 10 -10 16 0 5 5 9 10 9 6 0 10 -7 10 -16z m2643 -9 c-3 -9 -8
-14 -10 -11 -3 3 -2 9 2 15 9 16 15 13 8 -4z m174 -42 c-15 -21 -36 -44 -47
-51 -27 -17 -18 -30 17 -26 17 2 20 1 8 -3 -65 -18 -125 -46 -125 -58 0 -8 8
-11 23 -8 13 3 18 1 11 -4 -14 -11 -25 -53 -13 -53 15 0 10 -27 -6 -34 -17 -6
-22 -111 -5 -121 14 -9 13 -68 -2 -83 -9 -9 -7 -12 10 -12 25 0 31 -33 10 -54
-18 -17 -57 -26 -64 -15 -3 5 -10 7 -15 4 -5 -4 -9 8 -9 25 0 23 5 33 20 37
16 4 20 14 20 49 0 32 -4 44 -15 44 -11 0 -15 -11 -15 -37 0 -22 -4 -33 -8
-26 -6 9 -12 7 -25 -7 -21 -25 -21 -30 -2 -30 12 0 14 -4 7 -16 -5 -9 -7 -25
-5 -35 3 -11 1 -19 -5 -19 -6 0 -13 12 -15 28 -4 25 -4 25 -6 -5 -1 -22 -6
-33 -16 -33 -13 0 -15 7 -9 38 4 20 12 40 18 44 15 10 -16 20 -51 16 -28 -3
-28 -4 -27 -71 1 -80 13 -75 -166 -79 -114 -3 -128 -6 -148 -26 -27 -27 -42
-28 -42 -2 0 18 -7 20 -66 20 -42 0 -70 -5 -79 -14 -8 -7 -12 -16 -9 -19 3 -3
1 -8 -5 -12 -7 -3 -11 2 -11 14 0 11 -4 22 -9 26 -6 3 -8 -4 -6 -15 2 -12 -1
-20 -9 -20 -31 0 -38 29 -37 150 1 74 -3 120 -9 120 -16 0 -12 30 7 48 9 9 18
16 20 15 10 -8 1 15 -12 30 -8 9 -11 17 -6 17 5 0 17 -12 26 -27 17 -26 19
-26 26 -8 4 11 5 68 2 126 l-5 106 225 7 c123 4 239 11 258 16 18 6 42 7 52 4
16 -5 18 -13 12 -69 -4 -34 -8 -93 -9 -130 -2 -58 1 -69 16 -73 10 -2 18 -9
18 -14 0 -6 7 -7 16 -4 8 3 12 2 9 -3 -3 -5 -1 -12 5 -16 5 -3 10 -1 10 4 0 6
7 11 15 11 9 0 15 9 15 24 0 28 26 41 48 24 12 -10 14 -10 8 0 -4 6 -2 12 3
12 7 0 11 30 11 79 l0 78 93 81 c50 44 94 78 96 76 2 -2 -8 -21 -22 -41z
m-949 20 c2 -8 -5 -13 -17 -13 -12 0 -21 6 -21 16 0 18 31 15 38 -3z m-2118
-3 c0 -5 -9 -10 -19 -10 -11 0 -23 5 -26 10 -4 6 5 10 19 10 14 0 26 -4 26
-10z m40 0 c0 -5 -7 -10 -15 -10 -8 0 -15 5 -15 10 0 6 7 10 15 10 8 0 15 -4
15 -10z m90 1 c0 -5 -18 -9 -40 -9 -22 0 -40 3 -40 9 0 5 18 9 40 9 22 0 40
-4 40 -9z m2730 -5 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6
0 10 -2 10 -4z m-2980 -30 c0 -11 -14 -13 -57 -11 -32 2 -88 3 -125 4 -38 1
-68 5 -68 11 0 6 48 10 125 10 100 0 125 -3 125 -14z m920 0 c0 -20 -19 -31
-32 -18 -6 6 -7 15 -4 21 10 16 36 13 36 -3z m880 -6 c0 -5 -2 -10 -4 -10 -3
0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-2103 -16 c-3 -3 -12 -4
-19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m846 -23 c6 -26 -1 -33 -24 -20 -10 5
-16 16 -13 24 9 21 31 19 37 -4z m-903 -13 c0 -18 -2 -20 -9 -8 -6 8 -7 18 -5
22 9 14 14 9 14 -14z m30 3 c0 -6 -4 -13 -10 -16 -5 -3 -10 1 -10 9 0 9 5 16
10 16 6 0 10 -4 10 -9z m3553 2 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19
-2 13 -5z m-3522 -26 c-10 -9 -11 -8 -5 6 3 10 9 15 12 12 3 -3 0 -11 -7 -18z
m609 3 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10
-10z m298 -31 c-2 -6 -8 -10 -13 -10 -5 0 -11 4 -13 10 -2 6 4 11 13 11 9 0
15 -5 13 -11z m1156 3 c3 -5 -1 -9 -9 -9 -8 0 -15 4 -15 9 0 4 4 8 9 8 6 0 12
-4 15 -8z m337 -55 c-1 -12 -15 -9 -19 4 -3 6 1 10 8 8 6 -3 11 -8 11 -12z
m89 -11 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10
-4z m40 -75 c0 -6 -4 -13 -10 -16 -5 -3 -10 1 -10 9 0 9 5 16 10 16 6 0 10 -4
10 -9z m-1930 -275 c0 -2 -9 -6 -20 -9 -11 -3 -20 -1 -20 4 0 5 9 9 20 9 11 0
20 -2 20 -4z m1430 -20 c0 -11 -19 -15 -25 -6 -3 5 1 10 9 10 9 0 16 -2 16 -4z
m-1450 -76 c0 10 3 11 11 3 6 -6 9 -36 7 -72 -2 -35 1 -63 7 -65 6 -3 -3 -5
-20 -5 l-30 -1 3 77 c3 50 7 72 13 62 7 -12 9 -12 9 1z m2640 -39 c0 -6 -4
-13 -10 -16 -5 -3 -10 1 -10 9 0 9 5 16 10 16 6 0 10 -4 10 -9z m-1440 -29 c0
-15 -2 -15 -10 -2 -13 20 -13 33 0 25 6 -3 10 -14 10 -23z m1064 1 c-22 -91
-101 -241 -162 -305 -23 -25 -33 -28 -89 -28 -49 0 -63 -3 -63 -15 0 -8 -4
-15 -10 -15 -5 0 -10 5 -10 10 0 15 -50 12 -51 -2 0 -10 -2 -10 -6 0 -2 6 -14
12 -25 12 -15 0 -18 -4 -13 -22 4 -13 12 -27 18 -33 7 -7 8 -6 4 1 -4 7 6 14
25 18 40 8 45 2 20 -24 -17 -18 -23 -19 -46 -9 -20 10 -29 10 -38 1 -7 -7 -17
-12 -23 -12 -21 0 -55 41 -55 65 0 20 8 26 47 37 36 10 49 19 54 38 5 16 7 19
8 8 1 -10 5 -18 10 -18 14 0 76 47 74 56 -1 6 13 10 30 10 21 0 53 14 90 38
71 47 200 175 193 192 -5 13 2 24 16 24 5 0 5 -12 2 -27z m496 -3 c0 -11 -4
-20 -10 -20 -5 0 -10 9 -10 20 0 11 5 20 10 20 6 0 10 -9 10 -20z m-3220 -9
c0 -11 -4 -22 -8 -25 -14 -9 -35 12 -29 28 9 23 37 20 37 -3z m1905 -1 c3 -5
-1 -10 -10 -10 -9 0 -13 5 -10 10 3 6 8 10 10 10 2 0 7 -4 10 -10z m-1970 -20
c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m2022
-16 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-2027 -14 c0 -5
-7 -10 -15 -10 -8 0 -15 5 -15 10 0 6 7 10 15 10 8 0 15 -4 15 -10z m80 0 c0
-5 -7 -10 -16 -10 -10 0 -14 -5 -10 -16 3 -8 2 -12 -4 -9 -19 12 -11 45 10 45
11 0 20 -4 20 -10z m1702 -22 c-7 -7 -12 -8 -12 -2 0 6 3 14 7 17 3 4 9 5 12
2 2 -3 -1 -11 -7 -17z m-1207 2 c-3 -5 1 -10 9 -10 11 0 16 -9 16 -26 0 -24
-2 -25 -32 -19 -18 4 -39 13 -47 21 -13 11 -12 14 5 19 10 4 26 10 34 15 20
12 22 12 15 0z m638 3 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12 5 17 0 24 -2 18 -5z
m504 -50 c-3 -10 -5 -4 -5 12 0 17 2 24 5 18 2 -7 2 -21 0 -30z m1449 11 c-6
-31 -16 -45 -16 -21 0 18 10 47 16 47 3 0 2 -12 0 -26z m-3102 -15 c-3 -5 -10
-7 -15 -3 -5 3 -7 10 -3 15 3 5 10 7 15 3 5 -3 7 -10 3 -15z m1256 -19 c0 -18
-6 -20 -57 -18 l-58 1 55 7 c54 7 53 7 -30 10 l-85 4 75 6 c41 4 81 7 88 8 6
1 12 -7 12 -18z m240 16 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10
11 6 0 10 -2 10 -4z m621 -45 c-25 -66 -99 -170 -125 -176 -31 -7 -166 -11
-166 -5 0 3 29 18 63 33 35 15 76 39 92 52 l30 25 -74 -7 c-58 -5 -72 -3 -66
6 14 24 66 39 99 30 59 -17 74 -12 113 41 20 28 41 50 45 50 4 0 0 -22 -11
-49z m-576 11 c-6 -7 -35 -12 -35 -7 0 2 3 11 6 19 5 13 9 14 20 5 8 -7 12
-14 9 -17z m-1565 14 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11
6 0 10 -2 10 -4z m474 -11 c3 -9 0 -15 -8 -15 -7 0 -28 -3 -45 -6 -27 -6 -31
-4 -31 15 0 18 6 21 39 21 25 0 41 -5 45 -15z m79 0 c4 -9 -6 -23 -26 -37 -29
-20 -30 -20 -14 -2 9 11 17 28 17 37 0 21 16 22 23 2z m1330 -2 c-7 -2 -19 -2
-25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m457 -3 c21 -7 18 -8 -18 -9 -26 -1
-41 3 -37 9 7 11 19 11 55 0z m-2113 -61 c4 -1 10 -3 12 -5 2 -2 -12 -4 -32
-4 -23 0 -37 5 -37 13 0 6 -3 23 -7 37 -6 24 -5 23 25 -8 17 -18 35 -33 39
-33z m-222 41 c3 -5 2 -10 -4 -10 -5 0 -13 5 -16 10 -3 6 -2 10 4 10 5 0 13
-4 16 -10z m1275 2 c0 -4 -19 -6 -42 -4 -71 5 -77 10 -15 11 31 0 57 -2 57 -7z
m617 -18 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m410 0 c-3 -3
-12 -4 -19 -1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-1014 -10 c42 -7 50 -21 12
-21 -14 0 -25 3 -25 8 0 4 -26 10 -57 12 -51 3 -53 3 -13 5 25 1 62 -1 83 -4z
m384 -51 c-3 -10 -5 -2 -5 17 0 19 2 27 5 18 2 -10 2 -26 0 -35z m-542 7 c-27
-12 -35 -12 -35 0 0 6 12 10 28 9 24 0 25 -1 7 -9z m185 -5 c0 -8 -7 -15 -15
-15 -8 0 -15 7 -15 15 0 8 7 15 15 15 8 0 15 -7 15 -15z m984 0 c-4 -8 -8 -15
-10 -15 -2 0 -4 7 -4 15 0 8 4 15 10 15 5 0 7 -7 4 -15z m-1074 -5 c-20 -13
-50 -13 -50 0 0 6 15 10 33 10 24 0 28 -3 17 -10z m335 -75 c11 0 25 3 30 6
19 12 75 2 95 -16 16 -14 17 -20 8 -27 -14 -8 17 -13 62 -8 64 6 75 4 78 -11
4 -21 -56 -32 -122 -23 -31 5 -46 3 -46 -5 0 -7 21 -11 55 -11 59 0 72 -14 29
-30 -23 -9 -26 -15 -20 -40 3 -17 1 -30 -4 -30 -6 0 -10 -10 -10 -22 0 -17 -3
-19 -12 -10 -26 26 -30 10 -4 -17 21 -22 26 -33 18 -46 -6 -11 -12 -14 -16 -7
-4 6 -13 9 -21 6 -21 -8 -8 -24 18 -24 19 0 17 -3 -12 -21 -29 -18 -44 -20
-115 -14 -44 3 -108 8 -141 9 -79 5 -77 5 -70 16 3 5 12 7 19 4 7 -3 18 1 25
9 21 26 -29 30 -59 4 l-25 -22 21 25 c29 34 40 55 26 46 -8 -4 -12 0 -12 11 0
11 -5 24 -12 31 -8 8 -8 12 -1 12 6 0 10 17 9 39 0 22 -3 39 -6 39 -24 -2 -32
4 -27 21 4 16 -2 20 -39 26 -29 4 -48 13 -55 26 -14 27 -8 32 27 18 58 -22 74
-21 75 3 1 17 2 19 6 6 5 -20 33 -25 33 -7 0 6 6 9 13 6 8 -3 20 3 27 14 10
13 17 15 27 7 7 -6 13 -9 14 -7 0 2 2 12 4 22 5 25 15 34 15 14 0 -47 59 -22
62 26 1 30 1 29 7 -8 5 -31 10 -40 26 -40z m-300 44 c5 -6 -10 -9 -44 -8 -28
2 -51 6 -51 11 0 12 88 10 95 -3z m135 -24 c-7 -9 -15 -13 -17 -11 -6 6 20 36
26 30 2 -2 -2 -10 -9 -19z m770 -45 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3
6 -1 10 4 10 6 0 11 -4 11 -10z m351 -21 c-25 -20 -72 -23 -78 -3 -2 6 10 8
32 6 21 -3 35 0 35 7 0 6 8 11 18 11 14 -1 13 -4 -7 -21z m-600 -31 c30 0 39
-4 35 -14 -3 -8 -1 -14 5 -14 6 0 7 -5 4 -10 -4 -6 -12 -4 -21 5 -17 17 -34
12 -34 -10 0 -22 -29 -26 -40 -5 -13 24 -13 63 0 55 6 -3 28 -7 51 -7z m-901
-18 c0 -5 -12 -10 -27 -9 -25 0 -26 1 -8 9 27 12 35 12 35 0z m818 -2 c-6 -17
-36 -34 -45 -24 -4 4 1 14 11 22 24 17 39 18 34 2z m259 6 c-3 -3 -12 -4 -19
-1 -8 3 -5 6 6 6 11 1 17 -2 13 -5z m-997 -14 c0 -5 -7 -7 -15 -4 -8 4 -15 8
-15 10 0 2 7 4 15 4 8 0 15 -4 15 -10z m194 4 c25 -10 20 -33 -6 -29 -26 5
-42 -3 -51 -25 -3 -8 -6 2 -6 23 -1 33 2 37 23 37 13 0 31 -3 40 -6z m893 -16
c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m191 2 c2 -10 -6 -16
-23 -18 -19 -1 -25 3 -25 19 0 15 5 20 22 17 13 -2 24 -10 26 -18z m-298 -10
c0 -11 -4 -20 -10 -20 -5 0 -10 9 -10 20 0 11 5 20 10 20 6 0 10 -9 10 -20z
m-1394 -27 c-10 -10 -19 5 -10 18 6 11 8 11 12 0 2 -7 1 -15 -2 -18z m1641 10
c7 -6 12 -27 12 -45 -1 -27 -3 -29 -6 -8 -3 14 -14 35 -26 48 -23 25 -5 29 20
5z m-1587 -1 c0 -5 -7 -9 -15 -9 -8 0 -15 4 -15 9 0 4 7 8 15 8 8 0 15 -4 15
-8z m195 -21 c-3 -6 -11 -11 -17 -11 -6 0 -6 6 2 15 14 17 26 13 15 -4z m-835
-11 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m50
0 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z
m700 1 c0 -9 -24 -21 -41 -21 -5 0 -9 7 -9 15 0 9 9 15 25 15 14 0 25 -4 25
-9z m1023 2 c-7 -2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m210 0 c-7
-2 -19 -2 -25 0 -7 3 -2 5 12 5 14 0 19 -2 13 -5z m-1329 -23 c-6 -6 -15 -5
-24 1 -13 9 -12 10 3 5 9 -3 17 0 17 6 0 6 3 8 7 5 4 -4 2 -12 -3 -17z m-94 0
c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m30
0 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z
m250 0 c0 -5 -7 -10 -16 -10 -8 0 -12 5 -9 10 3 6 10 10 16 10 5 0 9 -4 9 -10z
m1365 0 c-3 -5 -14 -10 -23 -10 -15 0 -15 2 -2 10 20 13 33 13 25 0z m-1548
-42 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m90 8 c0 -8 -11 -16
-24 -19 -27 -5 -30 8 -5 22 23 14 29 13 29 -3z m1627 -11 c-4 -8 -10 -12 -15
-9 -14 8 -10 24 6 24 9 0 12 -6 9 -15z m-1824 -56 c0 -6 -4 -7 -10 -4 -5 3
-10 11 -10 16 0 6 5 7 10 4 6 -3 10 -11 10 -16z m90 7 c0 -8 -9 -12 -22 -11
-33 4 -34 4 -18 15 22 14 40 12 40 -4z m110 5 c0 -14 -60 -19 -77 -6 -14 10
-9 13 30 13 26 1 47 -3 47 -7z m1610 4 c0 -11 -42 -25 -53 -18 -8 5 -2 10 18
14 17 4 31 7 33 8 1 0 2 -1 2 -4z m-1142 -69 c-7 -8 -15 -12 -17 -11 -5 6 10
25 20 25 5 0 4 -6 -3 -14z m209 -32 c-3 -3 -12 -4 -19 -1 -8 3 -5 6 6 6 11 1
17 -2 13 -5z"/>
<path d="M3944 6469 c-4 -13 -8 -27 -9 -31 0 -3 -3 -10 -7 -14 -17 -17 -7 -26
11 -10 23 21 32 49 21 66 -5 9 -10 5 -16 -11z"/>
<path d="M3835 6360 c-3 -5 -12 -7 -19 -4 -14 6 -176 -226 -176 -253 0 -11 12
-8 50 13 39 21 60 43 101 107 43 67 50 84 40 99 -6 10 -7 18 -2 18 5 0 11 7
15 15 6 17 0 20 -9 5z"/>
<path d="M3938 6348 c-20 -27 -62 -83 -102 -135 -50 -64 -89 -102 -98 -97 -5
3 -12 -4 -15 -16 -3 -12 -11 -19 -18 -16 -13 4 -30 -20 -27 -37 1 -4 -3 -6
-10 -5 -6 2 -21 -11 -32 -29 -12 -18 -26 -30 -33 -28 -6 2 -17 -3 -23 -11 -14
-15 -40 -19 -40 -5 0 4 9 20 20 34 13 17 17 28 10 32 -7 4 -8 11 -2 18 5 7 13
22 16 35 6 17 3 22 -12 22 -11 0 -25 -7 -32 -15 -25 -30 -41 -18 -34 25 8 48
-5 52 -30 8 -11 -18 -36 -59 -57 -90 -38 -56 -38 -57 -13 -47 l27 9 -24 -26
c-63 -70 -69 -74 -91 -70 -19 4 -34 -8 -80 -62 -32 -37 -71 -88 -87 -114 -41
-64 -92 -119 -167 -179 -35 -28 -64 -58 -64 -67 0 -10 12 -28 25 -41 14 -13
25 -27 25 -31 0 -14 32 -21 46 -9 11 9 19 7 34 -11 10 -12 21 -27 23 -33 2 -7
9 -7 21 0 22 12 58 5 49 -10 -4 -6 2 -8 17 -4 l22 6 -23 -25 c-13 -14 -19 -24
-14 -22 6 2 20 -6 32 -17 21 -19 185 -85 214 -85 8 0 23 -7 33 -15 10 -8 23
-12 29 -8 6 3 7 2 4 -4 -6 -9 94 -73 116 -73 7 0 21 -7 31 -15 11 -8 30 -15
43 -15 13 0 23 -4 23 -8 0 -5 19 -15 43 -22 23 -7 56 -19 74 -26 38 -17 63
-18 63 -2 0 9 3 9 12 0 26 -26 58 -14 86 35 39 67 54 80 105 87 50 8 137 -11
115 -25 -16 -10 8 -40 27 -33 10 4 12 0 8 -15 -3 -14 0 -23 11 -27 9 -3 13
-11 10 -16 -6 -9 73 -5 141 6 11 2 24 4 28 5 5 0 5 10 2 21 -5 16 -2 20 17 18
18 -2 22 1 20 17 -2 18 -2 18 8 3 14 -22 38 -23 92 -1 88 34 212 133 168 133
-5 0 -10 5 -10 10 0 6 11 8 25 4 16 -4 25 -2 25 6 0 6 10 10 23 8 14 -2 26 4
33 17 12 22 8 45 -8 45 -6 0 -5 -8 3 -17 12 -17 12 -17 -5 -1 -19 17 -15 55 4
43 5 -3 11 -1 11 4 1 6 2 17 3 24 1 6 -2 18 -7 24 -5 7 -7 22 -4 33 3 10 1 18
-3 17 -4 -1 -16 7 -26 19 -23 25 -63 48 -72 40 -3 -3 5 -17 18 -31 13 -14 18
-25 11 -25 -7 0 -9 -6 -6 -12 4 -7 -1 -4 -9 6 -9 11 -16 16 -16 11 0 -4 -9 0
-20 10 -11 10 -17 22 -14 27 3 4 2 8 -3 7 -16 -4 -43 13 -43 28 0 8 -4 12 -8
9 -5 -3 -6 8 -4 25 l4 29 33 -20 c40 -25 45 -25 45 -1 0 11 -22 38 -50 62 -51
43 -61 63 -35 72 15 6 95 -77 95 -99 0 -6 28 -38 63 -71 34 -33 61 -66 59 -72
-2 -7 2 -11 9 -10 18 3 69 -21 69 -33 0 -5 -7 -11 -15 -14 -23 -9 -18 -29 10
-42 24 -11 25 -11 14 9 -11 21 -10 21 12 5 29 -20 39 -20 39 -1 0 8 -8 15 -17
16 -11 0 -13 2 -5 6 7 3 28 -7 47 -21 35 -27 69 -34 80 -16 4 6 10 8 13 6 4
-2 12 6 18 19 14 28 -6 65 -34 65 -18 1 -58 47 -49 57 3 3 16 -2 29 -11 30
-21 38 -20 38 5 0 27 -14 53 -67 120 -55 70 -97 219 -62 219 8 0 8 4 2 13 -6
6 -16 29 -23 50 -11 37 -13 38 -31 21 -10 -9 -21 -26 -25 -38 -9 -29 -43 -76
-55 -76 -6 0 -2 12 9 28 10 15 22 35 25 45 6 15 4 16 -13 7 -10 -6 -23 -17
-28 -25 -4 -9 -24 -23 -43 -33 -27 -13 -34 -22 -32 -43 2 -26 1 -27 -27 -13
-15 8 -44 35 -65 59 -40 50 -55 56 -55 24 0 -13 30 -55 73 -103 40 -44 77 -87
81 -93 15 -26 -11 -11 -73 42 -36 30 -66 53 -69 51 -2 -3 -13 5 -25 17 -13 13
-22 17 -25 9 -7 -22 -31 -12 -47 18 -19 36 -59 64 -81 56 -14 -6 -45 13 -94
58 -8 7 -38 16 -67 20 -62 8 -139 40 -147 62 -3 8 -9 13 -13 11 -5 -3 -8 8 -8
25 0 23 -9 38 -37 61 -46 37 -60 29 -28 -16 l23 -32 -32 29 c-38 36 -76 112
-73 146 2 14 18 39 36 56 32 30 32 32 15 53 -9 11 -22 21 -28 21 -6 0 -8 7 -5
15 9 21 1 19 -18 -7z m-78 -267 c-17 -28 -36 -51 -41 -51 -5 0 -9 -7 -9 -17 0
-9 -3 -13 -7 -10 -3 4 -17 0 -30 -8 -13 -9 -23 -11 -23 -5 0 6 7 13 15 16 8 3
20 21 27 39 6 19 15 32 20 29 4 -3 8 0 8 7 0 7 12 26 27 41 43 45 51 18 13
-41z m112 -96 c54 -54 83 -70 72 -40 -10 26 13 16 41 -17 18 -21 23 -33 15
-38 -13 -8 25 -40 48 -40 7 0 24 -7 37 -16 34 -22 31 -11 -7 37 -39 49 -33 58
13 19 19 -16 39 -29 44 -30 6 0 37 -21 69 -45 33 -25 63 -45 67 -45 5 0 14 12
22 26 12 22 15 24 26 10 14 -17 15 -33 10 -112 -4 -62 -22 -66 -61 -12 -25 33
-68 67 -68 53 0 -3 7 -21 15 -41 10 -24 11 -33 2 -28 -11 7 18 -33 34 -46 3
-3 6 -13 6 -22 0 -14 -6 -16 -25 -11 -16 4 -23 2 -19 -4 5 -7 -5 -8 -30 -2
-26 5 -40 4 -45 -4 -5 -8 -8 -4 -8 10 0 23 -52 68 -110 96 -50 23 -62 5 -22
-34 24 -24 30 -35 22 -45 -6 -7 -10 -21 -8 -30 4 -25 -29 -30 -53 -8 -17 16
-19 16 -19 1 0 -10 -5 -17 -11 -17 -6 0 -8 8 -4 19 4 13 -5 27 -30 49 -39 35
-71 34 -58 -2 4 -11 7 -31 6 -44 -1 -15 4 -22 11 -19 7 3 13 -1 13 -9 0 -7 -5
-10 -10 -7 -5 3 -13 0 -17 -6 -5 -9 -20 -5 -56 14 -32 17 -50 22 -53 14 -4
-13 -131 110 -131 128 0 7 13 19 29 28 16 8 31 20 34 27 3 10 13 8 41 -6 51
-27 56 -12 11 34 -55 56 -36 62 27 8 77 -65 83 -66 53 -12 -25 46 -25 47 -3
23 26 -29 155 -92 163 -79 5 9 -84 70 -103 70 -7 0 -12 4 -12 10 0 5 -15 16
-33 24 -45 18 -107 74 -107 95 0 10 -7 26 -15 37 -16 22 -20 48 -5 39 6 -3 10
-1 10 6 0 10 3 10 12 1 21 -21 59 -13 86 18 15 17 27 30 28 30 0 0 26 -25 56
-55z m-395 -49 c-7 -13 -15 -22 -19 -20 -3 2 -9 0 -13 -6 -4 -6 -11 -8 -16 -5
-5 4 -9 1 -9 -4 0 -6 -6 -11 -13 -11 -7 0 -19 -6 -25 -12 -17 -17 -112 -21
-106 -5 2 7 27 27 54 45 37 24 50 28 50 17 0 -14 3 -14 28 -2 15 8 35 13 44
12 10 -2 20 1 24 6 11 18 12 8 1 -15z m163 -6 c0 -5 -5 -10 -11 -10 -5 0 -7 5
-4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m390 -390 c0 -5 -4 -10 -10 -10 -5 0
-10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m-1065 -89 c10 -17 -12 -21
-25 -6 -10 12 -10 15 3 15 9 0 18 -4 22 -9z m-60 -39 c-8 -8 -25 10 -19 20 4
6 9 5 15 -3 4 -7 6 -15 4 -17z m207 -37 c-4 -26 -22 -35 -22 -12 0 10 18 37
26 37 1 0 -1 -11 -4 -25z m352 -56 c-3 -5 -10 -7 -15 -3 -5 3 -7 10 -3 15 3 5
10 7 15 3 5 -3 7 -10 3 -15z m42 -76 c-10 -10 -19 5 -10 18 6 11 8 11 12 0 2
-7 1 -15 -2 -18z m912 -35 c-6 -18 -28 -21 -28 -4 0 9 7 16 16 16 9 0 14 -5
12 -12z m-858 -118 c0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0
4 -4 4 -10z m54 2 c11 -18 -9 -29 -40 -23 -9 1 17 31 27 31 4 0 10 -4 13 -8z
m226 -2 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10
-10z m-170 -40 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11
-4 11 -10z m140 -30 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6
0 10 -4 10 -10z"/>
<path d="M3880 5892 c0 -11 89 -102 101 -102 5 0 3 14 -6 30 -9 17 -19 30 -23
30 -4 0 -20 11 -36 25 -31 27 -36 29 -36 17z"/>
<path d="M4240 5738 c0 -18 48 -64 57 -55 8 8 -27 59 -45 65 -7 2 -12 -3 -12
-10z"/>
<path d="M3730 5704 c0 -10 23 -26 77 -56 50 -27 62 -21 25 13 -18 16 -37 27
-42 24 -5 -3 -21 2 -35 11 -14 9 -25 12 -25 8z"/>
<path d="M4040 6220 c0 -5 13 -23 29 -39 28 -29 29 -29 27 -6 0 13 -4 21 -9
18 -4 -2 -10 2 -13 11 -6 17 -34 30 -34 16z"/>
<path d="M4758 6093 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M3595 6000 c4 -6 11 -8 16 -5 14 9 11 15 -7 15 -8 0 -12 -5 -9 -10z"/>
<path d="M4416 5915 c4 -8 10 -12 15 -9 11 6 2 24 -11 24 -5 0 -7 -7 -4 -15z"/>
<path d="M5258 5703 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
<path d="M5060 5641 c14 -28 13 -34 -7 -27 -26 11 26 -43 60 -60 37 -20 34 -4
-9 56 -35 49 -65 70 -44 31z"/>
<path d="M5130 5613 c0 -5 9 -19 20 -33 l20 -25 0 26 c0 15 -7 29 -16 33 -20
8 -24 8 -24 -1z"/>
<path d="M2880 5565 c0 -8 2 -15 4 -15 2 0 6 7 10 15 3 8 1 15 -4 15 -6 0 -10
-7 -10 -15z"/>
<path d="M5572 5493 c4 -24 21 -35 30 -20 14 21 8 37 -12 37 -14 0 -20 -6 -18
-17z"/>
<path d="M5080 5461 c0 -11 42 -43 48 -37 2 3 -1 14 -8 25 -11 21 -40 29 -40
12z"/>
<path d="M3020 5381 c0 -5 5 -13 10 -16 6 -3 10 -2 10 4 0 5 -4 13 -10 16 -5
3 -10 2 -10 -4z"/>
<path d="M4977 5216 c-4 -10 -1 -13 9 -9 15 6 19 23 5 23 -5 0 -11 -7 -14 -14z"/>
<path d="M3283 5183 c-13 -5 -6 -33 8 -33 12 0 55 -40 46 -41 -4 -1 -11 -2
-17 -3 -5 0 -10 -4 -10 -8 0 -5 0 -12 0 -18 0 -5 15 -10 34 -10 42 0 68 -9 60
-21 -3 -5 0 -9 6 -9 6 0 8 -4 5 -10 -3 -5 1 -10 9 -10 24 0 19 -16 -11 -39
-31 -25 -28 -30 20 -33 20 -2 37 -7 37 -13 1 -5 8 -1 18 10 12 15 30 20 65 21
46 0 47 0 23 -13 -14 -7 -30 -22 -36 -32 -11 -22 -3 -54 12 -45 5 3 15 -2 22
-12 15 -20 46 -13 46 10 0 10 6 13 16 9 11 -4 13 -13 9 -33 -3 -16 -1 -31 4
-35 6 -3 11 0 11 8 0 8 6 20 14 26 12 10 17 8 26 -9 9 -17 14 -19 26 -9 8 6
14 7 14 3 0 -5 -12 -16 -26 -25 -24 -15 -24 -16 -8 -30 16 -12 17 -12 11 3 -4
12 -2 15 8 11 8 -3 17 2 21 10 5 13 9 13 32 1 15 -8 34 -14 42 -14 11 0 11 -3
2 -12 -18 -18 -14 -38 8 -38 11 0 20 5 20 10 0 6 5 10 11 10 8 0 8 -4 -1 -15
-13 -15 -5 -39 11 -30 13 9 11 -9 -3 -23 -9 -9 -8 -12 5 -12 9 0 17 5 17 11 0
5 4 8 9 5 14 -9 19 15 10 54 -5 19 -9 60 -9 91 0 55 -1 57 -31 63 -17 3 -36 3
-42 -1 -5 -3 -7 -2 -4 4 7 10 -26 43 -62 62 -18 10 -20 9 -14 -6 6 -16 5 -16
-10 -4 -9 7 -15 17 -12 21 2 4 -16 8 -40 8 -24 1 -47 -2 -50 -8 -3 -5 1 -10
10 -10 9 0 14 -4 10 -9 -3 -5 2 -11 11 -13 15 -3 16 -4 2 -16 -13 -10 -19 -10
-34 5 -17 17 -18 17 -11 0 5 -14 2 -20 -15 -25 -21 -5 -21 -6 -2 -13 18 -6 18
-7 1 -14 -33 -14 -43 11 -19 45 12 16 22 34 22 39 0 6 7 14 16 19 21 12 9 33
-13 25 -13 -5 -15 -2 -10 11 4 9 3 15 -2 11 -5 -3 -21 -1 -35 5 -14 5 -26 6
-26 1 0 -5 11 -12 25 -15 13 -3 29 -15 35 -26 18 -34 -21 -25 -58 13 -39 40
-40 47 -4 47 20 0 23 3 12 9 -8 6 -18 7 -22 5 -4 -3 -8 0 -8 6 0 7 -7 9 -16 6
-8 -3 -12 -2 -9 4 3 5 -4 14 -15 20 -16 8 -20 8 -20 -4 0 -9 -7 -12 -19 -9
-11 3 -17 11 -14 18 8 21 -116 80 -144 68z m51 -22 c19 -11 36 -18 39 -15 2 2
10 -2 17 -11 25 -30 0 -27 -50 5 -46 29 -58 40 -45 40 2 0 20 -9 39 -19z m116
-115 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z
m41 -40 c-9 -11 -9 -15 1 -19 7 -2 0 -8 -15 -12 -38 -10 -45 0 -16 24 28 23
47 28 30 7z m213 -81 c-4 -8 -1 -15 6 -15 6 0 8 -4 5 -10 -9 -15 39 -12 54 3
11 10 12 8 7 -9 -7 -22 16 -40 35 -28 5 3 9 -2 9 -11 0 -12 -4 -14 -19 -5 -11
5 -27 7 -36 4 -10 -4 -15 -2 -13 7 2 8 -7 15 -22 17 -14 2 -30 10 -36 18 -10
12 -13 12 -23 0 -13 -16 -41 -11 -41 6 0 6 7 8 15 5 7 -3 24 3 37 13 28 24 29
24 22 5z m46 5 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11
-4 11 -10z m110 -134 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11
6 0 10 -2 10 -4z"/>
<path d="M4800 5157 c-39 -37 -94 -58 -84 -33 3 8 11 13 18 10 7 -3 21 4 31
16 11 12 13 20 6 20 -21 0 -76 -26 -90 -43 -12 -15 -11 -17 5 -17 17 0 17 -1
-1 -14 -14 -10 -24 -11 -36 -3 -12 7 -22 6 -40 -6 -19 -14 -20 -17 -6 -17 24
0 21 -17 -4 -23 -12 -3 -18 -10 -15 -16 11 -17 -13 -51 -37 -51 -22 -1 -22 -1
-2 -16 12 -9 30 -12 46 -9 17 4 32 1 42 -10 10 -9 18 -11 22 -5 4 6 11 8 16 5
5 -4 9 1 9 9 0 9 -8 16 -18 16 -10 0 -19 6 -19 14 0 8 6 12 14 9 19 -7 16 7
-4 23 -17 12 -17 13 -1 14 19 0 38 -28 31 -47 -2 -6 11 -18 28 -27 l33 -16
-24 25 -23 24 36 -4 c35 -5 36 -4 27 20 -11 29 3 34 19 8 9 -16 10 -16 11 4 0
19 5 22 37 19 25 -1 43 4 55 16 23 23 23 26 -7 26 -15 0 -27 -8 -30 -19 -5
-15 -10 -16 -32 -8 -15 5 -39 7 -55 4 -17 -4 -28 -2 -28 4 0 6 11 11 25 11 24
0 30 9 26 38 -1 6 3 12 9 12 14 0 60 46 60 60 0 17 -14 11 -50 -23z m-70 -126
c0 -5 -6 -11 -13 -14 -8 -3 -14 1 -14 9 0 8 6 14 14 14 7 0 13 -4 13 -9z"/>
<path d="M4935 5172 c-50 -6 -50 -20 -1 -27 26 -4 50 -5 53 -1 13 13 -23 32
-52 28z"/>
<path d="M3123 5154 c0 -8 6 -14 14 -14 7 0 13 4 13 9 0 5 15 5 36 1 25 -6 34
-5 31 3 -6 18 -94 18 -94 1z"/>
<path d="M4858 5111 c-10 -13 -10 -14 1 -4 11 9 17 8 28 -3 11 -11 19 -12 28
-4 10 8 16 7 22 -5 9 -15 11 -15 22 -1 15 18 9 22 -51 29 -27 3 -41 0 -50 -12z"/>
<path d="M3170 5111 c-18 -5 -21 -9 -12 -15 17 -10 82 2 82 14 0 11 -33 11
-70 1z"/>
<path d="M4795 5080 c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0
-8 -4 -11 -10z"/>
<path d="M3231 5063 c-12 -13 -11 -14 7 -8 17 5 21 3 16 -9 -3 -9 -1 -17 5
-17 35 -4 45 -3 48 7 3 9 -10 18 -57 41 -3 1 -11 -5 -19 -14z"/>
<path d="M3322 5048 c3 -7 14 -14 26 -16 18 -3 20 -8 15 -35 -5 -31 -5 -31 10
-12 11 13 16 15 17 6 0 -11 3 -11 16 0 14 12 14 14 0 25 -9 6 -16 16 -16 21 0
6 -10 13 -22 17 -36 9 -50 7 -46 -6z"/>
<path d="M4536 5033 c-32 -8 -48 -29 -32 -42 10 -8 19 -6 36 9 12 11 28 17 34
13 6 -4 5 1 -3 10 -7 9 -14 16 -15 16 0 -1 -10 -4 -20 -6z"/>
<path d="M3315 5011 c-3 -5 -1 -12 4 -15 5 -3 11 1 15 9 6 16 -9 21 -19 6z"/>
<path d="M4016 4994 c-8 -29 1 -64 15 -64 5 0 9 -6 9 -14 0 -7 6 -19 14 -25
11 -10 16 -8 21 9 3 11 10 18 15 15 4 -3 11 2 14 11 3 8 2 12 -4 9 -13 -8 -13
1 -1 24 6 10 7 28 4 40 -5 20 -7 21 -29 6 -22 -14 -25 -14 -30 0 -9 23 -21 18
-28 -11z"/>
<path d="M4443 5003 c-7 -2 -13 -11 -13 -18 0 -8 -7 -11 -20 -8 -22 6 -28 -12
-7 -20 6 -3 2 -6 -11 -6 -15 -1 -21 3 -16 11 5 8 0 9 -17 5 -13 -4 -31 -7 -39
-8 -10 0 -8 -3 5 -8 17 -8 14 -11 -22 -26 -24 -9 -43 -21 -43 -25 0 -5 -8 -6
-18 -3 -14 3 -18 -3 -20 -28 -3 -36 -12 -51 -19 -31 -3 6 -9 12 -14 12 -4 0
-6 -7 -2 -16 4 -10 -4 -24 -21 -39 -14 -12 -26 -27 -26 -34 0 -6 -4 -11 -10
-11 -5 0 -10 9 -10 20 0 37 -20 21 -26 -22 -7 -39 -8 -40 -17 -17 -5 14 -11
19 -14 12 -6 -15 -23 -17 -23 -3 0 18 -35 45 -55 42 -20 -3 -63 49 -57 69 1 6
-2 8 -7 5 -9 -6 -8 -64 1 -118 3 -14 13 -34 22 -43 12 -12 14 -21 7 -29 -18
-21 -9 -146 10 -146 5 0 9 -7 9 -16 0 -19 24 -13 26 7 5 54 6 54 15 24 14 -44
19 -81 18 -164 0 -61 3 -72 15 -68 8 3 17 1 20 -6 10 -26 25 19 25 73 -1 80
11 147 29 162 13 11 15 10 10 -9 -9 -33 25 -30 40 2 16 34 15 35 -5 29 -12 -4
-14 -3 -6 3 14 10 27 87 14 78 -21 -12 -20 30 0 51 12 13 19 30 16 38 -3 8 1
20 10 28 15 11 16 10 10 -11 -3 -14 0 -33 10 -47 17 -27 33 -31 33 -10 0 8 7
17 16 20 8 3 13 10 10 15 -3 5 1 11 8 14 8 3 17 1 20 -6 3 -8 7 -9 13 -2 4 6
22 18 38 27 24 14 30 23 28 48 -1 23 3 30 13 26 7 -3 20 1 28 9 21 21 39 19
31 -4 -3 -11 -1 -22 5 -26 6 -4 13 7 17 25 4 22 8 28 14 18 7 -10 9 -10 9 0 0
17 15 15 34 -4 15 -14 16 -14 16 0 0 9 7 16 16 16 11 0 14 5 10 16 -4 12 -2
15 9 10 10 -3 15 1 15 12 0 25 -10 35 -54 55 -30 14 -41 15 -52 6 -8 -7 -17
-10 -19 -7 -3 3 1 11 9 18 13 10 13 14 1 26 -14 15 -22 16 -42 7z m87 -72 c20
-38 13 -53 -21 -46 -22 5 -29 4 -25 -4 5 -7 1 -9 -8 -5 -9 3 -16 10 -16 16 0
5 4 7 9 3 5 -3 12 -1 16 4 3 6 12 8 20 4 10 -3 15 1 15 12 0 11 -5 15 -15 11
-15 -5 -20 5 -8 17 11 12 22 8 33 -12z m-73 -2 c-9 -6 -15 -13 -13 -17 2 -4
-9 -15 -25 -24 -16 -9 -31 -13 -33 -9 -3 4 8 15 25 25 16 9 29 21 29 27 0 5 8
9 18 9 16 -1 16 -1 -1 -11z m-87 -46 c0 -17 -18 -35 -29 -29 -8 5 -7 11 2 21
13 16 27 19 27 8z m80 -14 c0 -5 -4 -9 -10 -9 -5 0 -10 7 -10 16 0 8 5 12 10
9 6 -3 10 -10 10 -16z m-130 -9 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5
10 10 10 6 0 10 -4 10 -10z m-103 -77 c-3 -10 -5 -4 -5 12 0 17 2 24 5 18 2
-7 2 -21 0 -30z m147 19 c7 -11 -17 -38 -40 -46 -15 -5 -24 -2 -28 10 -8 21 4
40 15 23 6 -11 9 -10 15 4 6 17 29 23 38 9z m-366 -50 c-10 -2 -18 -8 -18 -13
0 -6 -5 -7 -11 -4 -6 5 -4 12 8 20 10 7 22 10 28 7 5 -4 2 -8 -7 -10z m182 4
c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10 25 14 25 6z m-195 -206 c3 -5 2
-10 -4 -10 -5 0 -13 5 -16 10 -3 6 -2 10 4 10 5 0 13 -4 16 -10z m80 -220 c3
-5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z"/>
<path d="M4602 4938 c5 -15 28 -23 28 -10 0 5 -7 13 -16 16 -10 4 -14 1 -12
-6z"/>
<path d="M3497 4922 c-10 -10 -14 -22 -10 -25 7 -8 43 21 43 35 0 14 -16 9
-33 -10z"/>
<path d="M4625 4900 c4 -6 11 -8 16 -5 14 9 11 15 -7 15 -8 0 -12 -5 -9 -10z"/>
<path d="M4130 4809 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M4500 4810 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
-4 -4 -4 -10z"/>
<path d="M4410 4786 c0 -9 5 -16 10 -16 6 0 10 4 10 9 0 6 -4 13 -10 16 -5 3
-10 -1 -10 -9z"/>
<path d="M3665 4780 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
-7 -4 -4 -10z"/>
<path d="M3747 4783 c-12 -11 -8 -23 9 -23 8 0 12 -4 9 -10 -3 -6 1 -7 10 -4
14 6 14 8 -1 25 -19 22 -18 21 -27 12z"/>
<path d="M4167 4486 c-4 -9 8 -29 25 -48 22 -23 33 -29 36 -19 2 7 0 16 -5 20
-5 3 -18 18 -30 33 -16 21 -22 24 -26 14z"/>
<path d="M4221 4484 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M3917 4473 c-10 -10 -8 -25 2 -19 5 4 11 1 13 -6 3 -7 7 -2 10 10 6
21 -10 31 -25 15z"/>
<path d="M3945 4428 c-4 -16 -4 -36 0 -45 12 -32 28 12 17 45 l-10 27 -7 -27z"/>
<path d="M4156 4428 c-9 -36 -7 -48 8 -48 21 0 28 29 12 51 -13 19 -14 19 -20
-3z"/>
<path d="M3890 4424 c0 -8 5 -12 10 -9 6 3 10 10 10 16 0 5 -4 9 -10 9 -5 0
-10 -7 -10 -16z"/>
<path d="M3997 4404 c6 -15 23 -19 23 -5 0 5 -7 11 -14 14 -10 4 -13 1 -9 -9z"/>
<path d="M4102 4370 c1 -23 5 -43 9 -45 10 -7 39 5 39 17 0 5 -5 6 -11 2 -8
-4 -9 0 -4 15 4 15 2 21 -9 21 -10 0 -13 6 -10 15 4 8 1 15 -5 15 -6 0 -10
-17 -9 -40z"/>
<path d="M4003 4364 c-16 -17 -17 -51 -1 -60 6 -4 8 -3 4 4 -3 6 -1 23 4 38
12 31 10 37 -7 18z"/>
<path d="M2543 4094 c8 -9 77 -25 122 -29 22 -2 30 -1 18 2 -13 2 -23 11 -23
19 0 11 -15 14 -62 14 -34 0 -59 -3 -55 -6z"/>
<path d="M2680 4090 c0 -5 25 -10 55 -10 30 0 55 5 55 10 0 6 -25 10 -55 10
-30 0 -55 -4 -55 -10z"/>
<path d="M2625 4040 c-8 -13 5 -13 25 0 13 8 13 10 -2 10 -9 0 -20 -4 -23 -10z"/>
<path d="M2680 4042 c0 -4 18 -6 40 -4 22 2 40 6 40 8 0 2 -18 4 -40 4 -22 0
-40 -3 -40 -8z"/>
<path d="M2775 4040 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
-7 -4 -4 -10z"/>
<path d="M2628 4013 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M2299 3988 c-3 -67 0 -161 5 -166 3 -3 6 38 6 91 0 54 -2 97 -5 97
-3 0 -5 -10 -6 -22z"/>
<path d="M2380 3985 c0 -7 7 -12 15 -11 22 3 23 19 3 22 -10 1 -18 -4 -18 -11z"/>
<path d="M2557 3963 c-11 -10 -8 -53 3 -53 6 0 10 14 10 30 0 31 -2 35 -13 23z"/>
<path d="M2623 3932 l0 -31 74 -3 c40 -2 83 -1 95 2 20 5 19 8 -18 29 -23 14
-62 25 -95 28 l-56 5 0 -30z"/>
<path d="M2670 3870 c0 -5 7 -10 16 -10 8 0 12 5 9 10 -3 6 -10 10 -16 10 -5
0 -9 -4 -9 -10z"/>
<path d="M2748 3863 c6 -2 18 -2 25 0 6 3 1 5 -13 5 -14 0 -19 -2 -12 -5z"/>
<path d="M3393 3853 c-10 -3 -13 -51 -13 -189 l0 -184 -25 -6 c-20 -5 -25 -12
-25 -39 0 -27 9 -41 47 -73 25 -22 62 -49 82 -60 l36 -21 3 290 3 289 -48 -1
c-26 0 -54 -3 -60 -6z m82 -213 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2
10 4 10 3 0 8 -4 11 -10z m5 -250 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6
5 10 10 10 6 0 10 -4 10 -10z"/>
<path d="M3670 3845 c0 -11 11 -15 39 -15 22 0 44 6 51 15 11 13 6 15 -39 15
-39 0 -51 -4 -51 -15z"/>
<path d="M2670 3825 c0 -9 17 -13 60 -14 47 0 58 2 54 14 -8 19 -114 19 -114
0z"/>
<path d="M3662 3726 c1 -52 6 -92 10 -90 5 3 8 0 8 -5 0 -19 40 -12 41 7 0 15
1 14 8 -2 7 -18 8 -18 14 5 12 42 8 49 -23 49 -34 0 -42 16 -7 17 12 0 38 1
57 3 34 3 34 3 -10 10 -25 4 -35 8 -22 8 35 3 30 42 -5 43 l-28 1 25 7 c14 4
26 15 28 24 3 14 -5 17 -48 17 l-51 0 3 -94z"/>
<path d="M4918 3685 c-2 -60 1 -94 7 -92 13 5 19 187 6 187 -5 0 -11 -43 -13
-95z"/>
<path d="M3770 3750 c0 -11 5 -20 10 -20 6 0 10 9 10 20 0 11 -4 20 -10 20 -5
0 -10 -9 -10 -20z"/>
<path d="M2740 3740 c0 -5 11 -10 24 -10 14 0 28 5 31 10 4 6 -7 10 -24 10
-17 0 -31 -4 -31 -10z"/>
<path d="M3770 3680 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0
-4 -4 -4 -10z"/>
<path d="M2775 3670 c3 -5 8 -10 11 -10 2 0 4 5 4 10 0 6 -5 10 -11 10 -5 0
-7 -4 -4 -10z"/>
<path d="M2820 3653 c0 -38 10 -73 21 -73 5 0 9 23 9 50 0 38 -4 50 -15 50
-10 0 -15 -10 -15 -27z"/>
<path d="M2872 3603 c4 -75 5 -78 29 -78 23 0 24 3 27 78 l3 77 -31 0 -32 0 4
-77z m48 -55 c0 -5 -4 -8 -10 -8 -5 0 -10 10 -10 23 0 18 2 19 10 7 5 -8 10
-18 10 -22z"/>
<path d="M4791 3651 c-14 -4 -27 -13 -29 -20 -3 -10 1 -12 17 -8 27 7 38 -9
11 -18 -11 -3 -20 -12 -20 -19 0 -33 14 -76 24 -76 16 1 106 68 106 80 0 6 -7
10 -15 10 -11 0 -13 8 -8 30 5 29 4 30 -28 29 -19 -1 -45 -4 -58 -8z"/>
<path d="M3685 3578 c4 -18 9 -36 12 -40 8 -15 23 -8 23 11 0 10 10 26 23 35
l22 17 -22 -5 c-13 -2 -23 0 -23 5 0 5 -9 9 -21 9 -18 0 -20 -4 -14 -32z"/>
<path d="M3870 3586 c0 -14 5 -28 10 -31 6 -3 10 0 10 9 0 8 3 21 6 30 4 11 1
16 -10 16 -10 0 -16 -9 -16 -24z"/>
<path d="M2750 3520 c-11 -6 -15 -20 -12 -49 l4 -41 64 0 c60 0 84 13 49 26
-8 4 -15 12 -15 20 0 8 -3 13 -7 12 -5 -2 -9 2 -10 7 -2 6 2 10 9 10 6 0 13 6
16 13 4 14 -74 17 -98 2z m50 -35 c0 -8 -7 -15 -15 -15 -26 0 -18 20 13 29 1
1 2 -6 2 -14z"/>
<path d="M4010 3492 c0 -16 32 -12 37 5 3 7 -4 11 -16 10 -12 -1 -21 -7 -21
-15z"/>
<path d="M2646 3445 c4 -8 8 -15 10 -15 2 0 4 7 4 15 0 8 -4 15 -10 15 -5 0
-7 -7 -4 -15z"/>
<path d="M4320 3410 c0 -5 -7 -10 -15 -10 -8 0 -15 -7 -15 -15 0 -12 5 -13 18
-7 9 5 23 7 30 5 6 -3 12 0 12 6 0 6 -5 11 -11 11 -5 0 -7 5 -4 10 3 6 1 10
-4 10 -6 0 -11 -4 -11 -10z"/>
<path d="M2635 5588 c-22 -12 -35 -28 -35 -42 0 -6 9 0 19 11 11 12 26 23 33
26 7 2 11 7 8 10 -3 3 -14 1 -25 -5z"/>
<path d="M5410 5772 c0 -4 9 -8 20 -9 11 -1 18 2 15 8 -7 11 -35 12 -35 1z"/>
<path d="M2532 4315 c9 -9 88 -13 88 -4 0 5 -21 9 -47 9 -25 0 -44 -2 -41 -5z"/>
<path d="M5187 4133 c-40 -4 -49 -8 -57 -29 -6 -14 -23 -33 -40 -42 -29 -16
-30 -19 -30 -89 0 -58 3 -73 15 -73 12 0 15 16 16 78 l1 77 10 -55 c5 -30 10
-63 11 -72 1 -19 17 -25 17 -7 0 5 5 7 11 3 8 -5 8 -1 0 14 -35 65 26 131 82
88 9 -7 17 -24 17 -38 0 -34 5 -37 45 -24 23 7 35 17 35 28 0 23 6 23 32 -2
24 -22 38 -26 38 -9 0 21 45 4 48 -18 2 -13 8 -23 13 -23 5 0 9 -7 9 -16 0 -8
5 -12 11 -8 8 4 9 -1 4 -17 l-7 -24 20 23 c11 13 23 19 26 13 3 -5 -1 -16 -9
-25 -14 -13 -13 -15 3 -13 10 0 18 8 18 16 1 9 5 51 9 94 7 68 6 77 -8 72 -8
-4 -23 2 -33 13 -23 24 -97 45 -127 37 -18 -5 -19 -4 -7 5 8 6 33 9 55 8 22
-1 49 3 60 10 16 9 -7 11 -110 10 -71 -1 -152 -3 -178 -5z m316 -133 c-7 -28
-13 -25 -13 6 0 14 4 23 9 20 5 -3 7 -15 4 -26z"/>
<path d="M5421 3944 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z"/>
<path d="M5604 3845 c8 -8 18 -15 22 -15 3 0 1 7 -6 15 -7 8 -17 15 -22 15 -5
0 -3 -7 6 -15z"/>
<path d="M5416 3813 c-3 -4 -6 -30 -6 -60 0 -50 -1 -53 -25 -53 -14 0 -28 6
-31 14 -4 10 -16 12 -37 9 -40 -6 -39 -5 -43 -45 -2 -17 -10 -35 -17 -40 -6
-4 33 -8 88 -8 110 0 131 7 121 38 -5 15 0 28 15 43 l22 22 -6 -31 c-8 -39 -5
-39 28 -7 42 43 28 75 -28 66 -4 -1 -10 6 -13 14 -7 18 -59 47 -68 38z m4
-147 c0 -11 -19 -15 -25 -6 -3 5 1 10 9 10 9 0 16 -2 16 -4z"/>
<path d="M5149 3716 c-2 -2 -20 -6 -39 -7 -46 -5 -54 -18 -24 -42 14 -11 23
-26 20 -34 -4 -8 -1 -11 5 -7 6 3 9 15 6 25 -4 16 1 19 26 20 18 1 35 1 40 0
9 -1 9 12 1 33 -6 15 -25 21 -35 12z"/>
<path d="M5170 3645 c0 -8 5 -15 10 -15 6 0 10 7 10 15 0 8 -4 15 -10 15 -5 0
-10 -7 -10 -15z"/>
<path d="M2992 3540 c0 -14 2 -19 5 -12 2 6 2 18 0 25 -3 6 -5 1 -5 -13z"/>
<path d="M4780 3131 c0 -6 5 -13 10 -16 6 -3 10 1 10 9 0 9 -4 16 -10 16 -5 0
-10 -4 -10 -9z"/>
<path d="M2948 3343 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M4178 3143 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M3855 3080 c3 -5 15 -10 26 -10 11 0 17 5 14 10 -3 6 -15 10 -26 10
-11 0 -17 -4 -14 -10z"/>
<path d="M4210 3036 c0 -9 0 -19 -1 -23 0 -4 4 -9 10 -11 14 -5 14 35 1 43 -5
3 -10 -1 -10 -9z"/>
<path d="M4158 3023 c-7 -25 6 -53 14 -31 3 7 2 22 -2 32 -6 19 -7 19 -12 -1z"/>
<path d="M3932 2854 c-10 -12 -10 -14 2 -14 17 0 30 16 19 23 -5 3 -14 -1 -21
-9z"/>
<path d="M4108 2843 c7 -3 16 -2 19 1 4 3 -2 6 -13 5 -11 0 -14 -3 -6 -6z"/>
<path d="M5020 6693 c-52 -31 -89 -58 -82 -61 16 -5 15 -22 -2 -22 -10 0 -11
-10 -5 -47 13 -80 34 -128 54 -125 48 9 118 116 129 197 4 28 10 65 13 83 3
17 1 32 -3 32 -5 0 -52 -26 -104 -57z"/>
<path d="M5146 6724 c-12 -42 -25 -149 -18 -155 14 -14 142 -22 142 -10 0 10
-89 151 -110 175 -5 4 -11 0 -14 -10z"/>
<path d="M3637 6690 c-13 -15 -14 -20 -3 -20 7 0 16 9 19 20 3 11 4 20 3 20
-1 0 -9 -9 -19 -20z"/>
<path d="M2878 6284 c-16 -8 -28 -16 -28 -18 0 -2 16 -6 35 -8 31 -4 35 -1 35
19 0 27 -5 28 -42 7z"/>
<path d="M6233 5347 c-5 -40 -7 -79 -5 -89 5 -21 19 -17 165 45 26 12 37 27
17 27 -5 0 -34 16 -65 35 -30 19 -65 39 -79 45 -24 9 -24 8 -33 -63z"/>
<path d="M1585 4759 c-5 -24 -45 -330 -45 -349 0 -6 33 -10 73 -10 68 0 72 1
73 23 0 12 4 58 8 102 l7 80 -55 89 c-48 77 -56 86 -61 65z"/>
<path d="M5904 3102 c-28 -15 -82 -46 -120 -70 -38 -24 -116 -71 -173 -105
-57 -34 -104 -67 -103 -72 2 -19 145 -204 154 -199 4 3 8 22 9 42 0 26 3 31 8
19 5 -15 30 18 111 145 164 257 171 268 168 268 -2 0 -26 -12 -54 -28z"/>
<path d="M2071 3082 c10 -25 143 -247 215 -357 l80 -124 48 48 c27 27 53 59
60 72 7 16 23 26 46 29 19 4 43 11 54 17 18 10 18 11 -1 30 -18 18 -174 109
-358 208 -38 21 -87 49 -109 63 -21 13 -37 19 -35 14z"/>
<path d="M5315 2724 c-63 -30 -826 -360 -960 -414 l-140 -58 -52 -73 c-28 -41
-73 -102 -99 -137 -26 -34 -45 -65 -42 -67 5 -5 482 195 754 315 61 27 182 76
270 108 87 33 166 63 175 66 15 7 149 177 149 190 0 14 -25 1 -181 -97 -90
-57 -189 -119 -219 -138 -30 -19 -62 -36 -70 -38 -40 -11 -70 -12 -84 -4 -11
6 -4 8 24 8 45 0 62 12 37 26 -9 6 -17 18 -17 27 0 30 -19 41 -51 30 -16 -5
-34 -8 -40 -6 -12 4 104 47 435 162 103 35 190 67 193 70 2 2 0 14 -7 25 -12
24 -33 26 -75 5z m-535 -288 c0 -2 -8 -10 -17 -17 -16 -13 -17 -12 -4 4 13 16
21 21 21 13z"/>
<path d="M2692 2669 c-10 -38 -9 -41 14 -49 48 -18 126 -24 134 -9 5 7 10 11
12 9 2 -3 20 -30 39 -60 20 -30 63 -89 96 -130 55 -70 64 -77 129 -99 38 -13
85 -32 104 -42 40 -21 369 -161 448 -191 29 -11 63 -18 74 -15 12 3 35 -1 52
-9 22 -11 10 5 -44 57 -95 92 -78 81 89 -53 74 -59 138 -108 143 -108 16 0 -3
162 -22 189 -9 14 -70 48 -146 83 -114 53 -732 322 -904 393 -36 15 -90 38
-121 51 -77 33 -85 31 -97 -17z"/>
<path d="M1848 1513 c0 -5 -2 -20 -2 -35 -2 -26 1 -28 40 -28 34 0 44 4 49 20
4 12 1 27 -5 35 -13 15 -79 21 -82 8z"/>
<path d="M1852 1401 c-8 -5 -12 -22 -10 -42 3 -30 7 -34 35 -37 44 -4 73 13
73 44 0 35 -63 58 -98 35z"/>
<path d="M2374 1506 c-13 -33 0 -51 36 -51 32 0 35 2 35 30 0 27 -4 30 -33 33
-22 2 -34 -2 -38 -12z"/>
<path d="M2372 1388 c-30 -30 -3 -72 44 -66 34 4 53 31 38 56 -13 21 -64 28
-82 10z"/>
<path d="M2740 1465 c0 -44 1 -45 33 -45 37 0 51 8 60 33 12 33 -10 57 -53 57
l-40 0 0 -45z"/>
<path d="M3268 1440 l-16 -50 35 0 c32 0 35 2 29 25 -8 32 -25 75 -29 75 -2 0
-10 -22 -19 -50z"/>
<path d="M4013 1496 c-24 -21 -28 -31 -27 -77 0 -44 5 -56 29 -76 21 -18 35
-23 54 -18 46 11 63 37 63 96 0 45 -4 56 -26 76 -34 29 -58 29 -93 -1z"/>
<path d="M4310 1470 c0 -40 0 -40 40 -40 46 0 68 26 50 60 -8 15 -21 20 -50
20 -40 0 -40 0 -40 -40z"/>
<path d="M5324 1509 c-66 -33 -54 -169 16 -184 41 -9 76 15 89 60 10 38 -1 96
-22 113 -20 17 -60 22 -83 11z"/>
<path d="M2877 1084 c-4 -4 -7 -20 -7 -36 0 -34 21 -45 59 -32 27 10 36 30 23
51 -10 15 -64 28 -75 17z"/>
<path d="M4701 1040 c-15 -46 -14 -50 14 -50 29 0 30 6 11 50 l-13 32 -12 -32z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 94 KiB

Some files were not shown because too many files have changed in this diff Show More