Compare commits

..

29 Commits

Author SHA1 Message Date
249ae14a71 fix 2026-07-15 13:30:02 +03:00
86afcefcf5 fix 2026-07-15 13:27:30 +03:00
4621a83d3f fix 2026-07-15 11:16:19 +03:00
8445937922 fix select bridge 2026-07-02 20:44:08 +03:00
6e0325e52f fix select bridge 2026-07-02 20:39:17 +03:00
0837d9c431 fix select bridge 2026-07-02 20:32:20 +03:00
1f8b9c3674 fix select bridge 2026-07-02 20:22:48 +03:00
68e9df3246 fix select bridge 2026-07-02 20:17:20 +03:00
8b3dbb4846 fix select bridge 2026-07-02 19:50:46 +03:00
ccd05ffb97 fix select bridge 2026-07-02 19:42:26 +03:00
59750206ab fix select bridge 2026-07-02 19:31:52 +03:00
7535845a86 fix select bridge 2026-07-01 16:59:00 +03:00
3f9f8db72c strange 2026-07-01 16:45:33 +03:00
66fdbdd964 profile refactor 2026-07-01 16:42:37 +03:00
Codex
6cac9db408 Add healthcheck endpoint 2026-07-01 12:22:15 +03:00
8789963a7b profile refactor 2026-07-01 01:28:39 +03:00
5ee794edf4 profile refactor 2026-06-30 16:29:54 +03:00
b59de00642 profile refactor 2026-06-30 15:53:34 +03:00
9f45efc9eb profile refactor 2026-06-29 19:57:36 +03:00
a5737e12e6 profile refactor 2026-06-29 19:42:07 +03:00
3020d6b334 profile refactor 2026-06-29 19:31:54 +03:00
d3c9662f82 profile refactor 2026-06-29 19:22:24 +03:00
7af549fb1d profile refactor 2026-06-29 19:11:45 +03:00
f372ef6fb5 profile refactor 2026-06-29 18:20:13 +03:00
d247e41d25 profile refactor 2026-06-29 18:13:56 +03:00
237112c302 profile refactor 2026-06-29 17:41:56 +03:00
2eaa11f790 fix 2026-06-26 16:06:42 +03:00
7e3493005b fix 2026-06-26 16:01:44 +03:00
564f21552d chore: set up OpenSpec spec-driven workflow
Add openspec/config.yaml with project context (React 19/Vite, FSD layers,
auth flow, CSS Modules) and per-artifact rules so agents generate proposals,
specs, designs, and tasks aligned with project conventions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 20:34:02 +03:00
177 changed files with 3531 additions and 1427 deletions

View File

@@ -1,5 +1,3 @@
# syntax=docker/dockerfile:1.7
FROM public.ecr.aws/docker/library/node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./

BIN
dist/assets/BONK-CSOWwKRv.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
dist/assets/DOGE-DGKVmDxD.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
dist/assets/JUP-B5soXSmJ.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
dist/assets/PUMP-ICTVsk_g.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
dist/assets/RAY-DjdDnD_x.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
dist/assets/TRUMP-DhGGs5Yg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
dist/assets/UNI-D58z1jTz.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
dist/assets/WIF-CBkpySMY.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

189
dist/assets/index-B04m7avt.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/assets/index-CmBRAAIp.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 994.3 1000.5" style="enable-background:new 0 0 994.3 1000.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F7F5F8;}
.st1{fill:#DCC4D4;}
.st2{fill:#EFAD93;}
.st3{fill:#D68C72;}
.st4{fill:#964C49;}
.st5{fill:#3A0101;}
.st6{fill:#894544;}
.st7{fill:#E3746D;}
.st8{fill:#FFFFFF;}
.st9{fill:#623538;}
.st10{fill:#C95755;}
</style>
<g>
<path class="st0" d="M27.4,444.9l471.8-254l124.2-2.5c0,0,129.7,15.8,232.7,116.6c0.1,0.1,0.2,0.1,0.2,0.2
c28.2,27.7,54.4,62.5,75.1,106.3c1.4,2.9,2.8,5.9,4.1,8.9c0,0,151.2,244-41.3,456.4c-192.5,212.3-651.4,110.6-789.3-112.5
c-1-1.5-2-3.1-3-4.7c-21.2-34.1-37-67.9-48.6-99.2c-14.7-39.6-22.9-75.1-27.4-101.6C20.8,528.5,27.5,444.9,27.4,444.9z"/>
<path class="st1" d="M218.8,420.3c-31.3,88.9,7.8,189.9,85.9,99.6c111.2-153,321.4-183.3,405.1-172.5
c102.5,19.8,182.5,123.4,207.9,125.4c25.4,2,13.7-61.3,13.7-61.3c1.4,2.9,2.8,5.9,4.1,8.9c0,0,151.2,244-41.3,456.4
C701.7,1089.1,242.8,987.4,105,764.2c-1-1.5-2-3.1-3-4.7c-21.2-34.1-37-67.9-48.6-99.2C106.8,572.1,243.9,348.5,218.8,420.3z"/>
<path class="st2" d="M680.7,183.7c49.4-48.5,129.9-117.2,190.6-152.4c29.2-17,53.8-26.2,68.1-21.7c2.8,0.8,5.1,2.2,7.1,4.1
c23.7,23.2,14.4,169.4,3.6,279.9c-7,70.6-14.6,126.7-14.6,126.7c-15.5-33.2-32-65.7-81.8-118c-20.7-20.3-41.8-37.4-63.2-51.7
c-36-24-72.5-40.1-108.3-50.3c-4.8-1.4-9.6-2.6-14.4-3.8C671.8,192.5,676.1,188.2,680.7,183.7z"/>
<path class="st3" d="M871.3,31.4c-10.1,73.5-12.2,200.9,78.8,262.3c-7,70.6-14.6,126.7-14.6,126.7c-15.5-33.2-32-65.7-81.8-118
c-20.7-20.3-41.8-37.4-63.2-51.7c-36-24-72.5-40.1-108.3-50.3l-1.6-16.6C730.1,135.2,810.6,66.6,871.3,31.4z"/>
<path class="st4" d="M51.1,14.9c49.7-15.8,213.2,136.5,315.7,216.5c0,0,141.2-74,301.1-34.9c7.5,1.8,15.1,3.9,22.8,6.3
c-46.6-1.7-115.4-3.1-144.9,2.2C499,213.5,329,264,254.7,383.2c-74.3,119.1-71.3,258.8-69.5,320.2c1.4,48.9-34.4,79.5-88.3,48
c-44.5-74.3-63.2-146.8-71-192.6c-1.1-10.1-2.2-20.5-3.5-31c-0.8-6-1.4-12-2.1-17.9C-12.3,223.4,2.5,30.3,51.1,14.9z"/>
<path class="st4" d="M939.4,9.6c-41.2,32.2-128.1,113.5-148.9,241c-40.8-27.2-82.3-44.2-122.7-54.1C736,126.7,892.6-5,939.4,9.6z"
/>
<path class="st5" d="M667.3,196.7c18-21.7,38.7-41.3,59-60.8c30.9-28.7,63.1-56.1,97.5-80.5c23.1-16.3,47-31.5,73.2-42.8
c13.8-5.3,28.2-11.2,43.7-6.9c3.2,0.8,4.1,5.5,1.3,7.4c-48,35.5-89.8,81.2-115,136l-7.3,16.4l-6.3,16.8c-8.3,23.1-13.5,47.2-19,71
c-1.4,2.2-4.4,2.7-6.5,1.3c-9.3-6.2-18.7-12.1-28.3-17.7C730.6,220,699.1,207.3,667.3,196.7L667.3,196.7z M668.3,196.4
c33.5,5.2,65.5,17.4,95.4,33c10,5.2,19.8,11.1,29.3,17.3l-7.2,3.2c11.1-73.1,51.8-137.4,99-192.5c15.9-18.4,33.2-35.6,52-51.1
l1.3,7.4c-34.7-7-111.7,54.4-141.3,75.9C755.4,121.4,714.9,155,676,189.9C673.8,191.8,670.7,194.7,668.3,196.4L668.3,196.4z"/>
<path class="st5" d="M667,196.8c9.8-12.7,21.5-23.8,32.5-35.3c56.3-55.7,115.3-109,185.4-147.2C903.6,5.5,934-9.3,952.6,8
c8.6,9.3,11,23.4,12.9,34.8c7.6,63.5,0.5,127.1-5.9,190.2c-7.1,62.7-14.3,125.2-20.2,188c-0.1,1.2-0.9,2.5-2.1,3.1
c-1.9,1-4.3,0.2-5.3-1.7c-21.3-43.7-51.6-81.8-85.2-116.5c-29-28.5-61.5-53.6-97.1-73.3C723.7,217.7,695.1,206.6,667,196.8
L667,196.8z M668.6,196.3c102.9,16.6,200.3,90.3,251,181.1c7.4,13.4,13.7,27.4,19.6,41.3l-7.6,1.2c15.8-93,21.6-187.6,22.5-281.8
c0.1-30.9,0.3-62.6-4.6-92.8c-1.5-8.2-3.1-16-6.7-22.5c-2.2-3.9-5.1-5.3-10-5.6c-13.2-0.3-28,6.5-40.3,12.5
c-13.6,6.6-26.9,14.5-39.9,22.9c-62,40.5-119.8,87.7-175.4,136.6C674.9,191.3,671.1,194.7,668.6,196.3L668.6,196.3z"/>
<path class="st5" d="M368.1,222.4c0,0-27.7,15.2-48.3,39.2c32.8-26.4,66.9-39.2,66.9-39.2H368.1z"/>
<path class="st5" d="M51.4,15.6C-13.1,43.9,7.5,316.1,13.6,383c3.6,42.3,8.6,84.5,13.7,126.7c0.9,16.6,3.4,33.8,6.5,50.3
c15.8,83.2,49,164.3,101,231.4c162.6,201.4,596.3,285.2,772.8,64.1c93.2-112.3,103.3-255.1,47.5-387.3c-6.8-15.7-14.3-31.3-23-45.7
c-9.8-21.3-21.3-41.7-34.7-60.8C858,307,809.5,265.5,746.8,233.1c-117.3-59-260-50.3-377.9,2.6c-1.6,0.8-3.7,0.7-5.2-0.5
c-50.3-40.8-98.5-83.9-148.5-125C183.7,85.2,89.5,5.3,51.4,15.6L51.4,15.6z M50.9,14.1c38.2-10.9,133.1,68.2,166.8,93
c51.1,39.6,100.6,81.4,152,120.5l-5.2-0.5c10.1-5.3,20.2-9.7,30.6-13.9c113.6-45.9,247.7-50.1,357.9,7.6
c38.5,19.3,80,51.8,106.2,79.6c28.3,26.3,63.5,77.6,79.6,117.9c37.5,68.6,57.7,147.2,55.3,225.5c-2,78.7-32.2,155.1-80.9,216.3
c-144.1,184.7-435.8,164.2-626.6,69.8c-70.3-34.9-136.1-83.3-181-148.9c-52.9-79.3-87.3-177.1-92-270.3
c-12-126.6-19.9-254.6-7-381.4C10.8,98.9,18.7,25.8,50.9,14.1L50.9,14.1z"/>
<path class="st2" d="M56.5,68.9c10.8,4.5,48,42.6,88.9,92c33.1,40,68.6,87.5,94.4,130.5C256.3,318.9,134.9,522,113,560.3
c-20.1,35.1-64.5-92-76.1-226c-1.1-12-1.8-23.9-2.3-35.9C28.8,152.3,36.9,60.8,56.5,68.9z"/>
<path class="st6" d="M327.6,643.2c7.1-85.1,52.7-166.4,117.6-206.6c75-42,139.1-61.4,202.6-61.1l0,0c15.2,0.1,30.5,1.3,45.8,3.6
c15,2.3,30.1,5.6,45.5,9.9c66,18.5,208.6,88.2,186.5,282.8c-0.7,5.8-1.5,11.5-2.5,17.2C891,873.9,688.2,995.2,467.4,887.4
C358,834,319.8,736.3,327.6,643.2z"/>
<path class="st7" d="M636.5,336.4c9.7,2.9,32.2,11.3,56.1-1c23.9-12.3,33.2,15.1,20.5,22.1c-14.4,7.9-18.4,17-19.6,21.7
c-15.3-2.3-30.5-3.5-45.8-3.6l0,0c-4.1-7.4-25.4-8.4-33.2-21.1C606.7,341.7,626.8,333.4,636.5,336.4z"/>
<path class="st8" d="M386.7,314c6.2-5.8,12.6-10.9,19.1-15.3c58-40,121.3-28.3,130.8-3.7c10.6,27.3-35.8,36.7-64.2,48.6
c-25.9,10.8-56.1,30.6-78.7,43.5c-16.6,9.5-29.3,15.3-33.1,11.1C351.5,388.3,342.5,354.9,386.7,314z"/>
<path class="st8" d="M773.8,272.5c33.4,12.4,58.6,33.3,75,50.7c11.4,12.1,18.4,22.5,20.9,27.2c6.1,11.4-12.7,14-36.2,5.3
c-1-0.4-2.1-0.8-3.2-1.2c-25.3-9-84.3-25.6-101.1-33C705.1,310.9,717.2,251.5,773.8,272.5z"/>
<path class="st5" d="M405.8,298.7c58-40,121.3-28.3,130.8-3.7c10.6,27.3-35.8,36.7-64.2,48.6c-25.9,10.8-56.1,30.6-78.7,43.5
C370.3,352.9,386.3,320.8,405.8,298.7z"/>
<path class="st5" d="M773.8,272.5c33.4,12.4,58.6,33.3,75,50.7c0.6,10.9-2.7,23.7-18.5,31.3c-25.3-9-84.3-25.6-101.1-33
C705.1,310.9,717.2,251.5,773.8,272.5z"/>
<path class="st5" d="M504.4,274.3c-72.3-19-136.4,35.7-149,74s-0.5,51.9,0,40.6s0-28.9,18-52.9c18.1-24,76-50.5,76-50.5
S477.1,292.5,504.4,274.3z"/>
<path class="st5" d="M869.5,341.4c-20.4-25.1-54.2-47.2-54.2-47.2s5.1,17,18.1,25.7c13,8.8,37.3,35.8,37.3,35.8
S876.6,352.4,869.5,341.4z"/>
<path class="st8" d="M504.4,294.2c-8.5,0.9-74.6,10.1-65.2-3.7s34.7-12.3,55.5-10.7C517.1,281.5,512.9,293.4,504.4,294.2z"/>
<path class="st8" d="M803.6,314.5c-12.8-6.2-34.7-17.4-31.5-26s27.8,6.4,42.5,14C833.1,312,816.4,320.7,803.6,314.5z"/>
<path class="st9" d="M445.2,436.6c75-42,139.1-61.4,202.6-61.1l0,0c15.2,0.1,30.5,1.3,45.8,3.6c15,2.3,30.1,5.6,45.5,9.9
c66,18.5,208.6,88.2,186.5,282.7c-0.7,5.8-1.5,11.5-2.5,17.2C859.5,755.1,757.8,798,643,797.9c-139.3,0-259.6-63.2-315.5-154.7
C334.6,558.1,380.2,476.8,445.2,436.6z"/>
<path class="st5" d="M467,888.1c-4.1-2.1-15-8-19-10.1c-4.3-2.5-13.8-8.5-18.2-11.3c-5.7-3.9-11.5-8.7-17.3-12.6
c-12.8-10.7-25.3-22-35.9-35c-51-59.2-67.4-143.5-50-219.2c14.9-66.8,52.5-130.4,110.4-168.2c74.4-43.3,162.1-73,249-60.2
c66.6,9.1,131.6,37.9,178.2,87.3c47.5,48.6,68.8,117.8,66.7,185c-0.4,38.6-7.7,77.3-22.3,113.1C871.9,848.2,785.9,914.7,689,928
C613.2,939.7,535.3,921.3,467,888.1L467,888.1z M467.7,886.6c103.1,51,224,52.6,322.3-10.2c62.5-40,109.6-104.2,126.4-177.1
c12.6-54.7,12.2-114.2-9.7-166.5C878,462.3,811,414,739.3,394.7C633,365.6,539,391.2,446.1,446.3
C361.9,503,321.5,614.9,336.4,714.1c5.5,34.6,19.1,68.2,39.4,96.7c3.2,4,7.6,9.9,10.8,13.9c6.6,7.1,14.9,16.4,22.4,22.6l5.2,4.8
l5.6,4.3c6.3,5.3,16.2,11.9,23.2,16.3C449.7,877.2,460.6,882.6,467.7,886.6L467.7,886.6z"/>
<path class="st10" d="M624.5,349.4c9.9-5,28,14.1,28,14.1C630,361.9,614.5,354.5,624.5,349.4z"/>
<path class="st10" d="M709.7,347.4c-8.3-4.5-19.1,16.1-19.1,16.1C701.2,361.2,718,351.9,709.7,347.4z"/>
<path class="st3" d="M145.4,160.9c33.1,40,68.6,87.5,94.4,130.5c16.5,27.5-104.9,230.6-126.9,268.9c-20.1,35.1-64.5-92-76.1-226
C134.4,390.3,148.1,261.2,145.4,160.9z"/>
<path class="st5" d="M239.3,291.7C203,231.8,156.6,179,109.9,127.3C94.3,110.6,78.5,93.1,61,78.7c-2.4-1.8-4.8-3.7-6.8-4.5
c-2.9,2.5-5.2,9.1-6.4,13.8c-7.9,33.4-8.7,68.6-9.8,103.1c-0.4,23.2-0.5,46.6-0.3,69.9c-0.2,70,5.5,140.1,23.6,207.9
c5.3,20,24.9,86.9,43.7,93.3c1.6-0.1,2.6-1.2,3.6-2.7l0.9-1.5c3.4-7.1,73.1-128.3,78.8-138.8C201.1,395.1,248.5,315.1,239.3,291.7
L239.3,291.7z M240.3,291.1c10.1,18.9-35.6,108.8-46,131.3c-23,47.3-49.2,93.1-76.6,137.9c-2,4.1-7.1,10.6-13.3,9.8
c-30.8-4.3-55.4-138.4-61-168.9C30.8,332,27.6,261.4,27.8,191.1c0.8-28.9-0.2-103.5,17.4-124.3c7.7-8.1,16.3-2.5,22.8,3
c9.4,7.7,17.6,16.1,25.8,24.6C150,154,197.5,221.4,240.3,291.1L240.3,291.1z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 400 432.7" style="enable-background:new 0 0 400 432.7;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F50DB4;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#F50DB4;}
</style>
<path class="st0" d="M325.1,65.4c0.6-10.2,2-17,4.8-23.1c1.1-2.4,2.1-4.4,2.3-4.4s-0.3,1.8-1.1,4c-2,6-2.4,14.2-1,23.7
c1.8,12.1,2.8,13.8,15.6,26.9c6,6.1,13,13.8,15.5,17.1l4.6,6l-4.6-4.3c-5.6-5.3-18.6-15.5-21.4-17c-1.9-1-2.2-1-3.4,0.2
c-1.1,1.1-1.3,2.7-1.5,10.4c-0.2,12-1.9,19.7-5.8,27.3c-2.1,4.2-2.5,3.3-0.5-1.4c1.4-3.5,1.6-5,1.6-16.6c0-23.3-2.8-28.9-19.1-38.5
c-4.1-2.4-10.9-5.9-15.1-7.8c-4.2-1.9-7.5-3.5-7.4-3.6c0.5-0.5,16.3,4.2,22.7,6.6c9.5,3.6,11.1,4.1,12.2,3.7
C324.4,74.2,324.8,72,325.1,65.4z"/>
<path class="st0" d="M124.4,31.5c-5.6-0.9-5.9-1-3.2-1.4c5.1-0.8,17.1,0.3,25.4,2.2c19.3,4.6,36.9,16.3,55.6,37l5,5.5l7.1-1.1
c30-4.8,60.6-1,86.1,10.8c7,3.2,18.1,9.7,19.5,11.3c0.4,0.5,1.3,3.9,1.8,7.5c1.9,12.5,0.9,22.1-2.9,29.3c-2.1,3.9-2.2,5.1-0.8,8.5
c1.1,2.7,4.3,4.6,7.4,4.6c6.3,0,13.2-10.2,16.3-24.4l1.3-5.6l2.5,2.8c13.7,15.4,24.4,36.4,26.2,51.3l0.5,3.9l-2.3-3.5
c-4-6.1-7.9-10.2-13-13.6c-9.2-6-18.9-8.1-44.5-9.4c-23.2-1.2-36.3-3.2-49.3-7.4c-22.1-7.2-33.3-16.7-59.6-51.1
c-11.7-15.2-18.9-23.7-26.1-30.5C161,42.8,145,34.7,124.4,31.5z"/>
<path class="st0" d="M135.4,105.3c-11.4-15.7-18.5-39.7-17-57.6l0.5-5.6l2.6,0.5c4.9,0.9,13.3,4,17.3,6.4
c10.8,6.5,15.5,15.2,20.3,37.3c1.4,6.5,3.2,13.8,4.1,16.3c1.4,4,6.5,13.3,10.7,19.4c3,4.4,1,6.4-5.6,5.8
C158,126.9,144.2,117.5,135.4,105.3z"/>
<path class="st0" d="M311.3,221.9c-53.5-21.4-72.3-40-72.3-71.4c0-4.6,0.2-8.4,0.4-8.4c0.2,0,2.3,1.5,4.6,3.4
c10.8,8.6,23,12.3,56.6,17.2c19.8,2.9,30.9,5.2,41.2,8.6c32.6,10.8,52.8,32.6,57.6,62.4c1.4,8.6,0.6,24.9-1.7,33.4
c-1.8,6.7-7.3,18.9-8.7,19.4c-0.4,0.1-0.8-1.4-0.9-3.5c-0.6-11.2-6.2-22-15.8-30.2C361.4,243.6,346.9,236.2,311.3,221.9z"/>
<path class="st0" d="M273.7,230.8c-0.7-4-1.8-9-2.6-11.3l-1.4-4l2.5,2.8c3.5,3.9,6.3,8.9,8.6,15.6c1.8,5.1,2,6.6,2,14.9
c0,8.1-0.2,9.8-1.9,14.4c-2.6,7.2-5.8,12.4-11.3,17.9c-9.8,9.9-22.3,15.4-40.4,17.6c-3.1,0.4-12.3,1.1-20.4,1.5
c-20.3,1.1-33.7,3.2-45.8,7.4c-1.7,0.6-3.3,1-3.4,0.8c-0.5-0.5,7.7-5.3,14.5-8.6c9.5-4.6,19-7.1,40.3-10.6
c10.5-1.7,21.4-3.9,24.1-4.7C264.6,276.7,278,256.2,273.7,230.8z"/>
<path class="st0" d="M298.2,274.1c-7.1-15.2-8.7-29.9-4.8-43.5c0.4-1.5,1.1-2.7,1.5-2.7c0.4,0,2.1,0.9,3.7,2
c3.3,2.2,9.8,5.9,27.3,15.4c21.8,11.8,34.3,21,42.7,31.5c7.4,9.2,12,19.6,14.2,32.3c1.3,7.2,0.5,24.6-1.3,31.8
c-5.9,22.9-19.5,40.9-39,51.4c-2.9,1.5-5.4,2.8-5.7,2.8c-0.3,0,0.8-2.6,2.3-5.8c6.5-13.6,7.3-26.8,2.3-41.6c-3-9-9.2-20-21.7-38.6
C305.4,287.5,301.8,281.7,298.2,274.1z"/>
<path class="st0" d="M97.4,356.1c19.8-16.7,44.5-28.5,67-32.1c9.7-1.6,25.8-0.9,34.8,1.3c14.4,3.7,27.3,11.9,33.9,21.6
c6.5,9.5,9.3,17.9,12.3,36.4c1.2,7.3,2.4,14.6,2.8,16.3c2.2,9.6,6.5,17.3,11.8,21.1c8.4,6.1,22.9,6.5,37.1,1
c2.4-0.9,4.5-1.6,4.7-1.4c0.5,0.5-6.7,5.3-11.7,7.8c-6.8,3.4-12.2,4.7-19.4,4.7c-13,0-23.9-6.6-32.9-20c-1.8-2.6-5.8-10.6-8.9-17.6
c-9.5-21.6-14.2-28.2-25.3-35.4c-9.6-6.3-22.1-7.4-31.4-2.8c-12.3,6-15.7,21.6-6.9,31.5c3.5,3.9,10,7.3,15.3,8
c10,1.2,18.5-6.3,18.5-16.3c0-6.5-2.5-10.2-8.8-13.1c-8.6-3.9-17.9,0.7-17.9,8.7c0,3.4,1.5,5.6,5,7.2c2.2,1,2.3,1.1,0.5,0.7
c-7.9-1.6-9.8-11.1-3.4-17.4c7.7-7.6,23.5-4.2,28.9,6.1c2.3,4.3,2.5,13,0.6,18.2c-4.5,11.7-17.4,17.8-30.6,14.5
c-9-2.3-12.6-4.7-23.4-15.8c-18.8-19.3-26.1-23-53.2-27.2l-5.2-0.8L97.4,356.1z"/>
<path class="st1" d="M9.2,11.5c62.8,75.7,106,107,110.8,113.6c4,5.5,2.5,10.4-4.3,14.2c-3.8,2.1-11.5,4.3-15.4,4.3
c-4.4,0-5.9-1.7-5.9-1.7c-2.6-2.4-4-2-17.1-25.1C59.1,88.8,43.9,65.5,43.5,65.1c-1-0.9-0.9-0.9,32,57.7c5.3,12.2,1.1,16.7,1.1,18.4
c0,3.5-1,5.4-5.4,10.3c-7.3,8.1-10.6,17.2-12.9,36.1c-2.6,21.1-10.1,36.1-30.7,61.6c-12.1,15-14,17.7-17.1,23.7
c-3.8,7.6-4.9,11.9-5.3,21.4c-0.5,10.1,0.4,16.7,3.5,26.4c2.7,8.5,5.6,14.1,12.9,25.3c6.3,9.7,9.9,16.9,9.9,19.7
c0,2.2,0.4,2.2,10.2,0.1c23.3-5.2,42.2-14.4,52.8-25.7c6.6-7,8.1-10.8,8.2-20.4c0-6.3-0.2-7.6-1.9-11.2c-2.8-5.9-7.8-10.7-18.9-18.3
c-14.5-9.9-20.8-17.9-22.5-28.8c-1.4-9,0.2-15.3,8.3-32.1c8.3-17.4,10.4-24.8,11.8-42.3c0.9-11.3,2.2-15.8,5.4-19.3
c3.4-3.7,6.5-5,14.9-6.1c13.7-1.9,22.5-5.4,29.7-12c6.2-5.7,8.9-11.2,9.3-19.5l0.3-6.3l-3.5-4C122.8,105.1,0.8,0,0,0
C-0.2,0,4,5.2,9.2,11.5z M38.5,305.9c2.9-5,1.3-11.5-3.4-14.7c-4.5-3-11.5-1.6-11.5,2.3c0,1.2,0.7,2.1,2.1,2.8
c2.5,1.3,2.7,2.7,0.7,5.7c-2,3-1.8,5.6,0.5,7.4C30.5,312.3,35.7,310.7,38.5,305.9z"/>
<path class="st1" d="M147.6,164.9c-6.5,2-12.7,8.8-14.7,15.9c-1.2,4.4-0.5,12,1.3,14.3c2.9,3.8,5.6,4.8,13.1,4.8
c14.7-0.1,27.5-6.4,29-14.2c1.2-6.4-4.4-15.3-12.1-19.2C160.2,164.4,151.7,163.6,147.6,164.9z M164.8,178.3c2.3-3.2,1.3-6.7-2.6-9
c-7.3-4.5-18.4-0.8-18.4,6.1c0,3.4,5.8,7.2,11.1,7.2C158.4,182.6,163.2,180.5,164.8,178.3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.9 KiB

4
dist/index.html vendored
View File

@@ -5,8 +5,8 @@
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ЭКСА — Ваш мост в мир цифровых активов</title>
<script type="module" crossorigin src="/assets/index-DFLADCGY.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BP0dDjYZ.css">
<script type="module" crossorigin src="/assets/index-B04m7avt.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CmBRAAIp.css">
</head>
<body>
<div id="root"></div>

154
install.ps1 Normal file
View File

@@ -0,0 +1,154 @@
# install.ps1 — One-line installer for codebase-memory-mcp (Windows).
#
# Usage: see README.md for install instructions.
#
# Environment:
# CBM_DOWNLOAD_URL Override base URL for downloads (for testing)
$ErrorActionPreference = "Stop"
# Enforce TLS 1.2+ (older PowerShell defaults to TLS 1.0 which GitHub rejects)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13
$Repo = "DeusData/codebase-memory-mcp"
$InstallDir = "$env:LOCALAPPDATA\Programs\codebase-memory-mcp"
$BinName = "codebase-memory-mcp.exe"
$BaseUrl = if ($env:CBM_DOWNLOAD_URL) { $env:CBM_DOWNLOAD_URL } else { "https://github.com/$Repo/releases/latest/download" }
# Security: reject non-HTTPS download URLs (defense-in-depth)
if (-not $BaseUrl.StartsWith("https://") -and -not $BaseUrl.StartsWith("http://localhost") -and -not $BaseUrl.StartsWith("http://127.0.0.1")) {
Write-Host "error: refusing non-HTTPS download URL: $BaseUrl" -ForegroundColor Red
exit 1
}
# Detect variant from args (--ui or --standard)
$Variant = "standard"
$SkipConfig = $false
foreach ($arg in $args) {
if ($arg -eq "--ui") { $Variant = "ui" }
if ($arg -eq "--standard") { $Variant = "standard" }
if ($arg -eq "--skip-config") { $SkipConfig = $true }
if ($arg -like "--dir=*") { $InstallDir = $arg.Substring(6) }
}
Write-Host "codebase-memory-mcp installer (Windows)"
Write-Host " variant: $Variant"
Write-Host " target: $InstallDir\$BinName"
Write-Host ""
# Build download URL
if ($Variant -eq "ui") {
$Archive = "codebase-memory-mcp-ui-windows-amd64.zip"
} else {
$Archive = "codebase-memory-mcp-windows-amd64.zip"
}
$Url = "$BaseUrl/$Archive"
# Download
$TmpDir = Join-Path ([System.IO.Path]::GetTempPath()) "cbm-install-$(Get-Random)"
New-Item -ItemType Directory -Path $TmpDir -Force | Out-Null
Write-Host "Downloading $Archive..."
try {
Invoke-WebRequest -Uri $Url -OutFile "$TmpDir\$Archive" -UseBasicParsing
} catch {
Write-Host "error: download failed: $_" -ForegroundColor Red
Remove-Item -Recurse -Force $TmpDir -ErrorAction SilentlyContinue
exit 1
}
# Checksum verification
$ChecksumUrl = "$BaseUrl/checksums.txt"
try {
Invoke-WebRequest -Uri $ChecksumUrl -OutFile "$TmpDir\checksums.txt" -UseBasicParsing
$checksumLine = Get-Content "$TmpDir\checksums.txt" | Where-Object { $_ -like "*$Archive*" }
if ($checksumLine) {
$expected = ($checksumLine -split '\s+')[0]
$actual = (Get-FileHash -Path "$TmpDir\$Archive" -Algorithm SHA256).Hash.ToLower()
if ($expected -ne $actual) {
Write-Host "error: CHECKSUM MISMATCH!" -ForegroundColor Red
Write-Host " expected: $expected"
Write-Host " actual: $actual"
Remove-Item -Recurse -Force $TmpDir
exit 1
}
Write-Host "Checksum verified."
}
} catch {
Write-Host "warning: could not verify checksum (non-fatal)"
}
# Extract
Write-Host "Extracting..."
Expand-Archive -Path "$TmpDir\$Archive" -DestinationPath $TmpDir -Force
$DlBin = Join-Path $TmpDir $BinName
if (-not (Test-Path $DlBin)) {
# UI variant may have different name in zip
$UiBin = Join-Path $TmpDir "codebase-memory-mcp-ui.exe"
if (Test-Path $UiBin) {
Rename-Item $UiBin $BinName
$DlBin = Join-Path $TmpDir $BinName
} else {
Write-Host "error: binary not found after extraction" -ForegroundColor Red
Remove-Item -Recurse -Force $TmpDir
exit 1
}
}
# Install
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
$Dest = Join-Path $InstallDir $BinName
# Handle replace-if-running (rename-aside)
if (Test-Path $Dest) {
$OldDest = "$Dest.old"
Remove-Item $OldDest -Force -ErrorAction SilentlyContinue
try {
Rename-Item $Dest $OldDest -ErrorAction Stop
} catch {
Write-Host "warning: could not rename existing binary (may be in use)"
}
}
Copy-Item $DlBin $Dest -Force
# Verify
try {
$ver = & $Dest --version 2>&1
Write-Host "Installed: $ver"
} catch {
Write-Host "error: installed binary failed to run" -ForegroundColor Red
Remove-Item -Recurse -Force $TmpDir
exit 1
}
# Configure agents
if ($SkipConfig) {
Write-Host ""
Write-Host "Skipping agent configuration (--skip-config)"
} else {
Write-Host ""
Write-Host "Configuring coding agents..."
try {
& $Dest install -y 2>&1 | Write-Host
} catch {
Write-Host "Agent configuration failed (non-fatal)."
Write-Host "Run manually: codebase-memory-mcp install"
}
}
# Add to PATH (user scope, no admin needed)
$UserPath = [Environment]::GetEnvironmentVariable("PATH", "User")
if ($UserPath -notlike "*$InstallDir*") {
[Environment]::SetEnvironmentVariable("PATH", "$UserPath;$InstallDir", "User")
$env:PATH = "$env:PATH;$InstallDir"
Write-Host "Added $InstallDir to user PATH"
}
# Cleanup
Remove-Item -Recurse -Force $TmpDir -ErrorAction SilentlyContinue
Write-Host ""
Write-Host "Done! Restart your terminal and coding agent to start using codebase-memory-mcp."

View File

@@ -9,6 +9,11 @@ server {
gzip_min_length 1024;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
location = /healthcheck {
add_header Content-Type application/json;
return 200 'ok';
}
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-06-29

View File

@@ -0,0 +1,96 @@
## Context
Сегодня в `RouterProvider` есть два независимых маршрута под `ProtectedRoute`:
- `/profile``ProfilePage`, которая сама рендерит `WalletHeader` + `KycBanner` + `ProfileSummary` + блоки `ProfileDetails` / `SecuritySection` / `MnemonicSection` одним столбцом (`ProfilePage.module.css`, `.main` — flex с `max-width: 1024px`).
- `/transactions``TransactionsPage` внутри обёртки `WalletLayout` (`footer`), которая сама даёт `WalletHeader` + `<Outlet/>` + `Footer`. `TransactionsPage` хранит таб «Транзакции/Заявки» в локальном `useState` (заявки только для юр. лиц через `useMe()`).
Несогласованность обёрток (профиль рисует свой `WalletHeader`, транзакции — через `WalletLayout`) — главный технический момент, который нужно унифицировать при слиянии.
Существующие переиспользуемые части: виджеты `@widgets/profile` (баррель уже экспортирует `ProfileSummary`, `ProfileDetails`, `SecuritySection`, `MnemonicSection`, `KycBanner`, `ProfileSection`), `@widgets/transactions-list`, `@widgets/purchase-requests-list`, и `Spinner` из `@shared/ui/Spinner` (поддерживает `size`, `label`, `fullscreen`).
## Goals / Non-Goals
**Goals:**
- Единый раздел `/profile` с боковым меню 25% / контентом 75% и вложенными URL на каждый пункт.
- Переиспользовать существующие блоки профиля и виджеты транзакций без переписывания их логики.
- Сохранить текущее поведение транзакций (табы «Транзакции/Заявки» для юр. лиц) внутри пункта меню.
- Индикатор загрузки контента через существующий `Spinner`; меню остаётся доступным.
- Сохранить рабочими старые ссылки (`/transactions``/profile/transactions`).
- Сохранить мобильное поведение (стек в одну колонку < 1024px).
**Non-Goals:**
- Не меняем бизнес-логику профиля, авторизации, загрузки данных (`useMe`, профильные хуки) и API транзакций.
- Не добавляем новые пункты меню сверх перечисленных.
- Не трогаем дизайн-токены и глобальные стили, кроме новых модульных CSS для layout/меню.
- Не вводим менеджер состояния — навигация через URL (React Router).
## Decisions
### D1. Маршрутизация — вложенные routes с `<Outlet/>`, а не локальный `useState`
Использовать nested routes React Router: родитель `/profile` рендерит layout профиля (меню + `<Outlet/>`), дети — `details` / `security` / `mnemonic` / `transactions`. `index`-маршрут редиректит на `details` (`<Navigate to="details" replace />`).
- **Почему:** пользователь выбрал отдельные URL с поддержкой кнопки «Назад» и deep-link. `<Outlet/>` — идиоматичный для проекта способ (так уже сделан `WalletLayout`).
- **Альтернатива (отклонена):** один компонент с `useState` для активного пункта — нет deep-link и истории; противоречит выбранному варианту.
- **Альтернатива (отклонена):** `?tab=` query — менее явный URL, чем сегментный путь.
### D2. Структура компонентов
- `pages/profile/ui/ProfilePage.tsx` → становится layout-страницей: рендерит обёртку (см. D3), левое меню и `<Outlet/>` в правой колонке с `KycBanner` над `<Outlet/>`.
- Новый виджет навигации `@widgets/profile``ProfileMenu` (`ProfileSummary` сверху + список ссылок-пунктов через `NavLink`, активный пункт подсвечивается через `aria-current`/класс). Добавить в баррель `widgets/profile/index.ts`.
- Контент-пункты — тонкие компоненты-страницы в `pages/profile/ui/` (или существующие виджеты напрямую):
- `details``<ProfileDetails/>`
- `security``<SecuritySection/>`
- `mnemonic``<MnemonicSection/>`
- `transactions` → содержимое бывшей `TransactionsPage` (список + табы юр. лиц).
- `pages/transactions` сохраняется как тонкая обёртка/переиспользуемый блок, переносимый в пункт меню; маршрут `/transactions` заменяется на редирект.
### D3. Унификация обёртки (header/footer)
Завести профиль под общий `WalletLayout` (как транзакции), убрав собственный `WalletHeader` из `ProfilePage`. В `RouterProvider`:
```
<Route element={<WalletLayout footer />}>
<Route path={ROUTES.PROFILE} element={<ProfilePage />}>
<Route index element={<Navigate to="details" replace />} />
<Route path="details" element={<ProfileDetailsItem />} />
<Route path="security" element={<SecurityItem />} />
<Route path="mnemonic" element={<MnemonicItem />} />
<Route path="transactions" element={<TransactionsItem />} />
</Route>
</Route>
<Route path={ROUTES.TRANSACTIONS} element={<Navigate to="/profile/transactions" replace />} />
```
`ProfilePage` рендерит свой `<Outlet/>` для пунктов внутри двухколоночного layout — то есть здесь два уровня `Outlet` (внешний от `WalletLayout`, внутренний от `ProfilePage`). Это допустимо в React Router.
- **Почему:** единый `WalletHeader`/`Footer` устраняет рассинхрон обёрток и убирает дублирование.
- **Альтернатива (отклонена):** оставить профилю собственный header — расходится с остальными разделами и усложняет поддержку.
### D4. Маршруты в конфиге
Добавить в `shared/config/routes.ts` константы для вложенных путей профиля (например `PROFILE_DETAILS`, `PROFILE_SECURITY`, `PROFILE_MNEMONIC`, `PROFILE_TRANSACTIONS`) либо хелпер; `TRANSACTIONS` сохранить для обратного редиректа. Меню (`ProfileMenu`) строит ссылки из этих констант.
### D5. Состояние загрузки
В правой колонке каждый пункт сам отвечает за свою загрузку: пока соответствующий React Query запрос в состоянии загрузки — рендерить `<Spinner label="Загрузка" />` (по центру области контента, `fullscreen` в пределах колонки). Меню вне `<Outlet/>`, поэтому остаётся интерактивным. Сейчас профильные блоки делают `if (!data) return null` — заменить на показ `Spinner`, пока `useMe` грузится.
### D6. Стили
Новый `ProfilePage.module.css`: grid/flex `25% / 75%`, `gap`, и `@media (max-width: 1023px)` — стек в одну колонку (перенести существующие брейкпоинты профиля). Меню — отдельный `ProfileMenu.module.css` (список, активное состояние, sticky сводка по желанию). Всё на CSS Modules, без новых зависимостей.
## Risks / Trade-offs
- **Двойной `<Outlet/>` (WalletLayout → ProfilePage)** → может запутать при чтении роутера. Mitigation: явные комментарии в `RouterProvider` и в `ProfilePage`.
- **Профиль внутри `WalletLayout footer`** меняет наличие `Footer`/центрирование на странице профиля по сравнению с текущим видом → Mitigation: сверить визуально; при необходимости подобрать пропсы `WalletLayout` (`footer`/`center`).
- **Дублирование табов транзакций** при переносе в пункт меню → Mitigation: вынести содержимое `TransactionsPage` в переиспользуемый компонент, не копировать логику.
- **Ломающий редирект `/transactions`** → внешние ссылки продолжают работать через `<Navigate replace/>`; зафиксировано как BREAKING в proposal.
- **Регрессия мобильного вида профиля** → Mitigation: перенести существующие медиа-брейкпоинты профиля.
## Migration Plan
1. Добавить вложенные маршруты профиля и редирект `/transactions` в `RouterProvider` + константы в `routes.ts`.
2. Создать `ProfileMenu` и компоненты-пункты, переработать `ProfilePage` в layout.
3. Вынести содержимое `TransactionsPage` в переиспользуемый блок, подключить как пункт.
4. Добавить состояние загрузки (`Spinner`) в пунктах.
5. `npm run build` (tsc) + ручная проверка: deep-link каждого пункта, кнопка «Назад», редиректы `/profile` и `/transactions`, мобильный вид, юр.лицо vs физлицо (табы).
Откат: вернуть прежние отдельные маршруты `/profile` и `/transactions` (изменения изолированы в `pages/profile`, `pages/transactions`, `widgets/profile`, `routes.ts`, `RouterProvider`).
## Open Questions
- Нужно ли подсвечивать пункт «Транзакции» в верхней навигации (`WalletHeader`) как раздел профиля, или ссылка на транзакции из шапки ведёт прямо на `/profile/transactions`? (По умолчанию: шапка ведёт на `/profile/transactions`.)
- Делать ли блок `ProfileSummary` sticky при скролле длинного контента (например списка транзакций)? (По умолчанию: обычное позиционирование, без sticky.)

View File

@@ -0,0 +1,35 @@
## Why
Сейчас профиль и транзакции — это две отдельные страницы (`/profile` и `/transactions`), между которыми нужно переключаться через общую навигацию. Профиль показывает все свои блоки (данные, безопасность, мнемоника) одним длинным скроллом. Объединение их в единый раздел с боковым меню даёт пользователю одну точку входа в «личный кабинет», убирает длинный скролл и делает транзакции равноправным пунктом наряду с настройками профиля.
## What Changes
- Страница профиля превращается в layout «личного кабинета»: слева колонка ~25% (меню), справа колонка ~75% (контент активного пункта).
- В левой колонке сверху всегда закреплён блок `ProfileSummary` (аватар + сводка), под ним — список пунктов меню.
- Существующие блоки профиля становятся пунктами меню и показываются в правой колонке по клику:
- **Данные профиля** (`ProfileDetails`) — пункт по умолчанию.
- **Безопасность** (`SecuritySection`).
- **Мнемоническая фраза** (`MnemonicSection`).
- **Транзакции** добавляются как ещё один пункт меню; в правой колонке рендерится содержимое бывшей `TransactionsPage` (список транзакций + табы «Транзакции / Заявки» для юр. лиц).
- Навигация между пунктами — через отдельные вложенные URL (`/profile/details`, `/profile/security`, `/profile/mnemonic`, `/profile/transactions`). Работают кнопка «Назад» и прямые ссылки.
- `/profile` редиректит на пункт по умолчанию (`/profile/details`).
- **BREAKING**: старый маршрут `/transactions` редиректит на `/profile/transactions`; отдельная страница транзакций в навигации больше не используется как самостоятельная.
- `KycBanner` отображается над контентом в правой колонке.
- Пока данные активного пункта загружаются, в правой колонке показывается индикатор загрузки (переиспользуется `Spinner` из `@shared/ui/Spinner`); меню остаётся доступным.
- Адаптив: на узких экранах (<1024px) меню и контент схлопываются в одну колонку, сохраняя текущее мобильное поведение профиля.
## Capabilities
### New Capabilities
- `profile-dashboard`: единый раздел личного кабинета с боковым меню (25/75), вложенной маршрутизацией по пунктам, закреплённой сводкой профиля, интеграцией транзакций как пункта меню и состоянием загрузки контента.
### Modified Capabilities
<!-- Нет существующих спеков, требующих изменения требований. -->
## Impact
- **pages**: `pages/profile` (переработка `ProfilePage` в layout с `<Outlet/>` или переключателем пунктов), `pages/transactions` (контент переезжает в пункт меню; маршрут редиректится).
- **widgets**: `widgets/profile` (новый виджет бокового меню / навигации; `ProfileSummary`, `ProfileDetails`, `SecuritySection`, `MnemonicSection`, `KycBanner` переиспользуются), `widgets/transactions-list`, `widgets/purchase-requests-list` (переиспользуются как контент пункта).
- **shared**: `shared/config/routes.ts` — новые вложенные маршруты профиля и редирект со старого `/transactions`; `shared/ui/Spinner` — переиспользуется.
- **app**: `app/providers/RouterProvider.tsx` — описание вложенных маршрутов под `ProtectedRoute`, согласование с `WalletLayout` (профиль сейчас рендерит собственный `WalletHeader`, а транзакции живут внутри `WalletLayout` — нужно унифицировать обёртку).
- Тестового раннера нет — проверка через `npm run build` (tsc) и ручной прогон.

View File

@@ -0,0 +1,77 @@
## ADDED Requirements
### Requirement: Two-column dashboard layout
The profile section SHALL be presented as a two-column layout: a left menu column occupying approximately 25% of the available width and a right content column occupying approximately 75%. On viewports narrower than 1024px the two columns SHALL collapse into a single stacked column.
#### Scenario: Wide viewport shows two columns
- **WHEN** an authenticated user opens the profile section on a viewport ≥ 1024px wide
- **THEN** the left menu column (~25%) and the right content column (~75%) are displayed side by side
#### Scenario: Narrow viewport stacks columns
- **WHEN** an authenticated user opens the profile section on a viewport < 1024px wide
- **THEN** the menu and the content are stacked vertically in a single column
### Requirement: Pinned profile summary
The left menu column SHALL display the profile summary (`ProfileSummary` — avatar and identity) pinned at the top, above the list of menu items, and it SHALL remain visible regardless of which menu item is active.
#### Scenario: Summary visible on every item
- **WHEN** the user switches between any menu items
- **THEN** the profile summary remains displayed at the top of the left column
### Requirement: Menu items for profile sections and transactions
The left menu SHALL list selectable items for: Данные профиля (`ProfileDetails`), Безопасность (`SecuritySection`), Мнемоническая фраза (`MnemonicSection`), and Транзакции (transactions content). Selecting an item SHALL render its content in the right column, and the currently active item SHALL be visually highlighted.
#### Scenario: Selecting a menu item shows its content
- **WHEN** the user clicks a menu item
- **THEN** the right column renders that item's content and the clicked item is marked as active
#### Scenario: Transactions appears as a menu item
- **WHEN** the user views the profile menu
- **THEN** a «Транзакции» item is present alongside the profile section items, and selecting it renders the transactions content (list plus the «Транзакции / Заявки» tabs for legal-entity accounts)
### Requirement: Per-item routing with default redirect
Each menu item SHALL have its own URL under `/profile` (`/profile/details`, `/profile/security`, `/profile/mnemonic`, `/profile/transactions`) so that the browser Back button and direct links select the corresponding item. Navigating to `/profile` SHALL redirect to the default item `/profile/details`.
#### Scenario: Direct link opens the matching item
- **WHEN** the user navigates directly to `/profile/transactions`
- **THEN** the transactions item is active and its content is shown in the right column
#### Scenario: Bare profile path redirects to default
- **WHEN** the user navigates to `/profile`
- **THEN** the app redirects to `/profile/details` and shows the profile data item
#### Scenario: Back button restores previous item
- **WHEN** the user selects one item and then another, and then presses the browser Back button
- **THEN** the previously active item is restored
### Requirement: Legacy transactions route redirect
The legacy route `/transactions` SHALL redirect to `/profile/transactions` so existing links and bookmarks continue to work.
#### Scenario: Old transactions URL redirects
- **WHEN** the user navigates to `/transactions`
- **THEN** the app redirects to `/profile/transactions`
### Requirement: KYC banner placement
The KYC banner (`KycBanner`) SHALL be displayed above the content in the right column.
#### Scenario: KYC banner shown above content
- **WHEN** the profile section is displayed and the KYC banner is applicable
- **THEN** the banner appears above the active item's content in the right column
### Requirement: Loading state for content
While the data for the active menu item is loading, the right column SHALL show a loading indicator (the shared `Spinner`) while the left menu remains interactive.
#### Scenario: Spinner while data loads
- **WHEN** the active item's data is still loading
- **THEN** a loading indicator is shown in the right column and the user can still click other menu items
#### Scenario: Content replaces spinner when ready
- **WHEN** the active item's data finishes loading
- **THEN** the loading indicator is replaced by the item's content

View File

@@ -0,0 +1,38 @@
## 1. Маршруты и конфиг
- [x] 1.1 Добавить в `shared/config/routes.ts` константы вложенных путей профиля (`PROFILE_DETAILS = '/profile/details'`, `PROFILE_SECURITY`, `PROFILE_MNEMONIC`, `PROFILE_TRANSACTIONS`); сохранить `TRANSACTIONS` для обратного редиректа.
- [x] 1.2 В `app/providers/RouterProvider.tsx` обернуть `ProfilePage` в `<WalletLayout footer />` и описать вложенные маршруты: `index``<Navigate to="details" replace />`, `details`, `security`, `mnemonic`, `transactions`.
- [x] 1.3 Заменить маршрут `/transactions` на `<Navigate to="/profile/transactions" replace />`; убрать прямой рендер `TransactionsPage` по `/transactions`.
- [x] 1.4 Добавить поясняющие комментарии о двух уровнях `<Outlet/>` (WalletLayout → ProfilePage).
## 2. Layout страницы профиля
- [x] 2.1 Переработать `pages/profile/ui/ProfilePage.tsx` в layout: убрать собственный `WalletHeader`; двухколоночная разметка — слева `ProfileMenu`, справа `KycBanner` над `<Outlet/>`.
- [x] 2.2 Обновить `pages/profile/ui/ProfilePage.module.css`: колонки ~25% / ~75% + `gap`; перенести медиа-брейкпоинты (< 1024px — стек в одну колонку, < 640px — паддинги).
## 3. Боковое меню (widget)
- [x] 3.1 Создать `widgets/profile/ui/ProfileMenu.tsx`: сверху закреплённый `ProfileSummary`, ниже список пунктов через `NavLink` (Данные профиля, Безопасность, Мнемоническая фраза, Транзакции) с подсветкой активного (`aria-current`/класс).
- [x] 3.2 Создать `widgets/profile/ui/ProfileMenu.module.css` (список, активное состояние, отступы).
- [x] 3.3 Экспортировать `ProfileMenu` из `widgets/profile/index.ts`.
## 4. Контент-пункты
- [x] 4.1 Создать компонент-пункт «Данные профиля» (рендерит `<ProfileDetails/>`); показывать `Spinner`, пока `useMe` грузится.
- [x] 4.2 Создать компонент-пункт «Безопасность» (`<SecuritySection/>`) с состоянием загрузки.
- [x] 4.3 Создать компонент-пункт «Мнемоническая фраза» (`<MnemonicSection/>`) с состоянием загрузки.
- [x] 4.4 Вынести содержимое `pages/transactions/ui/TransactionsPage.tsx` (список + табы «Транзакции/Заявки» для юр. лиц через `useMe`) в переиспользуемый блок и подключить как компонент-пункт «Транзакции»; показывать `Spinner` во время загрузки.
## 5. Состояние загрузки
- [x] 5.1 Заменить `if (!data) return null` в блоках профиля на отображение `<Spinner label="Загрузка" />` в области контента (меню остаётся доступным).
- [x] 5.2 Убедиться, что `Spinner` центрируется в правой колонке (использовать `fullscreen`/класс в пределах контента).
## 6. Проверка
- [x] 6.1 `npm run build` (tsc) проходит без ошибок типов и сборки.
- [ ] 6.2 Ручная проверка deep-link: прямой переход на `/profile/details`, `/profile/security`, `/profile/mnemonic`, `/profile/transactions` открывает нужный пункт.
- [ ] 6.3 `/profile` редиректит на `/profile/details`; `/transactions` редиректит на `/profile/transactions`.
- [ ] 6.4 Кнопка «Назад» переключает между ранее открытыми пунктами; активный пункт меню подсвечен.
- [ ] 6.5 Транзакции: для юр. лица видны табы «Транзакции/Заявки», для физлица — только список.
- [ ] 6.6 Мобильный вид (< 1024px): меню и контент схлопываются в одну колонку; `KycBanner` и `Spinner` отображаются корректно.

51
openspec/config.yaml Normal file
View File

@@ -0,0 +1,51 @@
schema: spec-driven
# Project context (optional)
# This is shown to AI when creating artifacts.
# Add your tech stack, conventions, style guides, domain knowledge, etc.
context: |
Project: elcsa frontend — a crypto/finance web app (currency converter,
wallet, networks, auth) for the ЭКСА platform.
Tech stack:
- React 19 + Vite, TypeScript (strict, tsc -b before build)
- TanStack Query (React Query) for server state
- React Router for routing
- Plain CSS Modules (.module.css) — NO Tailwind, NO CSS-in-JS
- Design tokens live in src/app/styles/variables.css
Architecture — Feature-Sliced Design (FSD). Layers are strictly ordered;
a lower layer must never import from a higher one:
app → pages → widgets → features → entities → shared
Path aliases map to layers: @app/* @pages/* @widgets/* @features/*
@entities/* @shared/*. Each widget/feature owns its model/, ui/ and a
barrel index.ts.
Key conventions:
- Auth is two-step email+code for both register and login. Access token is
kept in an in-memory tokenStore (NOT localStorage); refreshed via an
HttpOnly cookie against the auth service. Every request attaches a cached
CSRF token and retries once on 401 after a silent refresh.
- Reusable UI lives in shared/ui (Button, PrimaryButton, FormField, Pill,
Title, TokenIcon, Notification), each with its own CSS Module.
- Routes are centralized in shared/config/routes.ts (ROUTES const).
ProtectedRoute / GuestRoute guard auth-only and guest-only pages.
- VITE_API_URL must be set (src/shared/config/env.ts).
- No test runner is configured.
# Per-artifact rules (optional)
# Add custom rules for specific artifacts.
rules:
proposal:
- Keep it concise and focused on user-facing behavior and the "why".
- State which FSD layer(s) the change touches and any cross-layer impact.
specs:
- Write requirements as observable behavior, not implementation details.
- Cover the error/edge paths (network failure, 401 refresh, validation).
design:
- Place new code in the correct FSD layer and justify the placement.
- Reuse existing shared/ui components and shared/api helpers before adding new ones.
- Note any new env vars, routes (ROUTES const), or React Query keys.
tasks:
- Break work into small, verifiable steps ordered by FSD dependency (shared → up).
- Include a "type-check passes (npm run build)" and "npm run lint" step; there are no automated tests.

View File

@@ -0,0 +1,107 @@
# profile-dashboard
## Purpose
Единый раздел «личного кабинета» на `/profile`: боковое меню (25%) и контент (75%) с вложенной маршрутизацией по разделам. Объединяет блоки профиля (данные, безопасность, мнемоника) и транзакции в одну точку входа, с закреплённой сводкой профиля и состоянием загрузки контента.
## Requirements
### Requirement: Two-column dashboard layout
The profile section SHALL be presented as a two-column layout: a left menu column occupying approximately 25% of the available width and a right content column occupying approximately 75%. On viewports narrower than 1024px the two columns SHALL collapse into a single stacked column.
#### Scenario: Wide viewport shows two columns
- **WHEN** an authenticated user opens the profile section on a viewport ≥ 1024px wide
- **THEN** the left menu column (~25%) and the right content column (~75%) are displayed side by side
#### Scenario: Narrow viewport stacks columns
- **WHEN** an authenticated user opens the profile section on a viewport < 1024px wide
- **THEN** the menu and the content are stacked vertically in a single column
### Requirement: Pinned profile summary
The left menu column SHALL display the profile summary (`ProfileSummary` — avatar and identity) pinned at the top, above the menu navigation, and it SHALL remain visible regardless of which menu item is active. On desktop the avatar and the "Добавить фото" button SHALL span the full width of the menu column.
#### Scenario: Summary visible on every item
- **WHEN** the user switches between any menu items
- **THEN** the profile summary remains displayed at the top of the left column
### Requirement: Menu items for profile sections and transactions
The left menu SHALL list selectable items for: Данные профиля (`ProfileDetails`), Безопасность (`SecuritySection`), Транзакции (transactions content), and Мнемоническая фраза (last item). Selecting an item SHALL render its content in the right column, and the currently active item SHALL be visually highlighted.
#### Scenario: Selecting a menu item shows its content
- **WHEN** the user clicks a menu item
- **THEN** the right column renders that item's content and the clicked item is marked as active
#### Scenario: Transactions appears as a menu item
- **WHEN** the user views the profile menu
- **THEN** a «Транзакции» item is present alongside the profile section items, and selecting it renders the transactions content (list plus the «Транзакции / Заявки» tabs for legal-entity accounts)
### Requirement: Mobile navigation via select
On viewports narrower than 1024px the left menu navigation SHALL be presented as a single select control (the shared `Select` component) instead of the full list, so only the chosen section is shown. Changing the select SHALL navigate to the corresponding section.
#### Scenario: Mobile uses a select
- **WHEN** an authenticated user opens the profile section on a viewport < 1024px wide
- **THEN** the section navigation is a select control reflecting the active section
#### Scenario: Changing the select navigates
- **WHEN** the user picks another section in the select
- **THEN** the app navigates to that section's URL and renders its content
### Requirement: Mnemonic reveal requires explicit action
The «Мнемоническая фраза» item SHALL show the seed-phrase content inline (12-word grid with show/hide and copy), but the mnemonic SHALL be fetched only after the user explicitly requests it via a "Показать мнемонику" button. Until then no mnemonic request is made.
#### Scenario: Mnemonic gated behind a button
- **WHEN** the user opens the «Мнемоническая фраза» item
- **THEN** a warning and a "Показать мнемонику" button are shown, and no mnemonic request has been sent
#### Scenario: Revealing fetches and shows the seed phrase
- **WHEN** the user clicks "Показать мнемонику"
- **THEN** the mnemonic is fetched (a loading indicator is shown) and the seed-phrase content is rendered inline
### Requirement: Per-item routing with default redirect
Each menu item SHALL have its own URL under `/profile` (`/profile/details`, `/profile/security`, `/profile/mnemonic`, `/profile/transactions`) so that the browser Back button and direct links select the corresponding item. Navigating to `/profile` SHALL redirect to the default item `/profile/details`.
#### Scenario: Direct link opens the matching item
- **WHEN** the user navigates directly to `/profile/transactions`
- **THEN** the transactions item is active and its content is shown in the right column
#### Scenario: Bare profile path redirects to default
- **WHEN** the user navigates to `/profile`
- **THEN** the app redirects to `/profile/details` and shows the profile data item
#### Scenario: Back button restores previous item
- **WHEN** the user selects one item and then another, and then presses the browser Back button
- **THEN** the previously active item is restored
### Requirement: Legacy transactions route redirect
The legacy route `/transactions` SHALL redirect to `/profile/transactions` so existing links and bookmarks continue to work.
#### Scenario: Old transactions URL redirects
- **WHEN** the user navigates to `/transactions`
- **THEN** the app redirects to `/profile/transactions`
### Requirement: KYC banner placement
The KYC banner (`KycBanner`) SHALL be displayed above the content in the right column.
#### Scenario: KYC banner shown above content
- **WHEN** the profile section is displayed and the KYC banner is applicable
- **THEN** the banner appears above the active item's content in the right column
### Requirement: Loading state for content
While the data for the active menu item is loading, the right column SHALL show a loading indicator (the shared `Spinner`) while the left menu remains interactive.
#### Scenario: Spinner while data loads
- **WHEN** the active item's data is still loading
- **THEN** a loading indicator is shown in the right column and the user can still navigate to other menu items
#### Scenario: Content replaces spinner when ready
- **WHEN** the active item's data finishes loading
- **THEN** the loading indicator is replaced by the item's content

1
payment.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,13 +1,14 @@
import { Navigate, Outlet, useLocation } from 'react-router-dom'
import { useIsAuthenticated } from '@features/auth'
import { ROUTES } from '@shared/config/routes'
import { Spinner } from '@shared/ui'
export function GuestRoute() {
const { isAuthenticated, isLoading } = useIsAuthenticated()
const location = useLocation()
const from = (location.state as { from?: { pathname: string } })?.from?.pathname ?? ROUTES.WALLET
if (isLoading) return null
if (isLoading) return <Spinner overlay size="lg" label="Загрузка" />
if (isAuthenticated) return <Navigate to={from} replace />
return <Outlet />
}

View File

@@ -1,12 +1,13 @@
import { Navigate, Outlet, useLocation } from 'react-router-dom'
import { useIsAuthenticated } from '@features/auth'
import { ROUTES } from '@shared/config/routes'
import { Spinner } from '@shared/ui'
export function ProtectedRoute() {
const { isAuthenticated, isLoading } = useIsAuthenticated()
const location = useLocation()
if (isLoading) return null
if (isLoading) return <Spinner overlay size="lg" label="Загрузка" />
if (!isAuthenticated) return <Navigate to={ROUTES.LOGIN} state={{ from: location }} replace />
return <Outlet />
}

View File

@@ -1,9 +1,9 @@
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom'
import { HomePage } from '@pages/home'
import { WalletPage } from '@pages/wallet'
import { SwapPage } from '@pages/swap'
import { BridgePage } from '@pages/bridge'
import { ProfilePage } from '@pages/profile'
import { ProfilePage, ProfileDetailsItem, SecurityItem, MnemonicItem, TransactionsItem } from '@pages/profile'
import { LoginPage } from '@pages/login'
import { RegisterPage } from '@pages/register'
import { RegisterTestPage } from '@pages/register-test'
@@ -16,9 +16,9 @@ import { PolitikaPage } from '@pages/politika-personalnyh-dannyh'
import { PolitikaCookiePage } from '@pages/politika-cookie'
import { SoglasiePage } from '@pages/soglasie-personalnyh-dannyh'
import { ReestryPage } from '@pages/reestr-pd-rkn'
import { TransactionsPage } from '@pages/transactions'
import { StakingPage } from '@pages/staking'
import { PoolsPage } from '@pages/pools'
import { NotFoundPage } from '@pages/not-found'
import { WalletLayout } from '@widgets/wallet-layout'
import { ROUTES } from '@shared/config/routes'
import { ScrollToTop } from './ScrollToTop'
@@ -52,17 +52,30 @@ export function RouterProvider() {
<Route element={<WalletLayout footer />}>
<Route path={ROUTES.SWAP} element={<SwapPage />} />
<Route path={ROUTES.BRIDGE} element={<BridgePage />} />
<Route path={ROUTES.TRANSACTIONS} element={<TransactionsPage />} />
<Route path={ROUTES.STAKING} element={<StakingPage />} />
<Route path={ROUTES.POOLS} element={<PoolsPage />} />
{/* Profile dashboard: WalletLayout gives header/footer, ProfilePage
renders the menu + an inner <Outlet/> for the active item. */}
<Route path={ROUTES.PROFILE} element={<ProfilePage />}>
<Route index element={<Navigate to="details" replace />} />
<Route path="details" element={<ProfileDetailsItem />} />
<Route path="security" element={<SecurityItem />} />
<Route path="mnemonic" element={<MnemonicItem />} />
<Route path="transactions" element={<TransactionsItem />} />
</Route>
</Route>
{/* Legacy route — transactions now live inside the profile dashboard. */}
<Route path={ROUTES.TRANSACTIONS} element={<Navigate to={ROUTES.PROFILE_TRANSACTIONS} replace />} />
<Route path={ROUTES.WALLET} element={<WalletPage />} />
<Route path={ROUTES.WALLET_CHAIN} element={<WalletPage />} />
<Route path={ROUTES.PROFILE} element={<ProfilePage />} />
<Route path={ROUTES.SEED_PHRASE} element={<SeedPhrasePage />} />
<Route path={ROUTES.KYC} element={<KycPage />} />
</Route>
<Route path="*" element={<NotFoundPage />} />
</Routes>
</BrowserRouter>
)

View File

@@ -68,8 +68,7 @@
margin: 10px 0;
}
/* Вариант абзаца: предупреждение.
NB: исторический контраст (светлый фон + белый текст) сохранён как было. */
/* Вариант абзаца: предупреждение (тёмный текст на светло-жёлтом фоне). */
.warning {
padding: 15px;
background: #fff3cd;
@@ -77,6 +76,7 @@
border-radius: 4px;
margin: 15px 0;
font-weight: 500;
color: #664d03;
}
/* Вариант абзаца: акцент (был `.confirmation`). */

View File

@@ -95,8 +95,9 @@ export interface OrgAmountRaw {
raw: string
formatted: string
decimals: number
usd_price: string
usd_value: string
// null when pricing is unavailable (e.g. an upstream provider error).
usd_price: string | null
usd_value: string | null
}
export interface OrgWalletBalance {
@@ -107,13 +108,14 @@ export interface OrgWalletBalance {
native_symbol: string
native: OrgAmountRaw
tokens: Record<string, OrgAmountRaw>
total_usd: string
// null when the wallet's balance could not be fetched (see `error`).
total_usd: string | null
error: string | null
}
export interface OrgBalancesResponse {
items: OrgWalletBalance[]
total_usd: string
total_usd: string | null
has_errors: boolean
}

View File

@@ -161,17 +161,61 @@ export interface Payment {
expired_date: string
}
export interface OrderWithPayment {
order: Order
export type SbpWithdrawalStatus =
| 'created'
| 'waiting_usdt'
| 'usdt_underpaid'
| 'usdt_received'
| 'wallet_error'
| 'payout_processing'
| 'payout_completed'
| 'payout_failed'
| 'cancelled'
| 'expired'
export interface SbpWithdrawalOperation {
id: string | null
created_at: string | null
updated_at: string | null
user_id: string | null
bank_id: string | null
bank_name: string | null
phone: string | null
usdt_amount: string | null
rub_amount: string | null
usdt_exchange_rate: string | null
service_fee_rate: string | null
service_fee_usdt: string | null
mozen_order_id: string | null
trace_id: string | null
status: SbpWithdrawalStatus | null
provider_error: string | null
usdt_received_at: string | null
payout_created_at: string | null
payout_completed_at: string | null
}
export type ClientOperationType = 'payment' | 'withdrawal'
export interface ClientOperation {
type: ClientOperationType | string
created_at: string
payment: Payment | null
withdrawal: SbpWithdrawalOperation | null
}
export interface OrdersResponse {
orders: OrderWithPayment[]
export interface ClientOperationsResponse {
status_code: number
operations: ClientOperation[]
limit: number
offset: number
}
export const ORDERS_LIMIT = 20
export const OPERATIONS_LIMIT = 20
export function getOrders(offset: number, limit: number = ORDERS_LIMIT): Promise<OrdersResponse> {
return doPaymentRequest(`/payment/orders?offset=${offset}&limit=${limit}`, {}, true)
export function getClientOperations(
offset: number,
limit: number = OPERATIONS_LIMIT,
): Promise<ClientOperationsResponse> {
return doPaymentRequest(`/payment/payments?offset=${offset}&limit=${limit}`, {}, true)
}

View File

@@ -0,0 +1,15 @@
import { useInfiniteQuery } from '@tanstack/react-query'
import { getClientOperations, OPERATIONS_LIMIT } from '../api/paymentApi'
export function useOperations() {
return useInfiniteQuery({
queryKey: ['payment', 'operations'],
queryFn: ({ pageParam }) => getClientOperations(pageParam as number),
initialPageParam: 0,
getNextPageParam: (lastPage, allPages) => {
if (lastPage.operations.length < OPERATIONS_LIMIT) return undefined
return allPages.length * OPERATIONS_LIMIT
},
staleTime: 30_000,
})
}

View File

@@ -1,15 +0,0 @@
import { useInfiniteQuery } from '@tanstack/react-query'
import { getOrders, ORDERS_LIMIT } from '../api/paymentApi'
export function useOrders() {
return useInfiniteQuery({
queryKey: ['payment', 'orders'],
queryFn: ({ pageParam }) => getOrders(pageParam as number),
initialPageParam: 0,
getNextPageParam: (lastPage, allPages) => {
if (lastPage.orders.length < ORDERS_LIMIT) return undefined
return allPages.length * ORDERS_LIMIT
},
staleTime: 30_000,
})
}

View File

@@ -2,6 +2,20 @@ export { usePaymentConfig } from './hooks/usePaymentConfig'
export { usePaymentQuote } from './hooks/usePaymentQuote'
export { usePaymentQuoteByRub } from './hooks/usePaymentQuoteByRub'
export { useCreateOrder } from './hooks/useCreateOrder'
export { useOrders } from './hooks/useOrders'
export { useOperations } from './hooks/useOperations'
export { useCurrencyConversion } from './model/useCurrencyConversion'
export type { PaymentConfig, PaymentQuote, CreateOrderPayload, OrderResult, Order, Payment, OrderWithPayment, OrderStatus, PaymentStatus } from './api/paymentApi'
export type {
PaymentConfig,
PaymentQuote,
CreateOrderPayload,
OrderResult,
Order,
Payment,
OrderStatus,
PaymentStatus,
ClientOperation,
ClientOperationsResponse,
ClientOperationType,
SbpWithdrawalOperation,
SbpWithdrawalStatus,
} from './api/paymentApi'

View File

@@ -13,7 +13,9 @@ export function useWalletBalance(chain: Chain) {
return useQuery({
queryKey: ['wallet', 'balance', chain, isLegal ? 'org' : 'self'],
queryFn: isLegal ? () => getOrgWalletBalance(chain) : () => getWalletBalance(chain),
enabled: isLegal ? ready : true,
// Wait for `me` before firing: otherwise a legal_entity account would hit
// the cryptowallet endpoint during the brief window before account_type is known.
enabled: ready,
staleTime: 30_000,
})
}
@@ -48,7 +50,7 @@ export function useWalletAddresses() {
return useQuery({
queryKey: ['wallet', 'addresses', isLegal ? 'org' : 'self'],
queryFn: isLegal ? getOrgWalletAddresses : getWalletAddresses,
enabled: isLegal ? ready : true,
enabled: ready,
staleTime: 10 * 60 * 1000,
})
}
@@ -58,7 +60,7 @@ export function usePortfolio() {
return useQuery({
queryKey: ['wallet', 'portfolio', isLegal ? 'org' : 'self'],
queryFn: isLegal ? getOrgPortfolio : getPortfolio,
enabled: isLegal ? ready : true,
enabled: ready,
staleTime: 30_000,
})
}
@@ -104,12 +106,16 @@ export function useCreateWallet() {
return useMutation({ mutationFn: createWallet })
}
export function useRevealMnemonic() {
// `enabled` gates the request so callers can require an explicit user action
// (e.g. a "Показать" button) before the mnemonic is fetched. Defaults to true
// to preserve the standalone /seed-phrase page behavior.
export function useRevealMnemonic(enabled = true) {
return useQuery({
queryKey: ['wallet', 'mnemonic'],
queryFn: revealMnemonic,
staleTime: Infinity,
retry: false,
enabled,
})
}

View File

@@ -1,3 +1,5 @@
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import { About } from '@widgets/about'
import { Converter } from '@widgets/currency-converter'
import { Footer } from '@widgets/footer'
@@ -6,6 +8,16 @@ import { Hero } from '@widgets/hero'
import { NetworksTable } from '@widgets/networks-table'
export function HomePage() {
const location = useLocation()
useEffect(() => {
if ((location.state as { scrollTo?: string } | null)?.scrollTo === 'about') {
requestAnimationFrame(() => {
document.getElementById('about')?.scrollIntoView({ behavior: 'smooth' })
})
}
}, [location.state])
return (
<>
<Header />

View File

@@ -0,0 +1 @@
export { NotFoundPage } from './ui/NotFoundPage'

View File

@@ -0,0 +1,143 @@
.page {
position: relative;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
/* extra top padding clears the fixed header overlay */
padding: 120px 20px 80px;
box-sizing: border-box;
overflow: hidden;
}
/* ---- Falling coins (decorative background) ---- */
.rain {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 0;
}
.drop {
position: absolute;
top: -80px;
opacity: 0.55;
animation-name: fall;
animation-timing-function: linear;
animation-iteration-count: infinite;
filter: drop-shadow(0 6px 16px rgba(0, 0, 0, 0.35));
}
@keyframes fall {
0% {
transform: translateY(-80px) rotate(0deg);
opacity: 0;
}
10% {
opacity: 0.55;
}
90% {
opacity: 0.55;
}
100% {
transform: translateY(85vh) rotate(360deg);
opacity: 0;
}
}
/* ---- Foreground content ---- */
.content {
position: relative;
z-index: 1;
text-align: center;
max-width: 520px;
}
.code {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
}
.digit {
font-family: var(--font-mono);
font-size: 160px;
font-weight: 800;
line-height: 1;
color: var(--text-primary);
text-shadow: 0 8px 40px rgba(74, 109, 255, 0.4);
}
/* The middle "0" is a coin that flips like it's spinning in the air. */
.coin {
display: inline-flex;
animation: flip 2.6s ease-in-out infinite;
transform-style: preserve-3d;
filter: drop-shadow(0 12px 30px rgba(247, 147, 26, 0.45));
}
@keyframes flip {
0%,
100% {
transform: rotateY(0deg) translateY(0);
}
50% {
transform: rotateY(180deg) translateY(-16px);
}
}
.title {
margin: 36px 0 12px;
font-size: 28px;
font-weight: 700;
color: var(--text-primary);
}
.subtitle {
margin: 0 0 32px;
font-size: 16px;
line-height: 1.5;
color: var(--text-secondary);
}
.button {
display: inline-block;
padding: 14px 32px;
border-radius: 12px;
background: var(--interactive);
color: var(--text-primary);
font-size: 16px;
font-weight: 600;
text-decoration: none;
transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.button:hover {
background: var(--highlight);
transform: translateY(-2px);
box-shadow: 0 10px 28px rgba(0, 212, 255, 0.35);
}
@media (max-width: 600px) {
.digit {
font-size: 96px;
}
.coin > :global(div) {
width: 88px !important;
height: 88px !important;
font-size: 40px !important;
}
.title {
font-size: 22px;
}
}
@media (prefers-reduced-motion: reduce) {
.drop,
.coin {
animation: none;
}
}

View File

@@ -0,0 +1,78 @@
import { Link } from 'react-router-dom'
import { Header } from '@widgets/header'
import { Footer } from '@widgets/footer'
import { TokenIcon } from '@shared/ui/TokenIcon'
import { ROUTES } from '@shared/config/routes'
import styles from './NotFoundPage.module.css'
/** Decorative coin set — purely visual, no live rates. */
const COINS = [
{ letter: '₿', color: '#f7931a' },
{ letter: 'Ξ', color: '#627eea' },
{ letter: '₮', color: '#26a17b' },
{ letter: '◎', color: '#9945ff' },
{ letter: '$', color: '#2775ca' },
{ letter: '₽', color: '#4a6dff' },
{ letter: 'Ʉ', color: '#00d4ff' },
]
/** Pre-baked rain layout so the scene looks the same on every render. */
const RAIN = [
{ left: 6, size: 34, delay: 0, duration: 7.5 },
{ left: 18, size: 26, delay: 2.1, duration: 9 },
{ left: 29, size: 44, delay: 4.3, duration: 6.5 },
{ left: 41, size: 22, delay: 1.2, duration: 10 },
{ left: 54, size: 38, delay: 3.4, duration: 8 },
{ left: 67, size: 28, delay: 0.6, duration: 9.5 },
{ left: 78, size: 48, delay: 2.8, duration: 7 },
{ left: 88, size: 24, delay: 5, duration: 8.5 },
{ left: 95, size: 32, delay: 1.7, duration: 9.2 },
]
export function NotFoundPage() {
return (
<>
<Header />
<main className={styles.page}>
<div className={styles.rain} aria-hidden="true">
{RAIN.map((coin, i) => {
const token = COINS[i % COINS.length]
return (
<span
key={i}
className={styles.drop}
style={{
left: `${coin.left}%`,
animationDelay: `${coin.delay}s`,
animationDuration: `${coin.duration}s`,
}}
>
<TokenIcon letter={token.letter} color={token.color} size={coin.size} />
</span>
)
})}
</div>
<div className={styles.content}>
<div className={styles.code} aria-hidden="true">
<span className={styles.digit}>4</span>
<span className={styles.coin}>
<TokenIcon letter="₿" color="#f7931a" size={140} />
</span>
<span className={styles.digit}>4</span>
</div>
<h1 className={styles.title}>Такой страницы не существует</h1>
<p className={styles.subtitle}>
Похоже, курс этого маршрута обнулился. Проверьте адрес или вернитесь на главную.
</p>
<Link to={ROUTES.HOME} className={styles.button}>
На главную
</Link>
</div>
</main>
<Footer />
</>
)
}

View File

@@ -8,7 +8,7 @@ export const politikaCookieDoc: LegalDocData = {
blocks: [
{
kind: 'text',
text: 'Настоящая Политика использования файлов cookie устанавливает порядок обработки файлов cookie и содержащихся в них персональных данных ООО «БИТФОРС» при использовании пользователями интернет-ресурса https://bitforce-foundation.ru.',
text: 'Настоящая Политика использования файлов cookie устанавливает порядок обработки файлов cookie и содержащихся в них персональных данных ООО «ЭКСА» при использовании пользователями интернет-ресурса https://elcsa.ru.',
},
{
kind: 'text',
@@ -27,7 +27,7 @@ export const politikaCookieDoc: LegalDocData = {
{
kind: 'infoBox',
lines: [
'ООО «БИТФОРС»',
'ООО «ЭКСА»',
'ИНН: 9810001062',
'ОГРН: 1257800060990',
'Юридический адрес: 196246, город Санкт-Петербург, Московское ш, д. 25 к. 1 литера В, помещ. 3-н',
@@ -315,11 +315,11 @@ export const politikaCookieDoc: LegalDocData = {
{
kind: 'infoBox',
lines: [
'ООО «БИТФОРС»',
'ООО «ЭКСА»',
'ИНН: 9810001062',
'ОГРН: 1257800060990',
'Юридический адрес: 196246, город Санкт-Петербург, Московское ш, д. 25 к. 1 литера В, помещ. 3-н',
'Email компании: company@bitforcefoundation.ru',
'Email компании: company@elcsa.ru',
],
},
{ kind: 'subheading', text: 'Порядок рассмотрения обращений:' },

View File

@@ -2,14 +2,14 @@ import type { LegalDocData } from '@entities/legal-doc'
export const politikaPersonalnyhDannyhDoc: LegalDocData = {
title: 'ПОЛИТИКА ОБРАБОТКИ ПЕРСОНАЛЬНЫХ ДАННЫХ',
subtitle: 'ООО «БИТФОРС»',
subtitle: 'ООО «ЭКСА»',
sections: [
{
title: '1. Общие положения',
blocks: [
{
kind: 'text',
text: 'Настоящая Политика обработки персональных данных разработана в соответствии с Федеральным законом от 27.07.2006 № 152-ФЗ «О персональных данных» и определяет порядок обработки персональных данных и меры по обеспечению безопасности персональных данных, предпринимаемые ООО «БИТФОРС».',
text: 'Настоящая Политика обработки персональных данных разработана в соответствии с Федеральным законом от 27.07.2006 № 152-ФЗ «О персональных данных» и определяет порядок обработки персональных данных и меры по обеспечению безопасности персональных данных, предпринимаемые ООО «ЭКСА».',
},
{
kind: 'text',
@@ -41,7 +41,7 @@ export const politikaPersonalnyhDannyhDoc: LegalDocData = {
},
{
term: 'Пользователь',
text: '— любой посетитель веб-сайта https://bitforce-foundation.ru.',
text: '— любой посетитель веб-сайта https://elcsa.ru.',
},
],
},
@@ -53,13 +53,13 @@ export const politikaPersonalnyhDannyhDoc: LegalDocData = {
{
kind: 'list',
items: [
'Полное наименование: Общество с ограниченной ответственностью «БИТФОРС»',
'Сокращенное наименование: ООО «БИТФОРС»',
'Полное наименование: Общество с ограниченной ответственностью «ЭКСА»',
'Сокращенное наименование: ООО «ЭКСА»',
'ИНН: 9810001062',
'ОГРН: 1257800060990',
'Юридический адрес: 196246, город Санкт-Петербург, Московское шоссе, дом 25, корпус 1, литера В, помещение 3-н',
'Электронная почта: company@bitforcefoundation.ru',
'Веб-сайт: https://bitforce-foundation.ru',
'Электронная почта: company@elcsa.ru',
'Веб-сайт: https://elcsa.ru',
],
},
],
@@ -352,7 +352,7 @@ export const politikaPersonalnyhDannyhDoc: LegalDocData = {
kind: 'infoBox',
lines: [
'Почтовый адрес: 196246, г. Санкт-Петербург, Московское ш., д. 25, к. 1, лит. В, пом. 3-н',
'Электронная почта: company@bitforcefoundation.ru',
'Электронная почта: company@elcsa.ru',
],
},
],

View File

@@ -1 +1,5 @@
export { ProfilePage } from './ui/ProfilePage'
export { ProfileDetailsItem } from './ui/items/ProfileDetailsItem'
export { SecurityItem } from './ui/items/SecurityItem'
export { MnemonicItem } from './ui/items/MnemonicItem'
export { TransactionsItem } from './ui/items/TransactionsItem'

View File

@@ -1,30 +1,29 @@
.page {
min-height: 100vh;
display: flex;
flex-direction: column;
background: var(--bg-deep);
}
.main {
max-width: 1024px;
max-width: 1200px;
width: 100%;
margin: 0 auto;
padding: 40px 32px 60px;
display: flex;
display: grid;
grid-template-columns: 25% 1fr;
gap: 32px;
align-items: start;
}
.sections {
flex: 1;
.menu {
min-width: 0;
}
.content {
min-width: 0;
display: flex;
flex-direction: column;
gap: 16px;
}
/* < 1024px: avatar + sections stack into a single column */
/* < 1024px: menu and content stack into a single column */
@media (max-width: 1023px) {
.main {
flex-direction: column;
.page {
grid-template-columns: 1fr;
padding: 24px 20px 40px;
gap: 24px;
}
@@ -32,7 +31,7 @@
/* < 640px: tighter page padding */
@media (max-width: 639px) {
.main {
.page {
padding: 16px 16px 40px;
}
}

View File

@@ -1,19 +1,19 @@
import { WalletHeader } from '@widgets/wallet-header'
import { KycBanner, ProfileSummary, ProfileDetails, SecuritySection, MnemonicSection } from '@widgets/profile'
import { Outlet } from 'react-router-dom'
import { KycBanner, ProfileMenu } from '@widgets/profile'
import styles from './ProfilePage.module.css'
// Profile dashboard layout. The outer WalletLayout (see RouterProvider) renders
// the header/footer; here we split into a ~25% menu column and a ~75% content
// column. The active item is rendered into the inner <Outlet/>.
export function ProfilePage() {
return (
<div className={styles.page}>
<WalletHeader />
<KycBanner />
<main className={styles.main}>
<ProfileSummary />
<div className={styles.sections}>
<ProfileDetails />
<SecuritySection />
<MnemonicSection />
<div className={styles.menu}>
<ProfileMenu />
</div>
<main className={styles.content}>
<KycBanner />
<Outlet />
</main>
</div>
)

View File

@@ -0,0 +1,6 @@
.hint {
margin: 0;
font-size: 14px;
line-height: 1.6;
color: var(--text-secondary);
}

View File

@@ -0,0 +1,32 @@
import { useState } from 'react'
import { useRevealMnemonic } from '@features/wallet'
import { SeedPhraseWidget } from '@widgets/seed-phrase'
import { ProfileSection } from '@widgets/profile'
import { Button, Spinner } from '@shared/ui'
import styles from './MnemonicItem.module.css'
// «Мнемоническая фраза» dashboard item. The mnemonic is fetched only after the
// user explicitly clicks "Показать мнемонику" (the query stays disabled until
// then), then the seed-phrase content is shown inline.
export function MnemonicItem() {
const [revealed, setRevealed] = useState(false)
const { data: mnemonic, isLoading } = useRevealMnemonic(revealed)
if (!revealed) {
return (
<ProfileSection
title="Мнемоническая фраза"
actions={<Button variant="danger" onClick={() => setRevealed(true)}>Показать мнемонику</Button>}
>
<p className={styles.hint}>
Сид-фраза из 12 слов для восстановления кошелька. Никогда не передавайте её третьим лицам.
</p>
</ProfileSection>
)
}
if (isLoading) return <Spinner fullscreen label="Загрузка" />
const words = mnemonic ? mnemonic.split(' ') : []
return <SeedPhraseWidget words={words} showProfileLink={false} />
}

View File

@@ -0,0 +1,11 @@
import { useMe } from '@features/auth'
import { ProfileDetails } from '@widgets/profile'
import { Spinner } from '@shared/ui'
// «Данные профиля» — default dashboard item. Shows a spinner while the profile
// data is still loading, then the details form.
export function ProfileDetailsItem() {
const { isLoading } = useMe()
if (isLoading) return <Spinner fullscreen label="Загрузка" />
return <ProfileDetails />
}

View File

@@ -0,0 +1,10 @@
import { useMe } from '@features/auth'
import { SecuritySection } from '@widgets/profile'
import { Spinner } from '@shared/ui'
// «Безопасность» dashboard item.
export function SecurityItem() {
const { isLoading } = useMe()
if (isLoading) return <Spinner fullscreen label="Загрузка" />
return <SecuritySection />
}

View File

@@ -0,0 +1,7 @@
import { TransactionsPanel } from '@widgets/transactions-panel'
// «Транзакции» dashboard item — the shared transactions panel (list + tabs).
// The panel handles its own loading state.
export function TransactionsItem() {
return <TransactionsPanel />
}

View File

@@ -2,14 +2,14 @@ import type { LegalDocData } from '@entities/legal-doc'
export const publichnayaOfertaDoc: LegalDocData = {
title: 'ПУБЛИЧНЫЙ ДОГОВОР ОФЕРТЫ',
subtitle: 'ООО БИТФОРС',
subtitle: 'ООО ЭКСА',
sections: [
{
title: 'Агентский договор',
blocks: [
{
kind: 'text',
text: 'Настоящая оферта на заключение агентского договора (далее Оферта, Договор) является публичным предложением Общества с ограниченной ответственностью «БИТФОРС», заключить договор на условиях и в порядке, определенных настоящей Офертой.',
text: 'Настоящая оферта на заключение агентского договора (далее Оферта, Договор) является публичным предложением Общества с ограниченной ответственностью «ЭКСА», заключить договор на условиях и в порядке, определенных настоящей Офертой.',
},
{
kind: 'text',
@@ -49,7 +49,7 @@ export const publichnayaOfertaDoc: LegalDocData = {
},
{
term: 'Оферта (Договор)',
text: ' настоящий документ, который отражает предложение и намерение ООО «БИТФОРС» считать заключенным договор с лицом, которым будет принято предложение на условиях, изложенных ниже.',
text: ' настоящий документ, который отражает предложение и намерение ООО «ЭКСА» считать заключенным договор с лицом, которым будет принято предложение на условиях, изложенных ниже.',
},
],
},
@@ -221,13 +221,13 @@ export const publichnayaOfertaDoc: LegalDocData = {
{
kind: 'infoBox',
lines: [
'Общество с ограниченной ответственностью «БИТФОРС»',
'Общество с ограниченной ответственностью «ЭКСА»',
'196246, г. Санкт-Петербург, Московский р-н, Московское шоссе, д.25к1 литера в, помещ. 3-Н',
'ИНН / КПП: 9810001062 / 781001001',
'ОГРН: 1257800060990',
'ОКПО / ОКАТО / ОКТМО: 68342261 / 40284000000 / 40377000000',
'Руководитель: Кленин Михаил Васильевич',
'Электронная почта: company@bitforcefoundation.ru',
'Электронная почта: company@elcsa.ru',
'Наименование банка: ФИЛИАЛ "САНКТ-ПЕТЕРБУРГСКИЙ" АО "АЛЬФА-БАНК"',
'Корреспондентский счет: 30101810600000000786',
'БИК: 044030786',

View File

@@ -2,7 +2,7 @@ import type { LegalDocData } from '@entities/legal-doc'
export const reestrDoc: LegalDocData = {
title: 'Реестр операторов персональных данных',
subtitle: 'ООО «БИТФОРС»',
subtitle: 'ООО «ЭКСА»',
sections: [
{
blocks: [
@@ -31,14 +31,14 @@ export const reestrDoc: LegalDocData = {
{
kind: 'infoBox',
lines: [
{ strong: 'Наименование:', text: 'ООО «БИТФОРС»' },
{ strong: 'Наименование:', text: 'ООО «ЭКСА»' },
{ strong: 'ИНН:', text: '9810001062' },
{ strong: 'ОГРН:', text: '1257800060990' },
{
strong: 'Юридический адрес:',
text: '196246, город Санкт-Петербург, Московское шоссе, дом 25, корпус 1, литера В, помещение 3-н',
},
{ strong: 'Контактная информация:', text: 'company@bitforcefoundation.ru' },
{ strong: 'Контактная информация:', text: 'company@elcsa.ru' },
],
},
],

View File

@@ -2,14 +2,14 @@ import type { LegalDocData } from '@entities/legal-doc'
export const soglasieDoc: LegalDocData = {
title: 'СОГЛАСИЕ НА ОБРАБОТКУ ПЕРСОНАЛЬНЫХ ДАННЫХ',
subtitle: 'ООО «БИТФОРС»',
subtitle: 'ООО «ЭКСА»',
sections: [
{
title: 'Преамбула',
blocks: [
{
kind: 'text',
text: 'Я, субъект персональных данных, действуя своей волей и в своем интересе, в соответствии с требованиями Федерального закона от 27.07.2006 № 152-ФЗ «О персональных данных», предоставляю ООО «БИТФОРС» согласие на обработку моих персональных данных на условиях и для целей, определенных настоящим Согласием.',
text: 'Я, субъект персональных данных, действуя своей волей и в своем интересе, в соответствии с требованиями Федерального закона от 27.07.2006 № 152-ФЗ «О персональных данных», предоставляю ООО «ЭКСА» согласие на обработку моих персональных данных на условиях и для целей, определенных настоящим Согласием.',
},
],
},
@@ -19,12 +19,12 @@ export const soglasieDoc: LegalDocData = {
{
kind: 'infoBox',
lines: [
'Полное наименование: Общество с ограниченной ответственностью «БИТФОРС»',
'Полное наименование: Общество с ограниченной ответственностью «ЭКСА»',
'ИНН: 9810001062',
'ОГРН: 1257800060990',
'Юридический адрес: 196246, город Санкт-Петербург, Московское шоссе, дом 25, корпус 1, литера В, помещение 3-н',
'Электронная почта: company@bitforcefoundation.ru',
'Веб-сайт: https://bitforce-foundation.ru',
'Электронная почта: company@elcsa.ru',
'Веб-сайт: https://elcsa.ru',
],
},
],
@@ -280,7 +280,7 @@ export const soglasieDoc: LegalDocData = {
{
kind: 'list',
items: [
'Обращения направляются на адрес: company@bitforcefoundation.ru',
'Обращения направляются на адрес: company@elcsa.ru',
'Обращения рассматриваются в течение 30 дней',
'При необходимости срок может быть продлен на 30 дней',
],
@@ -323,9 +323,9 @@ export const soglasieDoc: LegalDocData = {
kind: 'infoBox',
lines: [
'Почтовый адрес: 196246, г. Санкт-Петербург, Московское ш., д. 25, к. 1, лит. В, пом. 3-н',
'Электронная почта: company@bitforcefoundation.ru',
'Электронная почта: company@elcsa.ru',
'Ответственное лицо: Кленин Михаил Васильевич',
'Официальный сайт: https://bitforce-foundation.ru',
'Официальный сайт: https://elcsa.ru',
],
},
{ kind: 'subheading', text: '9.5. Подтверждение понимания:' },

View File

@@ -1,45 +1,15 @@
import { useState } from 'react'
import { useMe } from '@features/auth'
import { TransactionsList } from '@widgets/transactions-list'
import { PurchaseRequestsList } from '@widgets/purchase-requests-list'
import { TransactionsPanel } from '@widgets/transactions-panel'
import styles from './TransactionsPage.module.css'
type Tab = 'transactions' | 'requests'
// The standalone /transactions route now redirects to /profile/transactions
// (see RouterProvider). This page is kept as a thin wrapper around the shared
// TransactionsPanel for any direct/legacy usage.
export function TransactionsPage() {
const { data } = useMe()
const [tab, setTab] = useState<Tab>('transactions')
const isLegal = !!data && data.account_type !== 'individual'
const activeTab: Tab = isLegal ? tab : 'transactions'
return (
<div className={styles.inner}>
<div className={styles.glow} />
<h1 className={styles.title}>Транзакции</h1>
{isLegal && (
<div className={styles.tabs}>
<button
type="button"
className={styles.tab}
data-active={activeTab === 'transactions' || undefined}
onClick={() => setTab('transactions')}
>
Транзакции
</button>
<button
type="button"
className={styles.tab}
data-active={activeTab === 'requests' || undefined}
onClick={() => setTab('requests')}
>
Заявки
</button>
</div>
)}
{activeTab === 'transactions' ? <TransactionsList /> : <PurchaseRequestsList />}
<TransactionsPanel />
</div>
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="151" height="172" viewBox="0 0 151 172" fill="none">
<path d="M144.518 39.2113L82.214 3.03438C80.1932 1.87961 77.9919 1.28418 75.7545 1.28418C73.5352 1.28418 71.3158 1.87961 69.3311 3.03438L7.00937 39.2474C3.05788 41.5569 0.585938 45.8151 0.585938 50.4162V122.842C0.585938 127.443 3.05788 131.756 7.00937 134.047L18.2143 140.561L34.5616 150.052L38.2243 139.965L71.8932 47.1143C72.2 46.2121 71.5504 45.2378 70.54 45.2378H54.752C53.5792 45.2378 52.4966 45.9775 52.1177 47.0782L21.8951 130.474L12.2961 124.899C11.5743 124.484 11.1232 123.708 11.1232 122.878V50.4162C11.1232 49.5862 11.5743 48.8103 12.2961 48.3953L74.6178 12.1824C74.9606 11.9658 75.3756 11.8756 75.7725 11.8756C76.1875 11.8756 76.5665 11.9839 76.9454 12.1824L139.285 48.3953C140.007 48.8103 140.458 49.5862 140.458 50.4162V122.842C140.458 123.672 140.007 124.448 139.285 124.863L129.794 130.384L104.822 61.4768C104.371 60.2137 102.639 60.2137 102.188 61.4768L93.9602 84.1392C93.7257 84.7707 93.7257 85.4744 93.9602 86.0879L113.447 139.875L106.969 143.646L91.0192 99.6023C90.5681 98.3393 88.8359 98.3393 88.3848 99.6023L80.1571 122.265C79.9225 122.896 79.9225 123.6 80.1571 124.213L90.6403 153.137L76.9634 161.094C76.6206 161.311 76.2056 161.401 75.7906 161.401C75.3756 161.401 74.9967 161.293 74.6178 161.094L61.1033 153.227L99.5537 47.1323C99.8965 46.1941 99.2108 45.2017 98.2365 45.2017H82.4486C81.2758 45.2017 80.1932 45.9414 79.8142 47.0421L44.756 143.718L41.0932 153.805L57.4405 163.295L69.3672 170.224C71.3519 171.379 73.5713 171.974 75.7906 171.974C78.0099 171.974 80.2292 171.379 82.214 170.224L144.554 134.011C148.541 131.701 150.977 127.443 150.977 122.806V50.4162C150.977 45.8151 148.505 41.5028 144.554 39.2113H144.518Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 2496 2496" style="enable-background:new 0 0 2496 2496;" xml:space="preserve">
<g>
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#F0B90B;" d="M1248,0c689.3,0,1248,558.7,1248,1248s-558.7,1248-1248,1248
S0,1937.3,0,1248S558.7,0,1248,0L1248,0z"/>
<path style="fill:#FFFFFF;" d="M685.9,1248l0.9,330l280.4,165v193.2l-444.5-260.7v-524L685.9,1248L685.9,1248z M685.9,918v192.3
l-163.3-96.6V821.4l163.3-96.6l164.1,96.6L685.9,918L685.9,918z M1084.3,821.4l163.3-96.6l164.1,96.6L1247.6,918L1084.3,821.4
L1084.3,821.4z"/>
<path style="fill:#FFFFFF;" d="M803.9,1509.6v-193.2l163.3,96.6v192.3L803.9,1509.6L803.9,1509.6z M1084.3,1812.2l163.3,96.6
l164.1-96.6v192.3l-164.1,96.6l-163.3-96.6V1812.2L1084.3,1812.2z M1645.9,821.4l163.3-96.6l164.1,96.6v192.3l-164.1,96.6V918
L1645.9,821.4L1645.9,821.4L1645.9,821.4z M1809.2,1578l0.9-330l163.3-96.6v524l-444.5,260.7v-193.2L1809.2,1578L1809.2,1578
L1809.2,1578z"/>
<polygon style="fill:#FFFFFF;" points="1692.1,1509.6 1528.8,1605.3 1528.8,1413 1692.1,1316.4 1692.1,1509.6 "/>
<path style="fill:#FFFFFF;" d="M1692.1,986.4l0.9,193.2l-281.2,165v330.8l-163.3,95.7l-163.3-95.7v-330.8l-281.2-165V986.4
L968,889.8l279.5,165.8l281.2-165.8l164.1,96.6H1692.1L1692.1,986.4z M803.9,656.5l443.7-261.6l444.5,261.6l-163.3,96.6
l-281.2-165.8L967.2,753.1L803.9,656.5L803.9,656.5z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="CIRCLE_OUTLINE_BLACK" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FDDE00;}
.st1{fill:#3C2D0C;}
.st2{fill:#E78C19;}
.st3{fill:#EFB99D;}
.st4{fill:#FBFBFB;}
.st5{fill:#E72D36;}
</style>
<circle class="st0" cx="256" cy="256" r="256"/>
<path class="st1" d="M131.4,181c0,0-13.2,16.7-8.8,92.2c0,0-28.9,74-19.1,111.8c9.8,37.7,48,35.8,48,35.8s61.3,53.9,108.3,6.4
c47.1-47.6-39.2-231.9-39.2-231.9l-10.8-63.7c0,0-11.8,9.3-10.3,70.6s-24,18.1-24,18.1L131.4,181z"/>
<path class="st2" d="M136.3,247.7l-16.2,45.6l-5.9,31.9c0,0-20.1,71.1,62.8,70.1c0,0,64.7,57.9,106.9,19.1l11.3-12.3l19.6-30.4
l32.4-96.6c0,0-10.3-66.2-75.5-93.6c0,0-5.4-2.9-15.2,1c0,0-27-60.8-44.1-53.4c0,0-14.7,7.8-2,67.7l-23,10.3
c0,0-25.2-47.8-48.5-38.2C117.2,177.6,136.3,247.7,136.3,247.7z"/>
<path class="st3" d="M220.1,158.9l2,26.5c0,0,1.5,15.2,17.6,9.8c4.6-1.5,8.6-4.7,8.2-9.9c-0.3-3.9-3-7.5-4.8-10.8
c-3.3-6.3-6-13-9.9-19.1c-2-3.1-6.1-10-10.6-9.2C222.6,146.2,219.2,145.2,220.1,158.9z"/>
<path class="st3" d="M149.3,188.7c0.3-0.2,6.9-8.5,20.6,11.7c13.7,20.2,12.3,17.6,12.3,17.6s7.4,8.1-7.7,18.5
c-3.3,2.4-6.9,4.4-10.7,6c-2.4,0.9-4.9,1.4-7.4,1.4c-2.9-0.1-4.2-1.6-4.9-4.3c-2.3-8.8-4.9-17.6-6.2-26.6
C144.3,206,142.3,193.2,149.3,188.7z"/>
<path class="st4" d="M308.5,229.4c0,4.8-7,8.7-15.7,8.7c-8.7,0-15.7-3.9-15.7-8.7s7.2-11.9,15.8-11.9S308.5,224.6,308.5,229.4z"/>
<ellipse transform="matrix(0.4925 -0.8703 0.8703 0.4925 -121.8385 314.1253)" class="st4" cx="208.4" cy="261.5" rx="17.1" ry="11"/>
<path class="st4" d="M240.2,306.7l42.9-22.3c0,0,53.4-27.9,66.4-6.4s0,54.4,0,54.4s-5.6,38.5-44.9,41.9l-21.1,2.9l-27,0.7
c0,0-43.4,2.5-75.3-21.1l-10.1-12.3c0,0-20.3-27.9-6.1-48s62.8,11,62.8,11S234.6,311.2,240.2,306.7z"/>
<circle class="st5" cx="337.5" cy="185.2" r="10.3"/>
<circle class="st5" cx="314.7" cy="159.9" r="10.3"/>
<circle class="st5" cx="278.2" cy="151.8" r="10.3"/>
<path class="st5" d="M286.3,78.8c2.2,30.4-2.2,57.9-9.6,57.9s-17.2-29.7-17.2-57.9c0-11.6,6.1-13.5,13.5-13.5
C280.5,65.3,285.5,67.2,286.3,78.8z"/>
<path class="st5" d="M354.5,97.7c-11.2,28.3-27.1,51.2-33.7,48c-6.6-3.2-2.6-34.2,9.7-59.6c5.1-10.5,11.4-9.5,18-6.3
C355.1,83.1,358.8,86.9,354.5,97.7z"/>
<path class="st5" d="M403.3,152.9c-24.7,17.9-50.3,28.7-54.2,22.4c-3.9-6.3,16.2-30.2,40.1-45.1c9.9-6.1,14.7-1.9,18.6,4.3
C411.6,140.8,412.7,146,403.3,152.9z"/>
<path d="M238.2,276.8c-0.9,0.1-1.8,0.2-2.7,0.3c0.1,0.3,0.2,0.6,0.2,1c0,3.1-4.9,5.7-11,5.9c0,0.3-0.1,0.5,0,0.8
c0.3,3.8,6.9,6.4,14.6,5.8c7.8-0.6,13.9-4.2,13.6-8C252.5,278.8,246,276.2,238.2,276.8z"/>
<path d="M292.4,263.4c-0.9,0.1-1.8,0.2-2.7,0.3c0.1,0.3,0.2,0.6,0.2,1c0,3.1-4.9,5.7-11,5.9c0,0.3-0.1,0.5,0,0.8
c0.3,3.8,6.9,6.4,14.6,5.8c7.8-0.6,13.9-4.2,13.6-8C306.8,265.4,300.2,262.8,292.4,263.4z"/>
<path d="M310.2,279.3c0,0-21.5,6.3-20.2,18.4s27.2,18.4,27.2,18.4s7,2.8,11-3.9c4-6.6,9.9-15.6,8.3-28.5
C336.5,283.7,336,274.1,310.2,279.3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 6H15C16.6569 6 18 7.34315 18 9C18 10.6569 16.6569 12 15 12M10 6V12M10 6H7M10 6V3M15 12H10M15 12C16.6569 12 18 13.3431 18 15C18 16.6569 16.6569 18 15 18H10M10 12V18M10 18H7M10 18V21M13 6V3M13 21V18" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 518 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 336.41 337.42"><defs><style>.cls-1{fill:#f0b90b;stroke:#f0b90b;}</style></defs><title>Asset 1</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M168.2.71l41.5,42.5L105.2,147.71l-41.5-41.5Z"/><path class="cls-1" d="M231.2,63.71l41.5,42.5L105.2,273.71l-41.5-41.5Z"/><path class="cls-1" d="M42.2,126.71l41.5,42.5-41.5,41.5L.7,169.21Z"/><path class="cls-1" d="M294.2,126.71l41.5,42.5L168.2,336.71l-41.5-41.5Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 528 B

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW 2019 (64-Bit) -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100%" height="100%" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
viewBox="0 0 444.44 444.44"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
<g id="Layer_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<path fill="#F5AC37" fill-rule="nonzero" d="M222.22 0c122.74,0 222.22,99.5 222.22,222.22 0,122.74 -99.48,222.22 -222.22,222.22 -122.72,0 -222.22,-99.49 -222.22,-222.22 0,-122.72 99.5,-222.22 222.22,-222.22z"/>
<path fill="#FEFEFD" fill-rule="nonzero" d="M230.41 237.91l84.44 0c1.8,0 2.65,0 2.78,-2.36 0.69,-8.59 0.69,-17.23 0,-25.83 0,-1.67 -0.83,-2.36 -2.64,-2.36l-168.05 0c-2.08,0 -2.64,0.69 -2.64,2.64l0 24.72c0,3.19 0,3.19 3.33,3.19l82.78 0zm77.79 -59.44c0.24,-0.63 0.24,-1.32 0,-1.94 -1.41,-3.07 -3.08,-6 -5.02,-8.75 -2.92,-4.7 -6.36,-9.03 -10.28,-12.92 -1.85,-2.35 -3.99,-4.46 -6.39,-6.25 -12.02,-10.23 -26.31,-17.47 -41.67,-21.11 -7.75,-1.74 -15.67,-2.57 -23.61,-2.5l-74.58 0c-2.08,0 -2.36,0.83 -2.36,2.64l0 49.3c0,2.08 0,2.64 2.64,2.64l160.27 0c0,0 1.39,-0.28 1.67,-1.11l-0.68 0zm0 88.33c-2.36,-0.26 -4.74,-0.26 -7.1,0l-154.02 0c-2.08,0 -2.78,0 -2.78,2.78l0 48.2c0,2.22 0,2.78 2.78,2.78l71.11 0c3.4,0.26 6.8,0.02 10.13,-0.69 10.32,-0.74 20.47,-2.98 30.15,-6.67 3.52,-1.22 6.92,-2.81 10.13,-4.72l0.97 0c16.67,-8.67 30.21,-22.29 38.75,-39.01 0,0 0.97,-2.1 -0.12,-2.65zm-191.81 78.75l0 -0.83 0 -32.36 0 -10.97 0 -32.64c0,-1.81 0,-2.08 -2.22,-2.08l-30.14 0c-1.67,0 -2.36,0 -2.36,-2.22l0 -26.39 32.22 0c1.8,0 2.5,0 2.5,-2.36l0 -26.11c0,-1.67 0,-2.08 -2.22,-2.08l-30.14 0c-1.67,0 -2.36,0 -2.36,-2.22l0 -24.44c0,-1.53 0,-1.94 2.22,-1.94l29.86 0c2.08,0 2.64,0 2.64,-2.64l0 -74.86c0,-2.22 0,-2.78 2.78,-2.78l104.16 0c7.56,0.3 15.07,1.13 22.5,2.5 15.31,2.83 30.02,8.3 43.47,16.11 8.92,5.25 17.13,11.59 24.44,18.89 5.5,5.71 10.46,11.89 14.86,18.47 4.37,6.67 8,13.8 10.85,21.25 0.35,1.94 2.21,3.25 4.15,2.92l24.86 0c3.19,0 3.19,0 3.33,3.06l0 22.78c0,2.22 -0.83,2.78 -3.06,2.78l-19.17 0c-1.94,0 -2.5,0 -2.36,2.5 0.76,8.46 0.76,16.95 0,25.41 0,2.36 0,2.64 2.65,2.64l21.93 0c0.97,1.25 0,2.5 0,3.76 0.14,1.61 0.14,3.24 0,4.85l0 16.81c0,2.36 -0.69,3.06 -2.78,3.06l-26.25 0c-1.83,-0.35 -3.61,0.82 -4.03,2.64 -6.25,16.25 -16.25,30.82 -29.17,42.5 -4.72,4.25 -9.68,8.25 -14.86,11.94 -5.56,3.2 -10.97,6.53 -16.67,9.17 -10.49,4.72 -21.49,8.2 -32.78,10.41 -10.72,1.92 -21.59,2.79 -32.5,2.64l-96.39 0 0 -0.14z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000" width="2500" height="2500"><g fill="#c2a633"><path d="M1024 659H881.12v281.69h224.79v117.94H881.12v281.67H1031c38.51 0 316.16 4.35 315.73-327.72S1077.44 659 1024 659z"/><path d="M1000 0C447.71 0 0 447.71 0 1000s447.71 1000 1000 1000 1000-447.71 1000-1000S1552.29 0 1000 0zm39.29 1540.1H677.14v-481.46H549.48V940.7h127.65V459.21h310.82c73.53 0 560.56-15.27 560.56 549.48 0 574.09-509.21 531.41-509.21 531.41z"/></g></svg>

Before

Width:  |  Height:  |  Size: 484 B

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" ?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 32 32" id="_x3C_Layer_x3E_" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
<![CDATA[
.st0{fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st1{fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
]]>
</style>
<g id="Ethereum_x2C__crypto_x2C__cryptocurrency_1_">
<g id="XMLID_15_">
<polygon class="st1" id="XMLID_8_" points="16.01,1.5 7.62,16.23 16.01,21.5 24.38,16.18 "/>
<line class="st1" id="XMLID_31_" x1="16.01" x2="16.01" y1="30.5" y2="24.1"/>
<polygon class="st1" id="XMLID_12_" points="16.01,30.5 7.62,18.83 16.01,24.1 24.38,18.78 "/>
<polygon class="st1" id="XMLID_30_" points="16.01,12.3 7.62,16.23 16.01,21.5 24.38,16.18 "/>
<line class="st1" id="XMLID_32_" x1="16.01" x2="16.01" y1="1.5" y2="21.5"/>
<polygon class="st1" id="XMLID_192_" points="16.01,1.5 7.62,16.23 16.01,21.5 24.38,16.18 "/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,49 +1,41 @@
import btc from './btc.svg'
import eth from './eth.svg'
import sol from './sol.svg'
import trx from './trx.svg'
import bnb from './bnb.svg'
import arb from './arb.svg'
import bonk from './bonk.svg'
import busd from './busd.svg'
import dai from './dai.svg'
import doge from './doge.svg'
import jup from './jup.svg'
import link from './link.svg'
import orca from './orca.svg'
import popcat from './popcat.svg'
import pyth from './pyth.svg'
import ray from './ray.svg'
import uni from './uni.svg'
import usdc from './usdc.svg'
import usdt from './usdt.svg'
import w from './w.svg'
import wif from './wif.svg'
// Единая точка доступа к логотипам монет.
// Логотипы автоматически подхватываются из этой папки — чтобы добавить новую
// монету, достаточно положить файл `<TICKER>.png` (или `.svg`) рядом с этим
// файлом. Ничего дописывать в код не нужно.
//
// При наличии и PNG, и SVG для одного тикера приоритет отдаётся PNG.
export const COIN_ICONS: Record<string, string> = {
BTC: btc,
ETH: eth,
SOL: sol,
TRX: trx,
BNB: bnb,
ARB: arb,
BONK: bonk,
BUSD: busd,
DAI: dai,
DOGE: doge,
JUP: jup,
LINK: link,
ORCA: orca,
POPCAT: popcat,
PYTH: pyth,
RAY: ray,
UNI: uni,
USDC: usdc,
USDT: usdt,
W: w,
WIF: wif,
type IconModules = Record<string, string>
const svgIcons = import.meta.glob('./*.svg', {
eager: true,
query: '?url',
import: 'default',
}) as IconModules
const pngIcons = import.meta.glob('./*.png', {
eager: true,
query: '?url',
import: 'default',
}) as IconModules
/** Достаёт тикер из пути вида `./usdt.svg` → `USDT`. */
function tickerFromPath(path: string): string {
return path.replace(/^\.\//, '').replace(/\.[^.]+$/, '').toUpperCase()
}
function collect(modules: IconModules, target: Record<string, string>) {
for (const [path, url] of Object.entries(modules)) {
target[tickerFromPath(path)] = url
}
}
/** Карта `ТИКЕР → url логотипа`. PNG перекрывает SVG при совпадении тикера. */
export const COIN_ICONS: Record<string, string> = {}
collect(svgIcons, COIN_ICONS) // сначала svg…
collect(pngIcons, COIN_ICONS) // …затем png перекрывает
/** Вернуть url логотипа по тикеру (регистр не важен), либо undefined. */
export function getCoinIcon(ticker: string): string | undefined {
return COIN_ICONS[ticker.toUpperCase()]
}

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="katman_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 800 800" style="enable-background:new 0 0 800 800;" xml:space="preserve">
<style type="text/css">
.st0{fill:#141726;}
.st1{fill:url(#SVGID_1_);}
.st2{fill:url(#SVGID_2_);}
.st3{fill:url(#SVGID_3_);}
.st4{fill:url(#SVGID_4_);}
.st5{fill:url(#SVGID_5_);}
.st6{fill:url(#SVGID_6_);}
</style>
<circle class="st0" cx="400" cy="400" r="400"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="574.9257" y1="665.8727" x2="248.5257" y2="142.3127" gradientTransform="matrix(1 0 0 -1 0 800)">
<stop offset="0.16" style="stop-color:#C6F462"/>
<stop offset="0.89" style="stop-color:#33D9FF"/>
</linearGradient>
<path class="st1" d="M536,568.9c-66.8-108.5-166.4-170-289.4-195.6c-43.5-9-87.2-8.9-129.4,7.7c-28.9,11.4-33.3,23.4-19.7,53.7
c92.4-21.9,178.4-1.5,258.9,45c81.1,46.9,141.6,112.2,169.1,205c38.6-11.8,43.6-18.3,34.3-54.2C554.3,609.4,547.4,587.4,536,568.9
L536,568.9z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="572.5896" y1="667.3303" x2="246.1996" y2="143.7703" gradientTransform="matrix(1 0 0 -1 0 800)">
<stop offset="0.16" style="stop-color:#C6F462"/>
<stop offset="0.89" style="stop-color:#33D9FF"/>
</linearGradient>
<path class="st2" d="M609.1,480.6c-85.8-125-207.3-194.9-355.8-218.3c-39.3-6.2-79.4-4.5-116.2,14.3c-17.6,9-33.2,20.5-37.4,44.9
c115.8-31.9,219.7-3.7,317.5,53c98.3,57,175.1,133.5,205,251.1c20.8-18.4,24.5-41,19.1-62C633.9,534.8,625.5,504.5,609.1,480.6
L609.1,480.6z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="577.0148" y1="664.5671" x2="250.6247" y2="141.0071" gradientTransform="matrix(1 0 0 -1 0 800)">
<stop offset="0.16" style="stop-color:#C6F462"/>
<stop offset="0.89" style="stop-color:#33D9FF"/>
</linearGradient>
<path class="st3" d="M105,488.6c7.3,16.2,12.1,34.5,23,47.6c5.5,6.7,22.2,4.1,33.8,5.7c1.8,0.2,3.6,0.5,5.4,0.7
c102.9,15.3,184.1,65.1,242.1,152c3.4,5.1,8.9,12.7,13.4,12.7c17.4-0.1,34.9-2.8,52.5-4.5C449,557.5,232.8,438.3,105,488.6
L105,488.6z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="569.0272" y1="669.5518" x2="242.6272" y2="145.9917" gradientTransform="matrix(1 0 0 -1 0 800)">
<stop offset="0.16" style="stop-color:#C6F462"/>
<stop offset="0.89" style="stop-color:#33D9FF"/>
</linearGradient>
<path class="st4" d="M656.6,366.7C599.9,287.4,521.7,234.6,432.9,197c-61.5-26.1-125.2-41.8-192.8-33.7
c-23.4,2.8-45.3,9.5-63.4,24.7c230.9,5.8,404.6,105.8,524,303.3c0.2-13.1,2.2-27.7-2.6-39.5C686.1,422.5,674.7,392,656.6,366.7z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="571.6973" y1="667.8917" x2="245.2973" y2="144.3317" gradientTransform="matrix(1 0 0 -1 0 800)">
<stop offset="0.16" style="stop-color:#C6F462"/>
<stop offset="0.89" style="stop-color:#33D9FF"/>
</linearGradient>
<path class="st5" d="M709.8,325.3c-47-178.9-238-265-379.2-221.4C482.7,133.9,607.5,206.4,709.8,325.3z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="579.0382" y1="663.3111" x2="252.6482" y2="139.7511" gradientTransform="matrix(1 0 0 -1 0 800)">
<stop offset="0.16" style="stop-color:#C6F462"/>
<stop offset="0.89" style="stop-color:#33D9FF"/>
</linearGradient>
<path class="st6" d="M155.4,583.9c54.6,69.3,124,109.7,213,122.8C334.4,643.2,214.6,574.5,155.4,583.9L155.4,583.9z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37.8 43.6"><defs><style>.cls-1{fill:#2a5ada;}</style></defs><title>Asset 1</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M18.9,0l-4,2.3L4,8.6,0,10.9V32.7L4,35l11,6.3,4,2.3,4-2.3L33.8,35l4-2.3V10.9l-4-2.3L22.9,2.3ZM8,28.1V15.5L18.9,9.2l10.9,6.3V28.1L18.9,34.4Z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 387 B

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="CIRCLE_OUTLINE_BLACK" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFD15C;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M512,256c0,141.4-114.6,256-256,256S0,397.4,0,256S114.6,0,256,0S512,114.6,512,256z"/>
<path class="st1" d="M193.5,152.3c-10.4,1.5-4.6,10.4-4.6,10.4l-0.3,2.5c14.9,25.7,39.5,52.7,64.6,70.7c18.5,13.2,32.3,32.7,39,54.9
c6.6,21.9,5.4,44.6-3.2,62.2c-10.4,21.2-30.1,33.5-55.3,34.7c-25.1,1.2-54.9-8.7-88.6-29.4c-0.3,0.8-0.7,1.6-1.1,2.3
c29.2,30.1,63,48.1,98.1,52.2c35.5,4.2,71.9-5.8,102.7-27.9c-0.8,0-1.4-0.2-1.9-0.5C446.5,298.8,276.9,140.4,193.5,152.3
L193.5,152.3z"/>
<path d="M462.6,267.4c-0.1-1.9-0.2-4.2-0.6-6.9c-1.3-10.5-5.5-26.6-17.7-43.7c-0.6-0.8-1.2-1.6-1.8-2.4c-0.1-0.2-0.3-0.4-0.4-0.6
c-0.5-0.7-1.1-1.4-1.6-2.1c0,0-0.1-0.1-0.1-0.1c-0.6-0.7-1.2-1.5-1.8-2.2c-0.1-0.2-0.3-0.3-0.4-0.5c-0.5-0.6-1.1-1.3-1.6-1.9
c-0.1-0.1-0.1-0.1-0.2-0.2c-0.6-0.7-1.2-1.3-1.8-2c-0.1-0.1-0.3-0.3-0.4-0.4c-0.5-0.6-1-1.1-1.5-1.6c-0.1-0.1-0.2-0.2-0.2-0.3
c-0.6-0.6-1.2-1.2-1.7-1.7c-0.1-0.1-0.2-0.2-0.4-0.4c-0.5-0.5-1-1-1.5-1.4c-0.1-0.1-0.2-0.2-0.3-0.3c-0.6-0.5-1.1-1-1.7-1.5
c-0.1-0.1-0.2-0.2-0.3-0.3c-0.5-0.4-1-0.8-1.4-1.2c-0.1-0.1-0.2-0.2-0.3-0.3c-0.5-0.5-1.1-0.9-1.6-1.3c-0.1-0.1-0.2-0.2-0.3-0.3
c-0.4-0.4-0.9-0.7-1.3-1.1c-0.1-0.1-0.3-0.2-0.4-0.3c-0.5-0.4-1-0.8-1.5-1.1c-0.1-0.1-0.2-0.2-0.3-0.2c-0.4-0.3-0.8-0.6-1.2-0.9
c-0.1-0.1-0.3-0.2-0.4-0.3c-0.5-0.3-0.9-0.6-1.4-1c-0.1-0.1-0.2-0.2-0.4-0.2c-0.4-0.2-0.7-0.5-1-0.7c-0.2-0.1-0.3-0.2-0.5-0.3
c-0.4-0.2-0.8-0.5-1.1-0.7c-0.2-0.1-0.4-0.2-0.5-0.3c-0.3-0.2-0.5-0.3-0.8-0.5c-0.2-0.1-0.4-0.2-0.6-0.3c-0.2-0.1-0.5-0.3-0.7-0.4
c-0.3-0.2-0.6-0.4-1-0.5c-0.2-0.1-0.3-0.2-0.5-0.3c-0.2-0.1-0.4-0.2-0.7-0.3c-0.1-0.1-0.2-0.1-0.3-0.2c-0.4-0.2-0.9-0.5-1.3-0.7
c0,0-0.1,0-0.1,0c-2.7-4.8-5.7-9.6-8.9-14.4c-37.3-54.6-78.2-81.1-124.9-81.2h-0.2c-19.8,0-37.9,4.5-53,8.9c-4.3,1.3-8.8,2.6-13.1,4
c-11,3.4-21.4,6.7-30.3,8.1c-5.6,0.9-10,3-13.1,6.2c-2.8,3-4.5,7.1-5,12.1c-1,9.7,2.5,22.8,10.1,37.8c15.3,30.4,44.6,63.9,74.6,85.4
c3.5,2.5,6.7,5.2,9.7,8.2c-0.6,0.1-1.2,0.2-1.9,0.3c-23.5,3.4-35.8,28.6-40.7,42.3c-1.3,3.6,2.2,6.8,5.8,5.5
c14.6-4.9,44.3-12.9,61-2.6c0.1,0,0.3-0.1,0.4-0.1c3,15,1.6,29.8-4.1,41.3c-7.5,15.1-21.8,24-40.3,24.9
c-21.8,1.1-48.6-8.2-79.7-27.6l-0.5-0.3c-0.3-0.1-0.6-0.3-0.8-0.5c24.2-27.5,9.9-69.9,4.3-83.8c-0.7-1.8-3.3-1.8-4.3-0.1
c-13,22.1-39.8,20.4-39.3,46.7c0,0,0,0,0-0.1c-20.4-16.6-35.6,5.5-61,2.2c-2-0.3-3.5,1.7-2.5,3.4c7.7,13.3,33.5,52.3,71.6,47.9
l-1.8,1.3l6.8,7.5c33.3,36.7,72.9,58.7,114.6,63.6c6,0.7,12,1.1,18,1.1c34.9,0,69.6-11.7,99.4-33.9c34.2-25.4,57.9-61.3,66.8-101
c3-13.2,4.2-26.4,3.7-39.5c7.5-3,15.7,0.3,22.2,4.7c0.1,0,0.1,0.1,0.2,0.1c0.3,0.2,0.5,0.4,0.8,0.5c0.1,0,0.1,0.1,0.2,0.1
c0.8,0.5,1.5,1.1,2.2,1.6c0.1,0.1,0.3,0.2,0.4,0.3c0.2,0.1,0.3,0.3,0.5,0.4c0.2,0.1,0.3,0.3,0.5,0.4c0.1,0.1,0.3,0.2,0.4,0.4
c0.3,0.2,0.6,0.5,0.8,0.7c0.1,0.1,0.2,0.2,0.3,0.2c0.2,0.2,0.4,0.4,0.6,0.5c0.1,0.1,0.2,0.2,0.3,0.3c0.2,0.2,0.4,0.3,0.6,0.5
c0.1,0.1,0.2,0.1,0.2,0.2c0.2,0.2,0.5,0.5,0.7,0.7c0.1,0.1,0.2,0.1,0.2,0.2c0.5,0.4,1.1,0.5,1.6,0.5
C461.7,269.5,462.7,268.6,462.6,267.4z M342.9,384.5c0.5,0.3,1.1,0.4,1.9,0.5c-30.8,22.2-67.2,32.1-102.7,27.9
c-35.2-4.1-68.9-22.1-98.1-52.2c0.4-0.8,0.8-1.5,1.1-2.3c33.7,20.7,63.5,30.6,88.6,29.4c25.2-1.2,44.9-13.6,55.3-34.7
c8.7-17.6,9.8-40.2,3.2-62.2c-6.7-22.2-20.5-41.7-39-54.9c-25.2-18-49.7-45-64.6-70.7l0.3-2.5c0,0-5.8-8.9,4.6-10.4
C276.9,140.4,446.5,298.8,342.9,384.5z"/>
<path class="st1" d="M280.3,146.5c-2.9-4.1-8.7-15.1,9.3-15.1c18,0,45.4,20.3,51,27.8c-1.7,4.6-13.3,5.6-19.1,5.2
s-15.6-1.4-23.2-5.2C290.8,155.6,283.2,150.6,280.3,146.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 994.3 1000.5" style="enable-background:new 0 0 994.3 1000.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F7F5F8;}
.st1{fill:#DCC4D4;}
.st2{fill:#EFAD93;}
.st3{fill:#D68C72;}
.st4{fill:#964C49;}
.st5{fill:#3A0101;}
.st6{fill:#894544;}
.st7{fill:#E3746D;}
.st8{fill:#FFFFFF;}
.st9{fill:#623538;}
.st10{fill:#C95755;}
</style>
<g>
<path class="st0" d="M27.4,444.9l471.8-254l124.2-2.5c0,0,129.7,15.8,232.7,116.6c0.1,0.1,0.2,0.1,0.2,0.2
c28.2,27.7,54.4,62.5,75.1,106.3c1.4,2.9,2.8,5.9,4.1,8.9c0,0,151.2,244-41.3,456.4c-192.5,212.3-651.4,110.6-789.3-112.5
c-1-1.5-2-3.1-3-4.7c-21.2-34.1-37-67.9-48.6-99.2c-14.7-39.6-22.9-75.1-27.4-101.6C20.8,528.5,27.5,444.9,27.4,444.9z"/>
<path class="st1" d="M218.8,420.3c-31.3,88.9,7.8,189.9,85.9,99.6c111.2-153,321.4-183.3,405.1-172.5
c102.5,19.8,182.5,123.4,207.9,125.4c25.4,2,13.7-61.3,13.7-61.3c1.4,2.9,2.8,5.9,4.1,8.9c0,0,151.2,244-41.3,456.4
C701.7,1089.1,242.8,987.4,105,764.2c-1-1.5-2-3.1-3-4.7c-21.2-34.1-37-67.9-48.6-99.2C106.8,572.1,243.9,348.5,218.8,420.3z"/>
<path class="st2" d="M680.7,183.7c49.4-48.5,129.9-117.2,190.6-152.4c29.2-17,53.8-26.2,68.1-21.7c2.8,0.8,5.1,2.2,7.1,4.1
c23.7,23.2,14.4,169.4,3.6,279.9c-7,70.6-14.6,126.7-14.6,126.7c-15.5-33.2-32-65.7-81.8-118c-20.7-20.3-41.8-37.4-63.2-51.7
c-36-24-72.5-40.1-108.3-50.3c-4.8-1.4-9.6-2.6-14.4-3.8C671.8,192.5,676.1,188.2,680.7,183.7z"/>
<path class="st3" d="M871.3,31.4c-10.1,73.5-12.2,200.9,78.8,262.3c-7,70.6-14.6,126.7-14.6,126.7c-15.5-33.2-32-65.7-81.8-118
c-20.7-20.3-41.8-37.4-63.2-51.7c-36-24-72.5-40.1-108.3-50.3l-1.6-16.6C730.1,135.2,810.6,66.6,871.3,31.4z"/>
<path class="st4" d="M51.1,14.9c49.7-15.8,213.2,136.5,315.7,216.5c0,0,141.2-74,301.1-34.9c7.5,1.8,15.1,3.9,22.8,6.3
c-46.6-1.7-115.4-3.1-144.9,2.2C499,213.5,329,264,254.7,383.2c-74.3,119.1-71.3,258.8-69.5,320.2c1.4,48.9-34.4,79.5-88.3,48
c-44.5-74.3-63.2-146.8-71-192.6c-1.1-10.1-2.2-20.5-3.5-31c-0.8-6-1.4-12-2.1-17.9C-12.3,223.4,2.5,30.3,51.1,14.9z"/>
<path class="st4" d="M939.4,9.6c-41.2,32.2-128.1,113.5-148.9,241c-40.8-27.2-82.3-44.2-122.7-54.1C736,126.7,892.6-5,939.4,9.6z"
/>
<path class="st5" d="M667.3,196.7c18-21.7,38.7-41.3,59-60.8c30.9-28.7,63.1-56.1,97.5-80.5c23.1-16.3,47-31.5,73.2-42.8
c13.8-5.3,28.2-11.2,43.7-6.9c3.2,0.8,4.1,5.5,1.3,7.4c-48,35.5-89.8,81.2-115,136l-7.3,16.4l-6.3,16.8c-8.3,23.1-13.5,47.2-19,71
c-1.4,2.2-4.4,2.7-6.5,1.3c-9.3-6.2-18.7-12.1-28.3-17.7C730.6,220,699.1,207.3,667.3,196.7L667.3,196.7z M668.3,196.4
c33.5,5.2,65.5,17.4,95.4,33c10,5.2,19.8,11.1,29.3,17.3l-7.2,3.2c11.1-73.1,51.8-137.4,99-192.5c15.9-18.4,33.2-35.6,52-51.1
l1.3,7.4c-34.7-7-111.7,54.4-141.3,75.9C755.4,121.4,714.9,155,676,189.9C673.8,191.8,670.7,194.7,668.3,196.4L668.3,196.4z"/>
<path class="st5" d="M667,196.8c9.8-12.7,21.5-23.8,32.5-35.3c56.3-55.7,115.3-109,185.4-147.2C903.6,5.5,934-9.3,952.6,8
c8.6,9.3,11,23.4,12.9,34.8c7.6,63.5,0.5,127.1-5.9,190.2c-7.1,62.7-14.3,125.2-20.2,188c-0.1,1.2-0.9,2.5-2.1,3.1
c-1.9,1-4.3,0.2-5.3-1.7c-21.3-43.7-51.6-81.8-85.2-116.5c-29-28.5-61.5-53.6-97.1-73.3C723.7,217.7,695.1,206.6,667,196.8
L667,196.8z M668.6,196.3c102.9,16.6,200.3,90.3,251,181.1c7.4,13.4,13.7,27.4,19.6,41.3l-7.6,1.2c15.8-93,21.6-187.6,22.5-281.8
c0.1-30.9,0.3-62.6-4.6-92.8c-1.5-8.2-3.1-16-6.7-22.5c-2.2-3.9-5.1-5.3-10-5.6c-13.2-0.3-28,6.5-40.3,12.5
c-13.6,6.6-26.9,14.5-39.9,22.9c-62,40.5-119.8,87.7-175.4,136.6C674.9,191.3,671.1,194.7,668.6,196.3L668.6,196.3z"/>
<path class="st5" d="M368.1,222.4c0,0-27.7,15.2-48.3,39.2c32.8-26.4,66.9-39.2,66.9-39.2H368.1z"/>
<path class="st5" d="M51.4,15.6C-13.1,43.9,7.5,316.1,13.6,383c3.6,42.3,8.6,84.5,13.7,126.7c0.9,16.6,3.4,33.8,6.5,50.3
c15.8,83.2,49,164.3,101,231.4c162.6,201.4,596.3,285.2,772.8,64.1c93.2-112.3,103.3-255.1,47.5-387.3c-6.8-15.7-14.3-31.3-23-45.7
c-9.8-21.3-21.3-41.7-34.7-60.8C858,307,809.5,265.5,746.8,233.1c-117.3-59-260-50.3-377.9,2.6c-1.6,0.8-3.7,0.7-5.2-0.5
c-50.3-40.8-98.5-83.9-148.5-125C183.7,85.2,89.5,5.3,51.4,15.6L51.4,15.6z M50.9,14.1c38.2-10.9,133.1,68.2,166.8,93
c51.1,39.6,100.6,81.4,152,120.5l-5.2-0.5c10.1-5.3,20.2-9.7,30.6-13.9c113.6-45.9,247.7-50.1,357.9,7.6
c38.5,19.3,80,51.8,106.2,79.6c28.3,26.3,63.5,77.6,79.6,117.9c37.5,68.6,57.7,147.2,55.3,225.5c-2,78.7-32.2,155.1-80.9,216.3
c-144.1,184.7-435.8,164.2-626.6,69.8c-70.3-34.9-136.1-83.3-181-148.9c-52.9-79.3-87.3-177.1-92-270.3
c-12-126.6-19.9-254.6-7-381.4C10.8,98.9,18.7,25.8,50.9,14.1L50.9,14.1z"/>
<path class="st2" d="M56.5,68.9c10.8,4.5,48,42.6,88.9,92c33.1,40,68.6,87.5,94.4,130.5C256.3,318.9,134.9,522,113,560.3
c-20.1,35.1-64.5-92-76.1-226c-1.1-12-1.8-23.9-2.3-35.9C28.8,152.3,36.9,60.8,56.5,68.9z"/>
<path class="st6" d="M327.6,643.2c7.1-85.1,52.7-166.4,117.6-206.6c75-42,139.1-61.4,202.6-61.1l0,0c15.2,0.1,30.5,1.3,45.8,3.6
c15,2.3,30.1,5.6,45.5,9.9c66,18.5,208.6,88.2,186.5,282.8c-0.7,5.8-1.5,11.5-2.5,17.2C891,873.9,688.2,995.2,467.4,887.4
C358,834,319.8,736.3,327.6,643.2z"/>
<path class="st7" d="M636.5,336.4c9.7,2.9,32.2,11.3,56.1-1c23.9-12.3,33.2,15.1,20.5,22.1c-14.4,7.9-18.4,17-19.6,21.7
c-15.3-2.3-30.5-3.5-45.8-3.6l0,0c-4.1-7.4-25.4-8.4-33.2-21.1C606.7,341.7,626.8,333.4,636.5,336.4z"/>
<path class="st8" d="M386.7,314c6.2-5.8,12.6-10.9,19.1-15.3c58-40,121.3-28.3,130.8-3.7c10.6,27.3-35.8,36.7-64.2,48.6
c-25.9,10.8-56.1,30.6-78.7,43.5c-16.6,9.5-29.3,15.3-33.1,11.1C351.5,388.3,342.5,354.9,386.7,314z"/>
<path class="st8" d="M773.8,272.5c33.4,12.4,58.6,33.3,75,50.7c11.4,12.1,18.4,22.5,20.9,27.2c6.1,11.4-12.7,14-36.2,5.3
c-1-0.4-2.1-0.8-3.2-1.2c-25.3-9-84.3-25.6-101.1-33C705.1,310.9,717.2,251.5,773.8,272.5z"/>
<path class="st5" d="M405.8,298.7c58-40,121.3-28.3,130.8-3.7c10.6,27.3-35.8,36.7-64.2,48.6c-25.9,10.8-56.1,30.6-78.7,43.5
C370.3,352.9,386.3,320.8,405.8,298.7z"/>
<path class="st5" d="M773.8,272.5c33.4,12.4,58.6,33.3,75,50.7c0.6,10.9-2.7,23.7-18.5,31.3c-25.3-9-84.3-25.6-101.1-33
C705.1,310.9,717.2,251.5,773.8,272.5z"/>
<path class="st5" d="M504.4,274.3c-72.3-19-136.4,35.7-149,74s-0.5,51.9,0,40.6s0-28.9,18-52.9c18.1-24,76-50.5,76-50.5
S477.1,292.5,504.4,274.3z"/>
<path class="st5" d="M869.5,341.4c-20.4-25.1-54.2-47.2-54.2-47.2s5.1,17,18.1,25.7c13,8.8,37.3,35.8,37.3,35.8
S876.6,352.4,869.5,341.4z"/>
<path class="st8" d="M504.4,294.2c-8.5,0.9-74.6,10.1-65.2-3.7s34.7-12.3,55.5-10.7C517.1,281.5,512.9,293.4,504.4,294.2z"/>
<path class="st8" d="M803.6,314.5c-12.8-6.2-34.7-17.4-31.5-26s27.8,6.4,42.5,14C833.1,312,816.4,320.7,803.6,314.5z"/>
<path class="st9" d="M445.2,436.6c75-42,139.1-61.4,202.6-61.1l0,0c15.2,0.1,30.5,1.3,45.8,3.6c15,2.3,30.1,5.6,45.5,9.9
c66,18.5,208.6,88.2,186.5,282.7c-0.7,5.8-1.5,11.5-2.5,17.2C859.5,755.1,757.8,798,643,797.9c-139.3,0-259.6-63.2-315.5-154.7
C334.6,558.1,380.2,476.8,445.2,436.6z"/>
<path class="st5" d="M467,888.1c-4.1-2.1-15-8-19-10.1c-4.3-2.5-13.8-8.5-18.2-11.3c-5.7-3.9-11.5-8.7-17.3-12.6
c-12.8-10.7-25.3-22-35.9-35c-51-59.2-67.4-143.5-50-219.2c14.9-66.8,52.5-130.4,110.4-168.2c74.4-43.3,162.1-73,249-60.2
c66.6,9.1,131.6,37.9,178.2,87.3c47.5,48.6,68.8,117.8,66.7,185c-0.4,38.6-7.7,77.3-22.3,113.1C871.9,848.2,785.9,914.7,689,928
C613.2,939.7,535.3,921.3,467,888.1L467,888.1z M467.7,886.6c103.1,51,224,52.6,322.3-10.2c62.5-40,109.6-104.2,126.4-177.1
c12.6-54.7,12.2-114.2-9.7-166.5C878,462.3,811,414,739.3,394.7C633,365.6,539,391.2,446.1,446.3
C361.9,503,321.5,614.9,336.4,714.1c5.5,34.6,19.1,68.2,39.4,96.7c3.2,4,7.6,9.9,10.8,13.9c6.6,7.1,14.9,16.4,22.4,22.6l5.2,4.8
l5.6,4.3c6.3,5.3,16.2,11.9,23.2,16.3C449.7,877.2,460.6,882.6,467.7,886.6L467.7,886.6z"/>
<path class="st10" d="M624.5,349.4c9.9-5,28,14.1,28,14.1C630,361.9,614.5,354.5,624.5,349.4z"/>
<path class="st10" d="M709.7,347.4c-8.3-4.5-19.1,16.1-19.1,16.1C701.2,361.2,718,351.9,709.7,347.4z"/>
<path class="st3" d="M145.4,160.9c33.1,40,68.6,87.5,94.4,130.5c16.5,27.5-104.9,230.6-126.9,268.9c-20.1,35.1-64.5-92-76.1-226
C134.4,390.3,148.1,261.2,145.4,160.9z"/>
<path class="st5" d="M239.3,291.7C203,231.8,156.6,179,109.9,127.3C94.3,110.6,78.5,93.1,61,78.7c-2.4-1.8-4.8-3.7-6.8-4.5
c-2.9,2.5-5.2,9.1-6.4,13.8c-7.9,33.4-8.7,68.6-9.8,103.1c-0.4,23.2-0.5,46.6-0.3,69.9c-0.2,70,5.5,140.1,23.6,207.9
c5.3,20,24.9,86.9,43.7,93.3c1.6-0.1,2.6-1.2,3.6-2.7l0.9-1.5c3.4-7.1,73.1-128.3,78.8-138.8C201.1,395.1,248.5,315.1,239.3,291.7
L239.3,291.7z M240.3,291.1c10.1,18.9-35.6,108.8-46,131.3c-23,47.3-49.2,93.1-76.6,137.9c-2,4.1-7.1,10.6-13.3,9.8
c-30.8-4.3-55.4-138.4-61-168.9C30.8,332,27.6,261.4,27.8,191.1c0.8-28.9-0.2-103.5,17.4-124.3c7.7-8.1,16.3-2.5,22.8,3
c9.4,7.7,17.6,16.1,25.8,24.6C150,154,197.5,221.4,240.3,291.1L240.3,291.1z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="CIRCLE_OUTLINE_BLACK" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E6DAFE;}
</style>
<circle class="st0" cx="256" cy="256" r="256"/>
<path d="M303.4,228.5c0,20.7-16.7,37.5-37.4,37.5v37.5c41.3,0,74.7-33.5,74.7-74.9s-33.5-74.9-74.7-74.9c-13.6,0-26.4,3.6-37.4,10
c-22.3,12.9-37.4,37.2-37.4,64.9v187.3l33.6,33.7l3.8,3.8V228.5c0-20.7,16.7-37.5,37.4-37.5S303.4,207.9,303.4,228.5z"/>
<path d="M266,78.7c-27.2,0-52.7,7.3-74.7,20.1c-14.1,8.1-26.7,18.5-37.4,30.7c-23.2,26.4-37.4,61.1-37.4,99.1v112.4l37.4,37.5V228.5
c0-33.3,14.4-63.2,37.4-83.8c10.8-9.7,23.4-17.3,37.4-22.2c11.7-4.2,24.3-6.4,37.4-6.4c61.9,0,112.1,50.3,112.1,112.4
S327.9,340.9,266,340.9v37.5c82.5,0,149.4-67.1,149.4-149.8S348.5,78.7,266,78.7z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 36.9" style="enable-background:new 0 0 32 36.9;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_2_);}
.st2{fill:url(#SVGID_3_);}
.st3{fill:url(#SVGID_4_);}
</style>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="32.95" y1="26.3048" x2="-0.9788" y2="12.7367" gradientTransform="matrix(1 0 0 -1 0 38)">
<stop offset="0" style="stop-color:#C200FB"/>
<stop offset="0.4897" style="stop-color:#3772FF"/>
<stop offset="1" style="stop-color:#5AC4BE"/>
</linearGradient>
<path class="st0" d="M30.3,13.9v12.9L16,35L1.7,26.7V10.2L16,1.9l11,6.4l1.7-1L16,0L0,9.2v18.5l16,9.2l16-9.2V12.9L30.3,13.9z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="32.2949" y1="27.9428" x2="-1.6339" y2="14.3747" gradientTransform="matrix(1 0 0 -1 0 38)">
<stop offset="0" style="stop-color:#C200FB"/>
<stop offset="0.4897" style="stop-color:#3772FF"/>
<stop offset="1" style="stop-color:#5AC4BE"/>
</linearGradient>
<path class="st1" d="M12,26.8H9.6v-8h8c0.8,0,1.5-0.3,2-0.9c0.5-0.5,0.8-1.3,0.8-2c0-0.4-0.1-0.7-0.2-1.1c-0.1-0.3-0.4-0.7-0.6-0.9
c-0.3-0.3-0.6-0.5-0.9-0.6S18,13,17.6,13h-8v-2.4h8c1.4,0,2.7,0.6,3.7,1.6c1,1,1.6,2.3,1.6,3.7c0,1.1-0.3,2.1-0.9,3
c-0.6,0.8-1.4,1.5-2.3,1.9c-0.9,0.3-1.9,0.4-2.9,0.4H12V26.8z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="35.6876" y1="19.4591" x2="1.7588" y2="5.891" gradientTransform="matrix(1 0 0 -1 0 38)">
<stop offset="0" style="stop-color:#C200FB"/>
<stop offset="0.4897" style="stop-color:#3772FF"/>
<stop offset="1" style="stop-color:#5AC4BE"/>
</linearGradient>
<path class="st2" d="M22.8,26.6H20l-2.2-3.8c0.9-0.1,1.7-0.2,2.5-0.5L22.8,26.6z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="32.0678" y1="28.5037" x2="-1.861" y2="14.9356" gradientTransform="matrix(1 0 0 -1 0 38)">
<stop offset="0" style="stop-color:#C200FB"/>
<stop offset="0.4897" style="stop-color:#3772FF"/>
<stop offset="1" style="stop-color:#5AC4BE"/>
</linearGradient>
<path class="st3" d="M28.7,11.2l1.7,0.9l1.7-0.9V9.2l-1.7-1l-1.7,1V11.2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.08398 5.22265C7.17671 5.08355 7.33282 5 7.5 5H18.5C18.6844 5 18.8538 5.10149 18.9408 5.26407C19.0278 5.42665 19.0183 5.62392 18.916 5.77735L16.916 8.77735C16.8233 8.91645 16.6672 9 16.5 9H5.5C5.3156 9 5.14617 8.89851 5.05916 8.73593C4.97215 8.57335 4.98169 8.37608 5.08398 8.22265L7.08398 5.22265ZM7.76759 6L6.43426 8H16.2324L17.5657 6H7.76759Z" fill="#fff"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.08398 15.2226C7.17671 15.0836 7.33282 15 7.5 15H18.5C18.6844 15 18.8538 15.1015 18.9408 15.2641C19.0278 15.4267 19.0183 15.6239 18.916 15.7774L16.916 18.7774C16.8233 18.9164 16.6672 19 16.5 19H5.5C5.3156 19 5.14617 18.8985 5.05916 18.7359C4.97215 18.5734 4.98169 18.3761 5.08398 18.2226L7.08398 15.2226ZM7.76759 16L6.43426 18H16.2324L17.5657 16H7.76759Z" fill="#fff"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.08398 13.7774C7.17671 13.9164 7.33282 14 7.5 14H18.5C18.6844 14 18.8538 13.8985 18.9408 13.7359C19.0278 13.5733 19.0183 13.3761 18.916 13.2226L16.916 10.2226C16.8233 10.0836 16.6672 10 16.5 10H5.5C5.3156 10 5.14617 10.1015 5.05916 10.2641C4.97215 10.4267 4.98169 10.6239 5.08398 10.7774L7.08398 13.7774ZM7.76759 13L6.43426 11H16.2324L17.5657 13H7.76759Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.6109 4.68601C4.72546 4.54406 4.90822 4.47575 5.0878 4.50778L16.575 6.55656C16.6715 6.57377 16.7608 6.61896 16.8318 6.68651L19.3446 9.07676C19.5379 9.26064 19.5528 9.5639 19.3784 9.76583L11.122 19.3268C11.0084 19.4583 10.8347 19.5214 10.6632 19.4935C10.4917 19.4656 10.347 19.3506 10.281 19.1898L4.53742 5.18979C4.46819 5.02103 4.49635 4.82796 4.6109 4.68601ZM6.19646 6.59904L10.4853 17.053L11.2894 10.6786L6.19646 6.59904ZM12.2688 10.9045L11.4468 17.4207L17.7491 10.1226L12.2688 10.9045ZM17.9075 9.08986L13.7298 9.68594L16.4453 7.69901L17.9075 9.08986ZM15.2483 7.33573L6.84451 5.83688L11.8343 9.83381L15.2483 7.33573Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 912 B

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 400 432.7" style="enable-background:new 0 0 400 432.7;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F50DB4;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#F50DB4;}
</style>
<path class="st0" d="M325.1,65.4c0.6-10.2,2-17,4.8-23.1c1.1-2.4,2.1-4.4,2.3-4.4s-0.3,1.8-1.1,4c-2,6-2.4,14.2-1,23.7
c1.8,12.1,2.8,13.8,15.6,26.9c6,6.1,13,13.8,15.5,17.1l4.6,6l-4.6-4.3c-5.6-5.3-18.6-15.5-21.4-17c-1.9-1-2.2-1-3.4,0.2
c-1.1,1.1-1.3,2.7-1.5,10.4c-0.2,12-1.9,19.7-5.8,27.3c-2.1,4.2-2.5,3.3-0.5-1.4c1.4-3.5,1.6-5,1.6-16.6c0-23.3-2.8-28.9-19.1-38.5
c-4.1-2.4-10.9-5.9-15.1-7.8c-4.2-1.9-7.5-3.5-7.4-3.6c0.5-0.5,16.3,4.2,22.7,6.6c9.5,3.6,11.1,4.1,12.2,3.7
C324.4,74.2,324.8,72,325.1,65.4z"/>
<path class="st0" d="M124.4,31.5c-5.6-0.9-5.9-1-3.2-1.4c5.1-0.8,17.1,0.3,25.4,2.2c19.3,4.6,36.9,16.3,55.6,37l5,5.5l7.1-1.1
c30-4.8,60.6-1,86.1,10.8c7,3.2,18.1,9.7,19.5,11.3c0.4,0.5,1.3,3.9,1.8,7.5c1.9,12.5,0.9,22.1-2.9,29.3c-2.1,3.9-2.2,5.1-0.8,8.5
c1.1,2.7,4.3,4.6,7.4,4.6c6.3,0,13.2-10.2,16.3-24.4l1.3-5.6l2.5,2.8c13.7,15.4,24.4,36.4,26.2,51.3l0.5,3.9l-2.3-3.5
c-4-6.1-7.9-10.2-13-13.6c-9.2-6-18.9-8.1-44.5-9.4c-23.2-1.2-36.3-3.2-49.3-7.4c-22.1-7.2-33.3-16.7-59.6-51.1
c-11.7-15.2-18.9-23.7-26.1-30.5C161,42.8,145,34.7,124.4,31.5z"/>
<path class="st0" d="M135.4,105.3c-11.4-15.7-18.5-39.7-17-57.6l0.5-5.6l2.6,0.5c4.9,0.9,13.3,4,17.3,6.4
c10.8,6.5,15.5,15.2,20.3,37.3c1.4,6.5,3.2,13.8,4.1,16.3c1.4,4,6.5,13.3,10.7,19.4c3,4.4,1,6.4-5.6,5.8
C158,126.9,144.2,117.5,135.4,105.3z"/>
<path class="st0" d="M311.3,221.9c-53.5-21.4-72.3-40-72.3-71.4c0-4.6,0.2-8.4,0.4-8.4c0.2,0,2.3,1.5,4.6,3.4
c10.8,8.6,23,12.3,56.6,17.2c19.8,2.9,30.9,5.2,41.2,8.6c32.6,10.8,52.8,32.6,57.6,62.4c1.4,8.6,0.6,24.9-1.7,33.4
c-1.8,6.7-7.3,18.9-8.7,19.4c-0.4,0.1-0.8-1.4-0.9-3.5c-0.6-11.2-6.2-22-15.8-30.2C361.4,243.6,346.9,236.2,311.3,221.9z"/>
<path class="st0" d="M273.7,230.8c-0.7-4-1.8-9-2.6-11.3l-1.4-4l2.5,2.8c3.5,3.9,6.3,8.9,8.6,15.6c1.8,5.1,2,6.6,2,14.9
c0,8.1-0.2,9.8-1.9,14.4c-2.6,7.2-5.8,12.4-11.3,17.9c-9.8,9.9-22.3,15.4-40.4,17.6c-3.1,0.4-12.3,1.1-20.4,1.5
c-20.3,1.1-33.7,3.2-45.8,7.4c-1.7,0.6-3.3,1-3.4,0.8c-0.5-0.5,7.7-5.3,14.5-8.6c9.5-4.6,19-7.1,40.3-10.6
c10.5-1.7,21.4-3.9,24.1-4.7C264.6,276.7,278,256.2,273.7,230.8z"/>
<path class="st0" d="M298.2,274.1c-7.1-15.2-8.7-29.9-4.8-43.5c0.4-1.5,1.1-2.7,1.5-2.7c0.4,0,2.1,0.9,3.7,2
c3.3,2.2,9.8,5.9,27.3,15.4c21.8,11.8,34.3,21,42.7,31.5c7.4,9.2,12,19.6,14.2,32.3c1.3,7.2,0.5,24.6-1.3,31.8
c-5.9,22.9-19.5,40.9-39,51.4c-2.9,1.5-5.4,2.8-5.7,2.8c-0.3,0,0.8-2.6,2.3-5.8c6.5-13.6,7.3-26.8,2.3-41.6c-3-9-9.2-20-21.7-38.6
C305.4,287.5,301.8,281.7,298.2,274.1z"/>
<path class="st0" d="M97.4,356.1c19.8-16.7,44.5-28.5,67-32.1c9.7-1.6,25.8-0.9,34.8,1.3c14.4,3.7,27.3,11.9,33.9,21.6
c6.5,9.5,9.3,17.9,12.3,36.4c1.2,7.3,2.4,14.6,2.8,16.3c2.2,9.6,6.5,17.3,11.8,21.1c8.4,6.1,22.9,6.5,37.1,1
c2.4-0.9,4.5-1.6,4.7-1.4c0.5,0.5-6.7,5.3-11.7,7.8c-6.8,3.4-12.2,4.7-19.4,4.7c-13,0-23.9-6.6-32.9-20c-1.8-2.6-5.8-10.6-8.9-17.6
c-9.5-21.6-14.2-28.2-25.3-35.4c-9.6-6.3-22.1-7.4-31.4-2.8c-12.3,6-15.7,21.6-6.9,31.5c3.5,3.9,10,7.3,15.3,8
c10,1.2,18.5-6.3,18.5-16.3c0-6.5-2.5-10.2-8.8-13.1c-8.6-3.9-17.9,0.7-17.9,8.7c0,3.4,1.5,5.6,5,7.2c2.2,1,2.3,1.1,0.5,0.7
c-7.9-1.6-9.8-11.1-3.4-17.4c7.7-7.6,23.5-4.2,28.9,6.1c2.3,4.3,2.5,13,0.6,18.2c-4.5,11.7-17.4,17.8-30.6,14.5
c-9-2.3-12.6-4.7-23.4-15.8c-18.8-19.3-26.1-23-53.2-27.2l-5.2-0.8L97.4,356.1z"/>
<path class="st1" d="M9.2,11.5c62.8,75.7,106,107,110.8,113.6c4,5.5,2.5,10.4-4.3,14.2c-3.8,2.1-11.5,4.3-15.4,4.3
c-4.4,0-5.9-1.7-5.9-1.7c-2.6-2.4-4-2-17.1-25.1C59.1,88.8,43.9,65.5,43.5,65.1c-1-0.9-0.9-0.9,32,57.7c5.3,12.2,1.1,16.7,1.1,18.4
c0,3.5-1,5.4-5.4,10.3c-7.3,8.1-10.6,17.2-12.9,36.1c-2.6,21.1-10.1,36.1-30.7,61.6c-12.1,15-14,17.7-17.1,23.7
c-3.8,7.6-4.9,11.9-5.3,21.4c-0.5,10.1,0.4,16.7,3.5,26.4c2.7,8.5,5.6,14.1,12.9,25.3c6.3,9.7,9.9,16.9,9.9,19.7
c0,2.2,0.4,2.2,10.2,0.1c23.3-5.2,42.2-14.4,52.8-25.7c6.6-7,8.1-10.8,8.2-20.4c0-6.3-0.2-7.6-1.9-11.2c-2.8-5.9-7.8-10.7-18.9-18.3
c-14.5-9.9-20.8-17.9-22.5-28.8c-1.4-9,0.2-15.3,8.3-32.1c8.3-17.4,10.4-24.8,11.8-42.3c0.9-11.3,2.2-15.8,5.4-19.3
c3.4-3.7,6.5-5,14.9-6.1c13.7-1.9,22.5-5.4,29.7-12c6.2-5.7,8.9-11.2,9.3-19.5l0.3-6.3l-3.5-4C122.8,105.1,0.8,0,0,0
C-0.2,0,4,5.2,9.2,11.5z M38.5,305.9c2.9-5,1.3-11.5-3.4-14.7c-4.5-3-11.5-1.6-11.5,2.3c0,1.2,0.7,2.1,2.1,2.8
c2.5,1.3,2.7,2.7,0.7,5.7c-2,3-1.8,5.6,0.5,7.4C30.5,312.3,35.7,310.7,38.5,305.9z"/>
<path class="st1" d="M147.6,164.9c-6.5,2-12.7,8.8-14.7,15.9c-1.2,4.4-0.5,12,1.3,14.3c2.9,3.8,5.6,4.8,13.1,4.8
c14.7-0.1,27.5-6.4,29-14.2c1.2-6.4-4.4-15.3-12.1-19.2C160.2,164.4,151.7,163.6,147.6,164.9z M164.8,178.3c2.3-3.2,1.3-6.7-2.6-9
c-7.3-4.5-18.4-0.8-18.4,6.1c0,3.4,5.8,7.2,11.1,7.2C158.4,182.6,163.2,180.5,164.8,178.3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -1,6 +0,0 @@
<svg width="96" height="96" viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M48 95C73.9574 95 95 73.9574 95 48C95 22.0426 73.9574 1 48 1C22.0426 1 1 22.0426 1 48C1 73.9574 22.0426 95 48 95Z" fill="#0B53BF"/>
<path d="M56.4609 13.7778V19.8291C68.5341 23.4716 77.3759 34.6928 77.3759 47.9997C77.3759 61.3066 68.5341 72.5278 56.4609 76.1703V82.2216C71.8534 78.4616 83.2509 64.5672 83.2509 47.9997C83.2509 31.4322 71.8534 17.5378 56.4609 13.7778Z" fill="white"/>
<path d="M18.625 47.9997C18.625 34.6928 27.4669 23.4716 39.54 19.8291V13.7778C24.1475 17.5378 12.75 31.4322 12.75 47.9997C12.75 64.5672 24.1475 78.4616 39.54 82.2216V76.1703C27.4669 72.5572 18.625 61.3066 18.625 47.9997Z" fill="white"/>
<path d="M60.6319 54.5506C60.6319 42.5362 41.8025 47.4713 41.8025 40.8325C41.8025 38.4531 43.7119 36.9256 47.3544 36.9256C51.7019 36.9256 53.2 39.0406 53.67 41.89H59.6625C59.1279 36.5426 56.0588 33.1662 50.9382 32.1604V27.4375H45.0632V31.9918C39.4534 32.7062 35.9275 35.973 35.9275 40.8325C35.9275 52.9056 54.7863 48.3819 54.7863 54.9031C54.7863 57.3706 52.4069 59.0156 48.3825 59.0156C43.1244 59.0156 41.3913 56.695 40.745 53.4931H34.8994C35.2781 59.3502 38.8897 63.0159 45.0632 63.9307V68.5625H50.9382V63.9923C56.9633 63.2139 60.6319 59.7089 60.6319 54.5506Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

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