Compare commits

...
30 Commits
Author SHA1 Message Date
Alex van Andel 98c78ba7e1 v3.3.5
Auto Comment Merge Conflicts / auto-comment-merge-conflicts (push) Canceled after 0s
release.yml / release (push) Canceled after 0s
2023-10-04 22:29:48 +01:00
alannnc c554779490 fix: rescheduled value DB update on reschedule and insights view cancelleds (#11474) 2023-10-04 12:10:10 -07:00
Crowdin Bot 53655a43eb New Crowdin translations by Github Action 2023-10-04 19:08:54 +00:00
Carina WollendorferandCarinaWolli 38d1b92226 fix: google calendar busy times (#11696)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2023-10-04 12:05:50 -07:00
3e08c66888 refactor: Use template literal instead of '+' operator (#11444)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: zomars <zomars@me.com>
2023-10-03 11:52:19 -07:00
Hariom Balhara a186b130cb fix: Use only the first connected calendar as fallback to create event (#11668) 2023-10-03 10:45:18 -07:00
Roland bb052a24bc fix: alby logo on payment component (#11678) 2023-10-03 16:14:54 +00:00
a1b6b7ad66 feat: #1490 [CAL-422] Intercom App (#10714)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Ubuntu <ubuntu@ip-172-31-18-13.eu-west-3.compute.internal>
2023-10-03 10:25:27 +01:00
sean-brydon 35181e4bfd fix: booker skeleton layout shift (#11653) 2023-10-02 17:53:10 +01:00
Nic Wortel c2e3638993 fix: Add 240 and 480 mins. options for multiple duration events (#10663) 2023-10-02 12:59:08 +01:00
Hariom Balhara 3ca7456885 test: Booking flow App failure and ics file tests and improved logging (#11646) 2023-10-02 16:21:04 +05:30
Peer Richelsen 07bfaec24e fix: inverted logos and new logo for cal video (#11633)
* new logo for cal video

* fixed cal video and other inverted icons

* Discard changes to apps/web/components/eventtype/EventAdvancedTab.tsx

* moved function to lib
2023-10-02 11:36:37 +01:00
alannnc 032435fbd4 fix: app that dont require setup page (#11628)
* fix

* add new test
2023-10-01 11:45:27 -03:00
Hariom Balhara caf1b4c5d7 test: More tests in booking flow (#11510) 2023-09-30 13:28:52 +00:00
Hariom Balharaandalannnc 20898e1505 fix: Handle payment flow webhooks in case of event requiring confirmation (#11458)
Co-authored-by: alannnc <alannnc@gmail.com>
2023-09-30 10:22:32 +05:30
AldrinandPeer Richelsen 0bb99fc667 refactor: <BookingListItem/> to use <Link/> to navigate instead of r… (#11602)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-09-29 22:54:22 +01:00
DexterStorey e5b88bd0b0 fix: prisma import in extract user route in Cal AI (#11625) 2023-09-29 13:53:38 -07:00
Udit TakkarandLeo Giovanetti 4a81b59fc9 fix: profile loading fix in org (#11618)
Co-authored-by: Leo Giovanetti <hello@leog.me>
2023-09-29 21:25:56 +01:00
Lauris SkraucisandAlan e1f47ef40e refactor: Paypal App UI & UX (#11528)
* refactor(ui): price input margin

* refactor(ui): price input border

* refactor(ui): inputs spacing

* fix: Use USD as the default currency

* fix: dynamic currency symbols

* undo

* apply same styles for stripe app

* type fixes

---------

Co-authored-by: Alan <alannnc@gmail.com>
2023-09-29 13:19:04 -07:00
Rolandandalannnc e568d70e65 fix: only set stripe app data if it requires payment (#11623)
Co-authored-by: alannnc <alannnc@gmail.com>
2023-09-29 18:49:52 +00:00
Carina WollendorferandCarinaWolli 41b6377f29 fix: availability for org team event (#11611)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2023-09-29 17:56:24 +02:00
Udit TakkarandPeer Richelsen 685be1663e refactor: Setting redesign (#11124)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-09-29 15:10:13 +01:00
Alex van Andel 85a1713897 Revert "refactor: Setting redesign (#11124)"
This reverts commit 4f3cf4f948.
2023-09-29 13:37:06 +01:00
Hariom Balhara c22d406d12 Enforce CSP on /login as well (#11610) 2023-09-29 07:50:15 -03:00
Lauris Skraucis cf43d9dcfc docs: E2E browser installation & setting up Node (#11551)
* docs: installing E2E test browsers

* docs: using required Node version

* refactor: correct use of English
2023-09-29 06:46:19 -03:00
BHARGAVA_GONUGUNTA 30a23cedbc Fixes the dropdowen issue #11597 (#11607) 2023-09-29 10:45:45 +01:00
Omar LópezandPeer Richelsen 6e2a96d69c fix: Add missing prisma import (#11598)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-09-28 21:42:24 +00:00
Peer Richelsen 490e0a9bb4 chore: cal.ai app store improvements (#11596) 2023-09-28 21:32:27 +00:00
alannnc 31bc586ee8 fix: stripe selected currency (#11593) 2023-09-28 14:29:12 -07:00
+15 68bd877c5b feat: OAuth provider for Zapier (#11465)
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: sajanlamsal <saznlamsal@gmail.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: alannnc <alannnc@gmail.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Nitin Panghal <nitin.panghal@unthinkable.co>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Peer Richelsen <peer@cal.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Shivam Kalra <shivamkalra98@gmail.com>
Co-authored-by: Richard Poelderl <richard.poelderl@gmail.com>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Nafees Nazik <84864519+G3root@users.noreply.github.com>
Co-authored-by: Chiranjeev Vishnoi <66114276+Chiranjeev-droid@users.noreply.github.com>
Co-authored-by: Denzil Samuel <71846487+samueldenzil@users.noreply.github.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: nitinpanghal <43965732+nitinpanghal@users.noreply.github.com>
Co-authored-by: Ahmad <57593864+Ahmadkashif@users.noreply.github.com>
Co-authored-by: Annlee Fores <annleefores@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Vijay <vijayraghav22@gmail.com>
2023-09-28 12:41:28 -07:00
309 changed files with 8758 additions and 2929 deletions

No files matched your search

+27 -2
View File
@@ -92,7 +92,22 @@ To develop locally:
- Use `openssl rand -base64 32` to generate a key and add it under `NEXTAUTH_SECRET` in the `.env` file. - Use `openssl rand -base64 32` to generate a key and add it under `NEXTAUTH_SECRET` in the `.env` file.
- Use `openssl rand -base64 24` to generate a key and add it under `CALENDSO_ENCRYPTION_KEY` in the `.env` file. - Use `openssl rand -base64 24` to generate a key and add it under `CALENDSO_ENCRYPTION_KEY` in the `.env` file.
6. Start developing and watch for code changes: 6. Setup Node
If your Node version does not meet the project's requirements as instructed by the docs, "nvm" (Node Version Manager) allows using Node at the version required by the project:
```sh
nvm use
```
You first might need to install the specific version and then use it:
```sh
nvm install && nvm use
```
You can install nvm from [here](https://github.com/nvm-sh/nvm).
7. Start developing and watch for code changes:
```sh ```sh
yarn dev yarn dev
@@ -120,6 +135,16 @@ This will run and test all flows in multiple Chromium windows to verify that no
yarn test-e2e yarn test-e2e
``` ```
#### Resolving issues
##### E2E test browsers not installed
Run `npx playwright install` to download test browsers and resolve the error below when running `yarn test-e2e`:
```
Executable doesn't exist at /Users/alice/Library/Caches/ms-playwright/chromium-1048/chrome-mac/Chromium.app/Contents/MacOS/Chromium
```
## Linting ## Linting
To check the formatting of your code: To check the formatting of your code:
@@ -135,4 +160,4 @@ If you get errors, be sure to fix them before committing.
- Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) while creating your PR. - Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) while creating your PR.
- If your PR refers to or fixes an issue, be sure to add `refs #XXX` or `fixes #XXX` to the PR description. Replacing `XXX` with the respective issue number. See more about [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue). - If your PR refers to or fixes an issue, be sure to add `refs #XXX` or `fixes #XXX` to the PR description. Replacing `XXX` with the respective issue number. See more about [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
- Be sure to fill the PR Template accordingly. - Be sure to fill the PR Template accordingly.
- Review [App Contribution Guidelines](./packages/app-store/CONTRIBUTING.md) when building integrations - Review [App Contribution Guidelines](./packages/app-store/CONTRIBUTING.md) when building integrations
+33 -6
View File
@@ -131,23 +131,39 @@ Here is what you need to be able to run Cal.com.
> If you are on Windows, run the following command on `gitbash` with admin privileges: <br> > `git clone -c core.symlinks=true https://github.com/calcom/cal.com.git` <br> > If you are on Windows, run the following command on `gitbash` with admin privileges: <br> > `git clone -c core.symlinks=true https://github.com/calcom/cal.com.git` <br>
> See [docs](https://cal.com/docs/how-to-guides/how-to-troubleshoot-symbolic-link-issues-on-windows#enable-symbolic-links) for more details. > See [docs](https://cal.com/docs/how-to-guides/how-to-troubleshoot-symbolic-link-issues-on-windows#enable-symbolic-links) for more details.
1. Go to the project folder 2. Go to the project folder
```sh ```sh
cd cal.com cd cal.com
``` ```
1. Install packages with yarn 3. Install packages with yarn
```sh ```sh
yarn yarn
``` ```
1. Set up your `.env` file 4. Set up your `.env` file
- Duplicate `.env.example` to `.env` - Duplicate `.env.example` to `.env`
- Use `openssl rand -base64 32` to generate a key and add it under `NEXTAUTH_SECRET` in the `.env` file. - Use `openssl rand -base64 32` to generate a key and add it under `NEXTAUTH_SECRET` in the `.env` file.
- Use `openssl rand -base64 24` to generate a key and add it under `CALENDSO_ENCRYPTION_KEY` in the `.env` file. - Use `openssl rand -base64 24` to generate a key and add it under `CALENDSO_ENCRYPTION_KEY` in the `.env` file.
5. Setup Node
If your Node version does not meet the project's requirements as instructed by the docs, "nvm" (Node Version Manager) allows using Node at the version required by the project:
```sh
nvm use
```
You first might need to install the specific version and then use it:
```sh
nvm install && nvm use
```
You can install nvm from [here](https://github.com/nvm-sh/nvm).
#### Quick start with `yarn dx` #### Quick start with `yarn dx`
> - **Requires Docker and Docker Compose to be installed** > - **Requires Docker and Docker Compose to be installed**
@@ -221,6 +237,7 @@ echo 'NEXT_PUBLIC_DEBUG=1' >> .env
``` ```
1. Run [mailhog](https://github.com/mailhog/MailHog) to view emails sent during development 1. Run [mailhog](https://github.com/mailhog/MailHog) to view emails sent during development
> **_NOTE:_** Required when `E2E_TEST_MAILHOG_ENABLED` is "1" > **_NOTE:_** Required when `E2E_TEST_MAILHOG_ENABLED` is "1"
```sh ```sh
@@ -259,6 +276,16 @@ yarn test-e2e
yarn playwright show-report test-results/reports/playwright-html-report yarn playwright show-report test-results/reports/playwright-html-report
``` ```
#### Resolving issues
##### E2E test browsers not installed
Run `npx playwright install` to download test browsers and resolve the error below when running `yarn test-e2e`:
```
Executable doesn't exist at /Users/alice/Library/Caches/ms-playwright/chromium-1048/chrome-mac/Chromium.app/Contents/MacOS/Chromium
```
### Upgrading from earlier versions ### Upgrading from earlier versions
1. Pull the current version: 1. Pull the current version:
@@ -470,9 +497,8 @@ following
4. Select Basecamp 4 as the product to integrate with. 4. Select Basecamp 4 as the product to integrate with.
5. Set the Redirect URL for OAuth `<Cal.com URL>/api/integrations/basecamp3/callback` replacing Cal.com URL with the URI at which your application runs. 5. Set the Redirect URL for OAuth `<Cal.com URL>/api/integrations/basecamp3/callback` replacing Cal.com URL with the URI at which your application runs.
6. Click on done and copy the Client ID and secret into the `BASECAMP3_CLIENT_ID` and `BASECAMP3_CLIENT_SECRET` fields. 6. Click on done and copy the Client ID and secret into the `BASECAMP3_CLIENT_ID` and `BASECAMP3_CLIENT_SECRET` fields.
7. Set the `BASECAMP3_CLIENT_SECRET` env variable to `{your_domain} ({support_email})`. 7. Set the `BASECAMP3_CLIENT_SECRET` env variable to `{your_domain} ({support_email})`.
For example, `Cal.com (support@cal.com)`. For example, `Cal.com (support@cal.com)`.
### Obtaining HubSpot Client ID and Secret ### Obtaining HubSpot Client ID and Secret
@@ -507,6 +533,7 @@ For example, `Cal.com (support@cal.com)`.
### Obtaining Zoho Calendar Client ID and Secret ### Obtaining Zoho Calendar Client ID and Secret
[Follow these steps](./packages/app-store/zohocalendar/) [Follow these steps](./packages/app-store/zohocalendar/)
### Obtaining Zoho Bigin Client ID and Secret ### Obtaining Zoho Bigin Client ID and Secret
[Follow these steps](./packages/app-store/zoho-bigin/) [Follow these steps](./packages/app-store/zoho-bigin/)
+7 -7
View File
@@ -4,9 +4,9 @@ Welcome to the first stage of Cal.ai!
This app lets you chat with your calendar via email: This app lets you chat with your calendar via email:
- Turn informal emails into bookings eg. forward "wanna meet tmrw at 2pm?" - Turn informal emails into bookings eg. forward "wanna meet tmrw at 2pm?"
- List and rearrange your bookings eg. "Cancel my next meeting" - List and rearrange your bookings eg. "Cancel my next meeting"
- Answer basic questions about your busiest times eg. "How does my Tuesday look?" - Answer basic questions about your busiest times eg. "How does my Tuesday look?"
The core logic is contained in [agent/route.ts](/apps/ai/src/app/api/agent/route.ts). Here, a [LangChain Agent Executor](https://docs.langchain.com/docs/components/agents/agent-executor) is tasked with following your instructions. Given your last-known timezone, working hours, and busy times, it attempts to CRUD your bookings. The core logic is contained in [agent/route.ts](/apps/ai/src/app/api/agent/route.ts). Here, a [LangChain Agent Executor](https://docs.langchain.com/docs/components/agents/agent-executor) is tasked with following your instructions. Given your last-known timezone, working hours, and busy times, it attempts to CRUD your bookings.
@@ -24,10 +24,10 @@ If you haven't yet, please run the [root setup](/README.md) steps.
Before running the app, please see [env.mjs](./src/env.mjs) for all required environment variables. You'll need: Before running the app, please see [env.mjs](./src/env.mjs) for all required environment variables. You'll need:
- An [OpenAI API key](https://platform.openai.com/account/api-keys) with access to GPT-4 - An [OpenAI API key](https://platform.openai.com/account/api-keys) with access to GPT-4
- A [SendGrid API key](https://app.sendgrid.com/settings/api_keys) - A [SendGrid API key](https://app.sendgrid.com/settings/api_keys)
- A default sender email (for example, `ai@cal.dev`) - A default sender email (for example, `ai@cal.dev`)
- The Cal.ai's app ID and URL (see [add.ts](/packages/app-store/cal-ai/api/index.ts)) - The Cal.ai's app ID and URL (see [add.ts](/packages/app-store/cal-ai/api/index.ts))
To stand up the API and AI apps simultaneously, simply run `yarn dev:ai`. To stand up the API and AI apps simultaneously, simply run `yarn dev:ai`.
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@calcom/ai", "name": "@calcom/ai",
"version": "1.1.0", "version": "1.1.1",
"private": true, "private": true,
"author": "Cal.com Inc.", "author": "Cal.com Inc.",
"dependencies": { "dependencies": {
+13 -12
View File
@@ -74,18 +74,19 @@ ${
? `The email references the following @usernames and emails: ${users ? `The email references the following @usernames and emails: ${users
.map( .map(
(u) => (u) =>
(u.id ? `, id: ${u.id}` : "id: (non user)") + `${
(u.username (u.id ? `, id: ${u.id}` : "id: (non user)") +
? u.type === "fromUsername" (u.username
? `, username: @${u.username}` ? u.type === "fromUsername"
: ", username: REDACTED" ? `, username: @${u.username}`
: ", (no username)") + : ", username: REDACTED"
(u.email : ", (no username)") +
? u.type === "fromEmail" (u.email
? `, email: ${u.email}` ? u.type === "fromEmail"
: ", email: REDACTED" ? `, email: ${u.email}`
: ", (no email)") + : ", email: REDACTED"
";" : ", (no email)")
};`
) )
.join("\n")}` .join("\n")}`
: "" : ""
+4 -2
View File
@@ -1,8 +1,10 @@
import prisma from "@calcom/prisma";
import type { UserList } from "../types/user";
/* /*
* Extracts usernames (@Example) and emails (hi@example.com) from a string * Extracts usernames (@Example) and emails (hi@example.com) from a string
*/ */
import type { UserList } from "../types/user";
export const extractUsers = async (text: string) => { export const extractUsers = async (text: string) => {
const usernames = text.match(/(?<![a-zA-Z0-9_.])@[a-zA-Z0-9_]+/g)?.map((username) => username.slice(1)); const usernames = text.match(/(?<![a-zA-Z0-9_.])@[a-zA-Z0-9_]+/g)?.map((username) => username.slice(1));
const emails = text.match(/[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+/g); const emails = text.match(/[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+/g);
+2 -1
View File
@@ -1,3 +1,5 @@
import prismaMock from "../../../../../tests/libs/__mocks__/prisma";
import type { Request, Response } from "express"; import type { Request, Response } from "express";
import type { NextApiRequest, NextApiResponse } from "next"; import type { NextApiRequest, NextApiResponse } from "next";
import { createMocks } from "node-mocks-http"; import { createMocks } from "node-mocks-http";
@@ -8,7 +10,6 @@ import sendPayload from "@calcom/features/webhooks/lib/sendPayload";
import { buildBooking, buildEventType, buildWebhook } from "@calcom/lib/test/builder"; import { buildBooking, buildEventType, buildWebhook } from "@calcom/lib/test/builder";
import prisma from "@calcom/prisma"; import prisma from "@calcom/prisma";
import prismaMock from "../../../../../tests/libs/__mocks__/prisma";
import handler from "../../../pages/api/bookings/_post"; import handler from "../../../pages/api/bookings/_post";
type CustomNextApiRequest = NextApiRequest & Request; type CustomNextApiRequest = NextApiRequest & Request;
+4 -4
View File
@@ -265,8 +265,8 @@ export const AppPage = ({
{price !== 0 && ( {price !== 0 && (
<span className="block text-right"> <span className="block text-right">
{feeType === "usage-based" ? commission + "% + " + priceInDollar + "/booking" : priceInDollar} {feeType === "usage-based" ? `${commission}% + ${priceInDollar}/booking` : priceInDollar}
{feeType === "monthly" && "/" + t("month")} {feeType === "monthly" && `/${t("month")}`}
</span> </span>
)} )}
@@ -286,7 +286,7 @@ export const AppPage = ({
currency: "USD", currency: "USD",
useGrouping: false, useGrouping: false,
}).format(price)} }).format(price)}
{feeType === "monthly" && "/" + t("month")} {feeType === "monthly" && `/${t("month")}`}
</> </>
)} )}
</span> </span>
@@ -323,7 +323,7 @@ export const AppPage = ({
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="text-emphasis font-normal no-underline hover:underline" className="text-emphasis font-normal no-underline hover:underline"
href={"mailto:" + email}> href={`mailto:${email}`}>
<Mail className="text-subtle -mt-px mr-1 inline h-4 w-4" /> <Mail className="text-subtle -mt-px mr-1 inline h-4 w-4" />
{email} {email}
@@ -130,7 +130,7 @@ function ConnectedCalendarsList(props: Props) {
title={t("something_went_wrong")} title={t("something_went_wrong")}
message={ message={
<span> <span>
<Link href={"/apps/" + item.integration.slug}>{item.integration.name}</Link>:{" "} <Link href={`/apps/${item.integration.slug}`}>{item.integration.name}</Link>:{" "}
{t("calendar_error")} {t("calendar_error")}
</span> </span>
} }
@@ -76,7 +76,7 @@ export const InstallAppButtonChild = ({
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuPortal> <DropdownMenuPortal>
<DropdownMenuContent <DropdownMenuContent
className="max-w-min" className="w-auto"
onInteractOutside={(event) => { onInteractOutside={(event) => {
if (mutation.isLoading) event.preventDefault(); if (mutation.isLoading) event.preventDefault();
}}> }}>
@@ -95,6 +95,7 @@ export const InstallAppButtonChild = ({
return ( return (
<DropdownItem <DropdownItem
className="flex"
type="button" type="button"
data-testid={team.isUser ? "install-app-button-personal" : "anything else"} data-testid={team.isUser ? "install-app-button-personal" : "anything else"}
key={team.id} key={team.id}
+109 -106
View File
@@ -1,4 +1,4 @@
import { useRouter } from "next/navigation"; import Link from "next/link";
import { useState } from "react"; import { useState } from "react";
import type { EventLocationType } from "@calcom/app-store/locations"; import type { EventLocationType } from "@calcom/app-store/locations";
@@ -26,11 +26,11 @@ import {
DialogFooter, DialogFooter,
MeetingTimeInTimezones, MeetingTimeInTimezones,
showToast, showToast,
Tooltip,
TableActions, TableActions,
TextAreaField, TextAreaField,
Tooltip,
} from "@calcom/ui"; } from "@calcom/ui";
import { Check, Clock, MapPin, RefreshCcw, Send, Ban, X, CreditCard } from "@calcom/ui/components/icon"; import { Ban, Check, Clock, CreditCard, MapPin, RefreshCcw, Send, X } from "@calcom/ui/components/icon";
import useMeQuery from "@lib/hooks/useMeQuery"; import useMeQuery from "@lib/hooks/useMeQuery";
@@ -58,7 +58,6 @@ function BookingListItem(booking: BookingItemProps) {
i18n: { language }, i18n: { language },
} = useLocale(); } = useLocale();
const utils = trpc.useContext(); const utils = trpc.useContext();
const router = useRouter();
const [rejectionReason, setRejectionReason] = useState<string>(""); const [rejectionReason, setRejectionReason] = useState<string>("");
const [rejectionDialogIsOpen, setRejectionDialogIsOpen] = useState(false); const [rejectionDialogIsOpen, setRejectionDialogIsOpen] = useState(false);
const [chargeCardDialogIsOpen, setChargeCardDialogIsOpen] = useState(false); const [chargeCardDialogIsOpen, setChargeCardDialogIsOpen] = useState(false);
@@ -259,14 +258,16 @@ function BookingListItem(booking: BookingItemProps) {
.concat(booking.recurringInfo?.bookings[BookingStatus.PENDING]) .concat(booking.recurringInfo?.bookings[BookingStatus.PENDING])
.sort((date1: Date, date2: Date) => date1.getTime() - date2.getTime()); .sort((date1: Date, date2: Date) => date1.getTime() - date2.getTime());
const onClickTableData = () => { const buildBookingLink = () => {
const urlSearchParams = new URLSearchParams({ const urlSearchParams = new URLSearchParams({
allRemainingBookings: isTabRecurring.toString(), allRemainingBookings: isTabRecurring.toString(),
}); });
if (booking.attendees[0]) urlSearchParams.set("email", booking.attendees[0].email); if (booking.attendees[0]) urlSearchParams.set("email", booking.attendees[0].email);
router.push(`/booking/${booking.uid}?${urlSearchParams.toString()}`); return `/booking/${booking.uid}?${urlSearchParams.toString()}`;
}; };
const bookingLink = buildBookingLink();
const title = booking.title; const title = booking.title;
// To be used after we run query on legacy bookings // To be used after we run query on legacy bookings
// const showRecordingsButtons = booking.isRecorded && isPast && isConfirmed; // const showRecordingsButtons = booking.isRecorded && isPast && isConfirmed;
@@ -337,54 +338,11 @@ function BookingListItem(booking: BookingItemProps) {
</Dialog> </Dialog>
<tr data-testid="booking-item" className="hover:bg-muted group flex flex-col sm:flex-row"> <tr data-testid="booking-item" className="hover:bg-muted group flex flex-col sm:flex-row">
<td <td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:min-w-[12rem]">
className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:min-w-[12rem]" <Link href={bookingLink}>
onClick={onClickTableData}> <div className="cursor-pointer py-4">
<div className="cursor-pointer py-4">
<div className="text-emphasis text-sm leading-6">{startTime}</div>
<div className="text-subtle text-sm">
{formatTime(booking.startTime, user?.timeFormat, user?.timeZone)} -{" "}
{formatTime(booking.endTime, user?.timeFormat, user?.timeZone)}
<MeetingTimeInTimezones
timeFormat={user?.timeFormat}
userTimezone={user?.timeZone}
startTime={booking.startTime}
endTime={booking.endTime}
attendees={booking.attendees}
/>
</div>
{isPending && (
<Badge className="ltr:mr-2 rtl:ml-2" variant="orange">
{t("unconfirmed")}
</Badge>
)}
{booking.eventType?.team && (
<Badge className="ltr:mr-2 rtl:ml-2" variant="gray">
{booking.eventType.team.name}
</Badge>
)}
{booking.paid && !booking.payment[0] ? (
<Badge className="ltr:mr-2 rtl:ml-2" variant="orange">
{t("error_collecting_card")}
</Badge>
) : booking.paid ? (
<Badge className="ltr:mr-2 rtl:ml-2" variant="green" data-testid="paid_badge">
{booking.payment[0].paymentOption === "HOLD" ? t("card_held") : t("paid")}
</Badge>
) : null}
{recurringDates !== undefined && (
<div className="text-muted mt-2 text-sm">
<RecurringBookingsTooltip booking={booking} recurringDates={recurringDates} />
</div>
)}
</div>
</td>
<td className={"w-full px-4" + (isRejected ? " line-through" : "")} onClick={onClickTableData}>
{/* Time and Badges for mobile */}
<div className="w-full pb-2 pt-4 sm:hidden">
<div className="flex w-full items-center justify-between sm:hidden">
<div className="text-emphasis text-sm leading-6">{startTime}</div> <div className="text-emphasis text-sm leading-6">{startTime}</div>
<div className="text-subtle pr-2 text-sm"> <div className="text-subtle text-sm">
{formatTime(booking.startTime, user?.timeFormat, user?.timeZone)} -{" "} {formatTime(booking.startTime, user?.timeFormat, user?.timeZone)} -{" "}
{formatTime(booking.endTime, user?.timeFormat, user?.timeZone)} {formatTime(booking.endTime, user?.timeFormat, user?.timeZone)}
<MeetingTimeInTimezones <MeetingTimeInTimezones
@@ -395,66 +353,111 @@ function BookingListItem(booking: BookingItemProps) {
attendees={booking.attendees} attendees={booking.attendees}
/> />
</div> </div>
{isPending && (
<Badge className="ltr:mr-2 rtl:ml-2" variant="orange">
{t("unconfirmed")}
</Badge>
)}
{booking.eventType?.team && (
<Badge className="ltr:mr-2 rtl:ml-2" variant="gray">
{booking.eventType.team.name}
</Badge>
)}
{booking.paid && !booking.payment[0] ? (
<Badge className="ltr:mr-2 rtl:ml-2" variant="orange">
{t("error_collecting_card")}
</Badge>
) : booking.paid ? (
<Badge className="ltr:mr-2 rtl:ml-2" variant="green" data-testid="paid_badge">
{booking.payment[0].paymentOption === "HOLD" ? t("card_held") : t("paid")}
</Badge>
) : null}
{recurringDates !== undefined && (
<div className="text-muted mt-2 text-sm">
<RecurringBookingsTooltip booking={booking} recurringDates={recurringDates} />
</div>
)}
</div> </div>
</Link>
{isPending && ( </td>
<Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="orange"> <td className={`w-full px-4${isRejected ? " line-through" : ""}`}>
{t("unconfirmed")} <Link href={bookingLink}>
</Badge> {/* Time and Badges for mobile */}
)} <div className="w-full pb-2 pt-4 sm:hidden">
{booking.eventType?.team && ( <div className="flex w-full items-center justify-between sm:hidden">
<Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="gray"> <div className="text-emphasis text-sm leading-6">{startTime}</div>
{booking.eventType.team.name} <div className="text-subtle pr-2 text-sm">
</Badge> {formatTime(booking.startTime, user?.timeFormat, user?.timeZone)} -{" "}
)} {formatTime(booking.endTime, user?.timeFormat, user?.timeZone)}
{!!booking?.eventType?.price && !booking.paid && ( <MeetingTimeInTimezones
<Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="orange"> timeFormat={user?.timeFormat}
{t("pending_payment")} userTimezone={user?.timeZone}
</Badge> startTime={booking.startTime}
)} endTime={booking.endTime}
{recurringDates !== undefined && ( attendees={booking.attendees}
<div className="text-muted text-sm sm:hidden"> />
<RecurringBookingsTooltip booking={booking} recurringDates={recurringDates} /> </div>
</div> </div>
)}
</div>
<div className="cursor-pointer py-4"> {isPending && (
<div <Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="orange">
title={title} {t("unconfirmed")}
className={classNames( </Badge>
"max-w-10/12 sm:max-w-56 text-emphasis text-sm font-medium leading-6 md:max-w-full", )}
isCancelled ? "line-through" : "" {booking.eventType?.team && (
)}> <Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="gray">
{title} {booking.eventType.team.name}
<span> </span> </Badge>
)}
{paymentAppData.enabled && !booking.paid && booking.payment.length && ( {!!booking?.eventType?.price && !booking.paid && (
<Badge className="me-2 ms-2 hidden sm:inline-flex" variant="orange"> <Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="orange">
{t("pending_payment")} {t("pending_payment")}
</Badge> </Badge>
)} )}
{recurringDates !== undefined && (
<div className="text-muted text-sm sm:hidden">
<RecurringBookingsTooltip booking={booking} recurringDates={recurringDates} />
</div>
)}
</div> </div>
{booking.description && (
<div className="cursor-pointer py-4">
<div <div
className="max-w-10/12 sm:max-w-32 md:max-w-52 xl:max-w-80 text-default truncate text-sm" title={title}
title={booking.description}> className={classNames(
&quot;{booking.description}&quot; "max-w-10/12 sm:max-w-56 text-emphasis text-sm font-medium leading-6 md:max-w-full",
isCancelled ? "line-through" : ""
)}>
{title}
<span> </span>
{paymentAppData.enabled && !booking.paid && booking.payment.length && (
<Badge className="me-2 ms-2 hidden sm:inline-flex" variant="orange">
{t("pending_payment")}
</Badge>
)}
</div> </div>
)} {booking.description && (
{booking.attendees.length !== 0 && ( <div
<DisplayAttendees className="max-w-10/12 sm:max-w-32 md:max-w-52 xl:max-w-80 text-default truncate text-sm"
attendees={booking.attendees} title={booking.description}>
user={booking.user} &quot;{booking.description}&quot;
currentEmail={user?.email} </div>
/> )}
)} {booking.attendees.length !== 0 && (
{isCancelled && booking.rescheduled && ( <DisplayAttendees
<div className="mt-2 inline-block md:hidden"> attendees={booking.attendees}
<RequestSentMessage /> user={booking.user}
</div> currentEmail={user?.email}
)} />
</div> )}
{isCancelled && booking.rescheduled && (
<div className="mt-2 inline-block md:hidden">
<RequestSentMessage />
</div>
)}
</div>
</Link>
</td> </td>
<td className="flex w-full justify-end py-4 pl-4 text-right text-sm font-medium ltr:pr-4 rtl:pl-4 sm:pl-0"> <td className="flex w-full justify-end py-4 pl-4 text-right text-sm font-medium ltr:pr-4 rtl:pl-4 sm:pl-0">
{isUpcoming && !isCancelled ? ( {isUpcoming && !isCancelled ? (
@@ -573,7 +576,7 @@ const FirstAttendee = ({
<a <a
key={user.email} key={user.email}
className=" hover:text-blue-500" className=" hover:text-blue-500"
href={"mailto:" + user.email} href={`mailto:${user.email}`}
onClick={(e) => e.stopPropagation()}> onClick={(e) => e.stopPropagation()}>
{user.name} {user.name}
</a> </a>
@@ -587,7 +590,7 @@ type AttendeeProps = {
const Attendee = ({ email, name }: AttendeeProps) => { const Attendee = ({ email, name }: AttendeeProps) => {
return ( return (
<a className="hover:text-blue-500" href={"mailto:" + email} onClick={(e) => e.stopPropagation()}> <a className="hover:text-blue-500" href={`mailto:${email}`} onClick={(e) => e.stopPropagation()}>
{name || email} {name || email}
</a> </a>
); );
@@ -121,7 +121,7 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
message: `Invalid URL for ${eventLocationType.label}. ${ message: `Invalid URL for ${eventLocationType.label}. ${
sampleUrl ? "Sample URL: " + sampleUrl : "" sampleUrl ? `Sample URL: ${sampleUrl}` : ""
}`, }`,
}); });
} }
@@ -67,7 +67,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
(!user?.theme && typeof document !== "undefined" && document.documentElement.classList.contains("dark")); (!user?.theme && typeof document !== "undefined" && document.documentElement.classList.contains("dark"));
eventType.bookingFields.forEach(({ name }) => { eventType.bookingFields.forEach(({ name }) => {
bookingFields[name] = name + " input"; bookingFields[name] = `${name} input`;
}); });
const eventNameObject: EventNameObjectType = { const eventNameObject: EventNameObjectType = {
@@ -189,7 +189,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
value: 0, value: 0,
}, },
...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({ ...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({
label: minutes + " " + t("minutes"), label: `minutes ${t("minutes")}`,
value: minutes, value: minutes,
})), })),
]; ];
@@ -225,7 +225,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
value: 0, value: 0,
}, },
...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({ ...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({
label: minutes + " " + t("minutes"), label: `minutes ${t("minutes")}`,
value: minutes, value: minutes,
})), })),
]; ];
@@ -272,7 +272,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
value: -1, value: -1,
}, },
...[5, 10, 15, 20, 30, 45, 60, 75, 90, 105, 120].map((minutes) => ({ ...[5, 10, 15, 20, 30, 45, 60, 75, 90, 105, 120].map((minutes) => ({
label: minutes + " " + t("minutes"), label: `minutes ${t("minutes")}`,
value: minutes, value: minutes,
})), })),
]; ];
@@ -13,8 +13,10 @@ import type { EventLocationType } from "@calcom/app-store/locations";
import { getEventLocationType, MeetLocationType, LocationType } from "@calcom/app-store/locations"; import { getEventLocationType, MeetLocationType, LocationType } from "@calcom/app-store/locations";
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager"; import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider"; import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { classNames } from "@calcom/lib";
import { CAL_URL } from "@calcom/lib/constants"; import { CAL_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import invertLogoOnDark from "@calcom/lib/invertLogoOnDark";
import { md } from "@calcom/lib/markdownIt"; import { md } from "@calcom/lib/markdownIt";
import { slugify } from "@calcom/lib/slugify"; import { slugify } from "@calcom/lib/slugify";
import turndown from "@calcom/lib/turndownService"; import turndown from "@calcom/lib/turndownService";
@@ -131,12 +133,12 @@ export const EventSetupTab = (
}; };
}); });
const multipleDurationOptions = [5, 10, 15, 20, 25, 30, 45, 50, 60, 75, 80, 90, 120, 150, 180].map( const multipleDurationOptions = [
(mins) => ({ 5, 10, 15, 20, 25, 30, 45, 50, 60, 75, 80, 90, 120, 150, 180, 240, 480,
value: mins, ].map((mins) => ({
label: t("multiple_duration_mins", { count: mins }), value: mins,
}) label: t("multiple_duration_mins", { count: mins }),
); }));
const [selectedMultipleDuration, setSelectedMultipleDuration] = useState< const [selectedMultipleDuration, setSelectedMultipleDuration] = useState<
MultiValue<{ MultiValue<{
@@ -301,7 +303,10 @@ export const EventSetupTab = (
<div className="flex items-center"> <div className="flex items-center">
<img <img
src={eventLocationType.iconUrl} src={eventLocationType.iconUrl}
className="h-4 w-4 dark:invert-[.65]" className={classNames(
"h-4 w-4",
classNames(invertLogoOnDark(eventLocationType.iconUrl))
)}
alt={`${eventLocationType.label} logo`} alt={`${eventLocationType.label} logo`}
/> />
<span className="ms-1 line-clamp-1 text-sm">{`${eventLabel} ${ <span className="ms-1 line-clamp-1 text-sm">{`${eventLabel} ${
@@ -247,7 +247,7 @@ function EventTypeSingleLayout({
return ( return (
<Shell <Shell
backPath="/event-types" backPath="/event-types"
title={eventType.title + " | " + t("event_type")} title={`${eventType.title} | ${t("event_type")}`}
heading={eventType.title} heading={eventType.title}
CTA={ CTA={
<div className="flex items-center justify-end"> <div className="flex items-center justify-end">
+1 -1
View File
@@ -22,7 +22,7 @@ const Member = ({ member, teamName }: { member: MemberType; teamName: string | n
return ( return (
<Link key={member.id} href={{ pathname: `/${member.username}`, query: queryParamsToForward }}> <Link key={member.id} href={{ pathname: `/${member.username}`, query: queryParamsToForward }}>
<div className="sm:min-w-80 sm:max-w-80 bg-default hover:bg-muted border-subtle group flex min-h-full flex-col space-y-2 rounded-md border p-4 hover:cursor-pointer"> <div className="sm:min-w-80 sm:max-w-80 bg-default hover:bg-muted border-subtle group flex min-h-full flex-col space-y-2 rounded-md border p-4 hover:cursor-pointer">
<Avatar size="md" alt={member.name || ""} imageSrc={"/" + member.username + "/avatar.png"} /> <Avatar size="md" alt={member.name || ""} imageSrc={`/${member.username}/avatar.png`} />
<section className="mt-2 line-clamp-4 w-full space-y-1"> <section className="mt-2 line-clamp-4 w-full space-y-1">
<p className="text-default font-medium">{member.name}</p> <p className="text-default font-medium">{member.name}</p>
<div className="text-subtle line-clamp-3 overflow-ellipsis text-sm font-normal"> <div className="text-subtle line-clamp-3 overflow-ellipsis text-sm font-normal">
@@ -4,6 +4,7 @@ import { components } from "react-select";
import type { EventLocationType } from "@calcom/app-store/locations"; import type { EventLocationType } from "@calcom/app-store/locations";
import type { CredentialDataWithTeamName } from "@calcom/app-store/utils"; import type { CredentialDataWithTeamName } from "@calcom/app-store/utils";
import { classNames } from "@calcom/lib"; import { classNames } from "@calcom/lib";
import invertLogoOnDark from "@calcom/lib/invertLogoOnDark";
import { Select } from "@calcom/ui"; import { Select } from "@calcom/ui";
export type LocationOption = { export type LocationOption = {
@@ -22,7 +23,7 @@ export type GroupOptionType = GroupBase<LocationOption>;
const OptionWithIcon = ({ icon, label }: { icon?: string; label: string }) => { const OptionWithIcon = ({ icon, label }: { icon?: string; label: string }) => {
return ( return (
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{icon && <img src={icon} alt="cover" className="h-3.5 w-3.5 dark:invert-[.65]" />} {icon && <img src={icon} alt="cover" className={classNames("h-3.5 w-3.5", invertLogoOnDark(icon))} />}
<span className={classNames("text-sm font-medium")}>{label}</span> <span className={classNames("text-sm font-medium")}>{label}</span>
</div> </div>
); );
+2 -2
View File
@@ -179,14 +179,14 @@ function getThemeProviderProps({
); );
} }
const appearanceIdSuffix = themeBasis ? ":" + themeBasis : ""; const appearanceIdSuffix = themeBasis ? `:${themeBasis}` : "";
const forcedTheme = themeSupport === ThemeSupport.None ? "light" : undefined; const forcedTheme = themeSupport === ThemeSupport.None ? "light" : undefined;
let embedExplicitlySetThemeSuffix = ""; let embedExplicitlySetThemeSuffix = "";
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
const embedTheme = window.getEmbedTheme(); const embedTheme = window.getEmbedTheme();
if (embedTheme) { if (embedTheme) {
embedExplicitlySetThemeSuffix = ":" + embedTheme; embedExplicitlySetThemeSuffix = `:${embedTheme}`;
} }
} }
+1 -1
View File
@@ -21,7 +21,7 @@ function getCspPolicy(nonce: string) {
script-src ${ script-src ${
IS_PRODUCTION IS_PRODUCTION
? // 'self' 'unsafe-inline' https: added for Browsers not supporting strict-dynamic not supporting strict-dynamic ? // 'self' 'unsafe-inline' https: added for Browsers not supporting strict-dynamic not supporting strict-dynamic
"'nonce-" + nonce + "' 'strict-dynamic' 'self' 'unsafe-inline' https:" `'nonce-${nonce}' 'strict-dynamic' 'self' 'unsafe-inline' https:`
: // Note: We could use 'strict-dynamic' with 'nonce-..' instead of unsafe-inline but there are some streaming related scripts that get blocked(because they don't have nonce on them). It causes a really frustrating full page error model by Next.js to show up sometimes : // Note: We could use 'strict-dynamic' with 'nonce-..' instead of unsafe-inline but there are some streaming related scripts that get blocked(because they don't have nonce on them). It causes a really frustrating full page error model by Next.js to show up sometimes
"'unsafe-inline' 'unsafe-eval' https: http:" "'unsafe-inline' 'unsafe-eval' https: http:"
}; };
+3 -8
View File
@@ -15,14 +15,9 @@ export default function withEmbedSsr(getServerSideProps: GetServerSideProps) {
const destinationUrlObj = new URL(ssrResponse.redirect.destination, "https://base"); const destinationUrlObj = new URL(ssrResponse.redirect.destination, "https://base");
// Make sure that redirect happens to /embed page and pass on embed query param as is for preserving Cal JS API namespace // Make sure that redirect happens to /embed page and pass on embed query param as is for preserving Cal JS API namespace
const newDestinationUrl = const newDestinationUrl = `${
destinationUrlObj.pathname + destinationUrlObj.pathname
"/embed?" + }/embed?${destinationUrlObj.searchParams.toString()}&layout=${layout}&embed=${embed}`;
destinationUrlObj.searchParams.toString() +
"&layout=" +
layout +
"&embed=" +
embed;
return { return {
...ssrResponse, ...ssrResponse,
+2 -1
View File
@@ -40,7 +40,7 @@ const middleware: NextMiddleware = async (req) => {
requestHeaders.set("x-cal-timezone", req.headers.get("x-vercel-ip-timezone") ?? ""); requestHeaders.set("x-cal-timezone", req.headers.get("x-vercel-ip-timezone") ?? "");
} }
if (url.pathname.startsWith("/auth/login")) { if (url.pathname.startsWith("/auth/login") || url.pathname.startsWith("/login")) {
// Use this header to actually enforce CSP, otherwise it is running in Report Only mode on all pages. // Use this header to actually enforce CSP, otherwise it is running in Report Only mode on all pages.
requestHeaders.set("x-csp-enforce", "true"); requestHeaders.set("x-csp-enforce", "true");
} }
@@ -68,6 +68,7 @@ export const config = {
matcher: [ matcher: [
"/:path*/embed", "/:path*/embed",
"/api/trpc/:path*", "/api/trpc/:path*",
"/login",
"/auth/login", "/auth/login",
/** /**
* Paths required by routingForms.handle * Paths required by routingForms.handle
+2 -2
View File
@@ -21,11 +21,11 @@ process.env.NEXT_PUBLIC_CALCOM_VERSION = version;
// So we can test deploy previews preview // So we can test deploy previews preview
if (process.env.VERCEL_URL && !process.env.NEXT_PUBLIC_WEBAPP_URL) { if (process.env.VERCEL_URL && !process.env.NEXT_PUBLIC_WEBAPP_URL) {
process.env.NEXT_PUBLIC_WEBAPP_URL = "https://" + process.env.VERCEL_URL; process.env.NEXT_PUBLIC_WEBAPP_URL = `https://${process.env.VERCEL_URL}`;
} }
// Check for configuration of NEXTAUTH_URL before overriding // Check for configuration of NEXTAUTH_URL before overriding
if (!process.env.NEXTAUTH_URL && process.env.NEXT_PUBLIC_WEBAPP_URL) { if (!process.env.NEXTAUTH_URL && process.env.NEXT_PUBLIC_WEBAPP_URL) {
process.env.NEXTAUTH_URL = process.env.NEXT_PUBLIC_WEBAPP_URL + "/api/auth"; process.env.NEXTAUTH_URL = `${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/auth`;
} }
if (!process.env.NEXT_PUBLIC_WEBSITE_URL) { if (!process.env.NEXT_PUBLIC_WEBSITE_URL) {
process.env.NEXT_PUBLIC_WEBSITE_URL = process.env.NEXT_PUBLIC_WEBAPP_URL; process.env.NEXT_PUBLIC_WEBSITE_URL = process.env.NEXT_PUBLIC_WEBAPP_URL;
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@calcom/web", "name": "@calcom/web",
"version": "3.3.4", "version": "3.3.5",
"private": true, "private": true,
"scripts": { "scripts": {
"analyze": "ANALYZE=true next build", "analyze": "ANALYZE=true next build",
+1 -1
View File
@@ -125,7 +125,7 @@ export function UserPage(props: InferGetServerSidePropsType<typeof getServerSide
{user.away ? ( {user.away ? (
<div className="overflow-hidden rounded-sm border "> <div className="overflow-hidden rounded-sm border ">
<div className="text-muted p-8 text-center"> <div className="text-muted p-8 text-center">
<h2 className="font-cal text-default mb-2 text-3xl">😴{" " + t("user_away")}</h2> <h2 className="font-cal text-default mb-2 text-3xl">😴{` ${t("user_away")}`}</h2>
<p className="mx-auto max-w-md">{t("user_away_description") as string}</p> <p className="mx-auto max-w-md">{t("user_away_description") as string}</p>
</div> </div>
</div> </div>
+14
View File
@@ -0,0 +1,14 @@
import type { NextApiRequest, NextApiResponse } from "next";
import isAuthorized from "@calcom/features/auth/lib/oAuthAuthorization";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const requriedScopes = ["READ_PROFILE"];
const account = await isAuthorized(req, requriedScopes);
if (!account) {
return res.status(401).json({ message: "Unauthorized" });
}
return res.status(201).json({ username: account.name });
}
@@ -0,0 +1,68 @@
import jwt from "jsonwebtoken";
import type { NextApiRequest, NextApiResponse } from "next";
import type { OAuthTokenPayload } from "pages/api/auth/oauth/token";
import prisma from "@calcom/prisma";
import { generateSecret } from "@calcom/trpc/server/routers/viewer/oAuth/addClient.handler";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "POST") {
res.status(405).json({ message: "Invalid method" });
return;
}
const refreshToken = req.headers.authorization?.split(" ")[1] || "";
const { client_id, client_secret, grant_type } = req.body;
if (grant_type !== "refresh_token") {
res.status(400).json({ message: "grant type invalid" });
return;
}
const [hashedSecret] = generateSecret(client_secret);
const client = await prisma.oAuthClient.findFirst({
where: {
clientId: client_id,
clientSecret: hashedSecret,
},
select: {
redirectUri: true,
},
});
if (!client) {
res.status(401).json({ message: "Unauthorized" });
return;
}
const secretKey = process.env.CALENDSO_ENCRYPTION_KEY || "";
let decodedRefreshToken: OAuthTokenPayload;
try {
decodedRefreshToken = jwt.verify(refreshToken, secretKey) as OAuthTokenPayload;
} catch {
res.status(401).json({ message: "Unauthorized" });
return;
}
if (!decodedRefreshToken || decodedRefreshToken.token_type !== "Refresh Token") {
res.status(401).json({ message: "Unauthorized" });
return;
}
const payload: OAuthTokenPayload = {
userId: decodedRefreshToken.userId,
scope: decodedRefreshToken.scope,
token_type: "Access Token",
clientId: client_id,
};
const access_token = jwt.sign(payload, secretKey, {
expiresIn: 1800, // 30 min
});
res.status(200).json({ access_token });
}
+104
View File
@@ -0,0 +1,104 @@
import jwt from "jsonwebtoken";
import type { NextApiRequest, NextApiResponse } from "next";
import prisma from "@calcom/prisma";
import { generateSecret } from "@calcom/trpc/server/routers/viewer/oAuth/addClient.handler";
export type OAuthTokenPayload = {
userId?: number | null;
teamId?: number | null;
token_type: string;
scope: string[];
clientId: string;
};
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "POST") {
res.status(405).json({ message: "Invalid method" });
return;
}
const { code, client_id, client_secret, grant_type, redirect_uri } = req.body;
if (grant_type !== "authorization_code") {
res.status(400).json({ message: "grant_type invalid" });
return;
}
const [hashedSecret] = generateSecret(client_secret);
const client = await prisma.oAuthClient.findFirst({
where: {
clientId: client_id,
clientSecret: hashedSecret,
},
select: {
redirectUri: true,
},
});
if (!client || client.redirectUri !== redirect_uri) {
res.status(401).json({ message: "Unauthorized" });
return;
}
const accessCode = await prisma.accessCode.findFirst({
where: {
code: code,
clientId: client_id,
expiresAt: {
gt: new Date(),
},
},
});
//delete all expired accessCodes + the one that is used here
await prisma.accessCode.deleteMany({
where: {
OR: [
{
expiresAt: {
lt: new Date(),
},
},
{
code: code,
clientId: client_id,
},
],
},
});
if (!accessCode) {
res.status(401).json({ message: "Unauthorized" });
return;
}
const secretKey = process.env.CALENDSO_ENCRYPTION_KEY || "";
const payloadAuthToken: OAuthTokenPayload = {
userId: accessCode.userId,
teamId: accessCode.teamId,
scope: accessCode.scopes,
token_type: "Access Token",
clientId: client_id,
};
const payloadRefreshToken: OAuthTokenPayload = {
userId: accessCode.userId,
teamId: accessCode.teamId,
scope: accessCode.scopes,
token_type: "Refresh Token",
clientId: client_id,
};
const access_token = jwt.sign(payloadAuthToken, secretKey, {
expiresIn: 1800, // 30 min
});
const refresh_token = jwt.sign(payloadRefreshToken, secretKey, {
expiresIn: 30 * 24 * 60 * 60, // 30 days
});
res.status(200).json({ access_token, refresh_token });
}
@@ -19,7 +19,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
return res.status(400).json({ message: "Google client_secret missing." }); return res.status(400).json({ message: "Google client_secret missing." });
// use differnt callback to normal calendar connection // use differnt callback to normal calendar connection
const redirect_uri = WEBAPP_URL + "/api/teams/googleworkspace/callback"; const redirect_uri = `${WEBAPP_URL}/api/teams/googleworkspace/callback`;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri); const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri);
const authUrl = oAuth2Client.generateAuthUrl({ const authUrl = oAuth2Client.generateAuthUrl({
@@ -36,7 +36,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if (!client_secret || typeof client_secret !== "string") if (!client_secret || typeof client_secret !== "string")
return res.status(400).json({ message: "Google client_secret missing." }); return res.status(400).json({ message: "Google client_secret missing." });
const redirect_uri = WEBAPP_URL + "/api/teams/googleworkspace/callback"; const redirect_uri = `${WEBAPP_URL}/api/teams/googleworkspace/callback`;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri); const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uri);
if (!code) { if (!code) {
@@ -54,11 +54,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}); });
if (!teamId) { if (!teamId) {
res.redirect(getSafeRedirectUrl(WEBAPP_URL + "/settings") ?? `${WEBAPP_URL}/teams`); res.redirect(getSafeRedirectUrl(`${WEBAPP_URL}/settings`) ?? `${WEBAPP_URL}/teams`);
} }
res.redirect( res.redirect(
getSafeRedirectUrl(WEBAPP_URL + `/settings/teams/${teamId}/members?inviteModal=true&bulk=true`) ?? getSafeRedirectUrl(`${WEBAPP_URL}/settings/teams/${teamId}/members?inviteModal=true&bulk=true`) ??
`${WEBAPP_URL}/teams` `${WEBAPP_URL}/teams`
); );
} }
+4
View File
@@ -0,0 +1,4 @@
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import { oAuthRouter } from "@calcom/trpc/server/routers/viewer/oAuth/_router";
export default createNextApiHandler(oAuthRouter);
+1 -1
View File
@@ -31,7 +31,7 @@ export default function Apps({ categories }: inferSSRProps<typeof getServerSideP
{categories.map((category) => ( {categories.map((category) => (
<Link <Link
key={category.name} key={category.name}
href={"/apps/categories/" + category.name} href={`/apps/categories/${category.name}`}
data-testid={`app-store-category-${category.name}`} data-testid={`app-store-category-${category.name}`}
className="bg-subtle relative flex rounded-sm px-6 py-4 sm:block"> className="bg-subtle relative flex rounded-sm px-6 py-4 sm:block">
<div className="self-center"> <div className="self-center">
+179
View File
@@ -0,0 +1,179 @@
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useSearchParams } from "next/navigation";
import { useState, useEffect } from "react";
import { APP_NAME } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { Avatar, Button, Select } from "@calcom/ui";
import { Plus, Info } from "@calcom/ui/components/icon";
import PageWrapper from "@components/PageWrapper";
export default function Authorize() {
const { t } = useLocale();
const { status } = useSession();
const router = useRouter();
const searchParams = useSearchParams();
const client_id = searchParams?.get("client_id") as string;
const state = searchParams?.get("state") as string;
const scope = searchParams?.get("scope") as string;
const queryString = searchParams.toString();
const [selectedAccount, setSelectedAccount] = useState<{ value: string; label: string } | null>();
const scopes = scope ? scope.toString().split(",") : [];
const { data: client, isLoading: isLoadingGetClient } = trpc.viewer.oAuth.getClient.useQuery(
{
clientId: client_id as string,
},
{
enabled: status !== "loading",
}
);
const { data, isLoading: isLoadingProfiles } = trpc.viewer.teamsAndUserProfilesQuery.useQuery();
const generateAuthCodeMutation = trpc.viewer.oAuth.generateAuthCode.useMutation({
onSuccess: (data) => {
window.location.href = `${client?.redirectUri}?code=${data.authorizationCode}&state=${state}`;
},
});
const mappedProfiles = data
? data
.filter((profile) => !profile.readOnly)
.map((profile) => ({
label: profile.name || profile.slug || "",
value: profile.slug || "",
}))
: [];
useEffect(() => {
if (mappedProfiles.length > 0) {
setSelectedAccount(mappedProfiles[0]);
}
}, [isLoadingProfiles]);
useEffect(() => {
if (status === "unauthenticated") {
const urlSearchParams = new URLSearchParams({
callbackUrl: `auth/oauth2/authorize?${queryString}`,
});
router.replace(`/auth/login?${urlSearchParams.toString()}`);
}
}, [status]);
const isLoading = isLoadingGetClient || isLoadingProfiles || status !== "authenticated";
if (isLoading) {
return <></>;
}
if (!client) {
return <div>{t("unauthorized")}</div>;
}
return (
<div className="flex min-h-screen items-center justify-center">
<div className="mt-2 max-w-xl rounded-md bg-white px-9 pb-3 pt-2">
<div className="flex items-center justify-center">
<Avatar
alt=""
fallback={<Plus className="text-subtle h-6 w-6" />}
className="items-center"
imageSrc={client.logo}
size="lg"
/>
<div className="relative -ml-6 h-24 w-24">
<div className="absolute inset-0 flex items-center justify-center">
<div className="flex h-[70px] w-[70px] items-center justify-center rounded-full bg-white">
<img src="/cal-com-icon.svg" alt="Logo" className="h-16 w-16 rounded-full" />
</div>
</div>
</div>
</div>
<h1 className="px-5 pb-5 pt-3 text-center text-2xl font-bold tracking-tight">
{t("access_cal_account", { clientName: client.name, appName: APP_NAME })}
</h1>
<div className="mb-1 text-sm font-medium">{t("select_account_team")}</div>
<Select
isSearchable={true}
id="account-select"
onChange={(value) => {
setSelectedAccount(value);
}}
className="w-52"
defaultValue={selectedAccount || mappedProfiles[0]}
options={mappedProfiles}
/>
<div className="mb-4 mt-5 font-medium">{t("allow_client_to", { clientName: client.name })}</div>
<ul className="space-y-4 text-sm">
<li className="relative pl-5">
<span className="absolute left-0">&#10003;</span>{" "}
{t("associate_with_cal_account", { clientName: client.name })}
</li>
<li className="relative pl-5">
<span className="absolute left-0">&#10003;</span> {t("see_personal_info")}
</li>
<li className="relative pl-5">
<span className="absolute left-0">&#10003;</span> {t("see_primary_email_address")}
</li>
<li className="relative pl-5">
<span className="absolute left-0">&#10003;</span> {t("connect_installed_apps")}
</li>
<li className="relative pl-5">
<span className="absolute left-0">&#10003;</span> {t("access_event_type")}
</li>
<li className="relative pl-5">
<span className="absolute left-0">&#10003;</span> {t("access_availability")}
</li>
<li className="relative pl-5">
<span className="absolute left-0">&#10003;</span> {t("access_bookings")}
</li>
</ul>
<div className="bg-subtle mb-8 mt-8 flex rounded-md p-3">
<div>
<Info className="mr-1 mt-0.5 h-4 w-4" />
</div>
<div className="ml-1 ">
<div className="mb-1 text-sm font-medium">
{t("allow_client_to_do", { clientName: client.name })}
</div>
<div className="text-sm">{t("oauth_access_information", { appName: APP_NAME })}</div>{" "}
</div>
</div>
<div className="border-subtle border- -mx-9 mb-4 border-b" />
<div className="flex justify-end">
<Button
className="mr-2"
color="minimal"
onClick={() => {
window.location.href = `${client.redirectUri}`;
}}>
{t("go_back")}
</Button>
<Button
onClick={() => {
generateAuthCodeMutation.mutate({
clientId: client_id as string,
scopes,
teamSlug: selectedAccount?.value.startsWith("team/")
? selectedAccount?.value.substring(5)
: undefined, // team account starts with /team/<slug>
});
}}
data-testid="allow-button">
{t("allow")}
</Button>
</div>
</div>
</div>
);
}
Authorize.PageWrapper = PageWrapper;
+4 -4
View File
@@ -30,12 +30,12 @@ export default function Provider(props: SSOProviderPageProps) {
const email = searchParams?.get("email"); const email = searchParams?.get("email");
if (!email) { if (!email) {
router.push("/auth/error?error=" + "Email not provided"); router.push(`/auth/error?error=Email not provided`);
return; return;
} }
if (!props.isSAMLLoginEnabled) { if (!props.isSAMLLoginEnabled) {
router.push("/auth/error?error=" + "SAML login not enabled"); router.push(`/auth/error?error=SAML login not enabled`);
return; return;
} }
@@ -56,7 +56,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
const providerParam = asStringOrNull(context.query.provider); const providerParam = asStringOrNull(context.query.provider);
const emailParam = asStringOrNull(context.query.email); const emailParam = asStringOrNull(context.query.email);
const usernameParam = asStringOrNull(context.query.username); const usernameParam = asStringOrNull(context.query.username);
const successDestination = "/getting-started" + (usernameParam ? `?username=${usernameParam}` : ""); const successDestination = `/getting-started${usernameParam ? `?username=${usernameParam}` : ""}`;
if (!providerParam) { if (!providerParam) {
throw new Error(`File is not named sso/[provider]`); throw new Error(`File is not named sso/[provider]`);
} }
@@ -120,7 +120,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
if (error) { if (error) {
return { return {
redirect: { redirect: {
destination: "/auth/error?error=" + error, destination: `/auth/error?error=${error}`,
permanent: false, permanent: false,
}, },
}; };
+1 -1
View File
@@ -120,7 +120,7 @@ export default function Verify() {
? "Your payment failed" ? "Your payment failed"
: sessionId : sessionId
? "Payment successful!" ? "Payment successful!"
: "Verify your email" + " | " + APP_NAME} : `Verify your email | ${APP_NAME}`}
</title> </title>
</Head> </Head>
<div className="flex min-h-screen flex-col items-center justify-center px-6"> <div className="flex min-h-screen flex-col items-center justify-center px-6">
+1 -1
View File
@@ -151,7 +151,7 @@ export default function Availability() {
return ( return (
<Shell <Shell
backPath={fromEventType ? true : "/availability"} backPath={fromEventType ? true : "/availability"}
title={schedule?.name ? schedule.name + " | " + t("availability") : t("availability")} title={schedule?.name ? `${schedule.name} | ${t("availability")}` : t("availability")}
heading={ heading={
<Controller <Controller
control={form.control} control={form.control}
+2 -2
View File
@@ -133,7 +133,7 @@ Troubleshoot.PageWrapper = PageWrapper;
function convertMinsToHrsMins(mins: number) { function convertMinsToHrsMins(mins: number) {
const h = Math.floor(mins / 60); const h = Math.floor(mins / 60);
const m = mins % 60; const m = mins % 60;
const hs = h < 10 ? "0" + h : h; const hs = h < 10 ? `0${h}` : h;
const ms = m < 10 ? "0" + m : m; const ms = m < 10 ? `0${m}` : m;
return `${hs}:${ms}`; return `${hs}:${ms}`;
} }
+41 -40
View File
@@ -269,13 +269,13 @@ export default function Success(props: SuccessProps) {
} }
if (needsConfirmation) { if (needsConfirmation) {
if (props.profile.name !== null) { if (props.profile.name !== null) {
return t("user_needs_to_confirm_or_reject_booking" + titleSuffix, { return t(`user_needs_to_confirm_or_reject_booking${titleSuffix}`, {
user: props.profile.name, user: props.profile.name,
}); });
} }
return t("needs_to_be_confirmed_or_rejected" + titleSuffix); return t(`needs_to_be_confirmed_or_rejected${titleSuffix}`);
} }
return t("emailed_you_and_attendees" + titleSuffix); return t(`emailed_you_and_attendees${titleSuffix}`);
} }
// This is a weird case where the same route can be opened in booking flow as a success page or as a booking detail page from the app // This is a weird case where the same route can be opened in booking flow as a success page or as a booking detail page from the app
@@ -592,23 +592,24 @@ export default function Success(props: SuccessProps) {
</span> </span>
<div className="justify-left mt-1 flex text-left sm:mt-0"> <div className="justify-left mt-1 flex text-left sm:mt-0">
<Link <Link
href={ href={`https://calendar.google.com/calendar/r/eventedit?dates=${date
`https://calendar.google.com/calendar/r/eventedit?dates=${date .utc()
.utc() .format("YYYYMMDDTHHmmss[Z]")}/${date
.format("YYYYMMDDTHHmmss[Z]")}/${date .add(calculatedDuration, "minute")
.add(calculatedDuration, "minute") .utc()
.utc() .format("YYYYMMDDTHHmmss[Z]")}&text=${eventName}&details=${
.format("YYYYMMDDTHHmmss[Z]")}&text=${eventName}&details=${ props.eventType.description
props.eventType.description }${
}` + typeof locationVideoCallUrl === "string"
(typeof locationVideoCallUrl === "string" ? `&location=${encodeURIComponent(locationVideoCallUrl)}`
? "&location=" + encodeURIComponent(locationVideoCallUrl) : ""
: "") + }${
(props.eventType.recurringEvent props.eventType.recurringEvent
? "&recur=" + ? `&recur=${encodeURIComponent(
encodeURIComponent(new RRule(props.eventType.recurringEvent).toString()) new RRule(props.eventType.recurringEvent).toString()
: "") )}`
} : ""
}`}
className="text-default border-subtle h-10 w-10 rounded-sm border px-3 py-2 ltr:mr-2 rtl:ml-2"> className="text-default border-subtle h-10 w-10 rounded-sm border px-3 py-2 ltr:mr-2 rtl:ml-2">
<svg <svg
className="-mt-1.5 inline-block h-4 w-4" className="-mt-1.5 inline-block h-4 w-4"
@@ -622,17 +623,17 @@ export default function Success(props: SuccessProps) {
<Link <Link
href={ href={
encodeURI( encodeURI(
"https://outlook.live.com/calendar/0/deeplink/compose?body=" + `https://outlook.live.com/calendar/0/deeplink/compose?body=${
props.eventType.description + props.eventType.description
"&enddt=" + }&enddt=${date
date.add(calculatedDuration, "minute").utc().format() + .add(calculatedDuration, "minute")
"&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=" + .utc()
date.utc().format() + .format()}&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=${date
"&subject=" + .utc()
eventName .format()}&subject=${eventName}`
) + ) +
(locationVideoCallUrl (locationVideoCallUrl
? "&location=" + encodeURIComponent(locationVideoCallUrl) ? `&location=${encodeURIComponent(locationVideoCallUrl)}`
: "") : "")
} }
className="border-subtle text-default mx-2 h-10 w-10 rounded-sm border px-3 py-2" className="border-subtle text-default mx-2 h-10 w-10 rounded-sm border px-3 py-2"
@@ -649,17 +650,17 @@ export default function Success(props: SuccessProps) {
<Link <Link
href={ href={
encodeURI( encodeURI(
"https://outlook.office.com/calendar/0/deeplink/compose?body=" + `https://outlook.office.com/calendar/0/deeplink/compose?body=${
props.eventType.description + props.eventType.description
"&enddt=" + }&enddt=${date
date.add(calculatedDuration, "minute").utc().format() + .add(calculatedDuration, "minute")
"&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=" + .utc()
date.utc().format() + .format()}&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=${date
"&subject=" + .utc()
eventName .format()}&subject=${eventName}`
) + ) +
(locationVideoCallUrl (locationVideoCallUrl
? "&location=" + encodeURIComponent(locationVideoCallUrl) ? `&location=${encodeURIComponent(locationVideoCallUrl)}`
: "") : "")
} }
className="text-default border-subtle mx-2 h-10 w-10 rounded-sm border px-3 py-2" className="text-default border-subtle mx-2 h-10 w-10 rounded-sm border px-3 py-2"
@@ -674,9 +675,9 @@ export default function Success(props: SuccessProps) {
</svg> </svg>
</Link> </Link>
<Link <Link
href={"data:text/calendar," + eventLink()} href={`data:text/calendar,${eventLink()}`}
className="border-subtle text-default mx-2 h-10 w-10 rounded-sm border px-3 py-2" className="border-subtle text-default mx-2 h-10 w-10 rounded-sm border px-3 py-2"
download={props.eventType.title + ".ics"}> download={`${props.eventType.title}.ics`}>
<svg <svg
version="1.1" version="1.1"
fill="currentColor" fill="currentColor"
+13 -13
View File
@@ -140,13 +140,13 @@ const Item = ({ type, group, readOnly }: { type: EventType; group: EventTypeGrou
<div> <div>
<span <span
className="text-default font-semibold ltr:mr-1 rtl:ml-1" className="text-default font-semibold ltr:mr-1 rtl:ml-1"
data-testid={"event-type-title-" + type.id}> data-testid={`event-type-title-${type.id}`}>
{type.title} {type.title}
</span> </span>
{group.profile.slug ? ( {group.profile.slug ? (
<small <small
className="text-subtle hidden font-normal leading-4 sm:inline" className="text-subtle hidden font-normal leading-4 sm:inline"
data-testid={"event-type-slug-" + type.id}> data-testid={`event-type-slug-${type.id}`}>
{`/${ {`/${
type.schedulingType !== SchedulingType.MANAGED ? group.profile.slug : t("username_placeholder") type.schedulingType !== SchedulingType.MANAGED ? group.profile.slug : t("username_placeholder")
}/${type.slug}`} }/${type.slug}`}
@@ -177,13 +177,13 @@ const Item = ({ type, group, readOnly }: { type: EventType; group: EventTypeGrou
<div> <div>
<span <span
className="text-default font-semibold ltr:mr-1 rtl:ml-1" className="text-default font-semibold ltr:mr-1 rtl:ml-1"
data-testid={"event-type-title-" + type.id}> data-testid={`event-type-title-${type.id}`}>
{type.title} {type.title}
</span> </span>
{group.profile.slug ? ( {group.profile.slug ? (
<small <small
className="text-subtle hidden font-normal leading-4 sm:inline" className="text-subtle hidden font-normal leading-4 sm:inline"
data-testid={"event-type-slug-" + type.id}> data-testid={`event-type-slug-${type.id}`}>
{`/${group.profile.slug}/${type.slug}`} {`/${group.profile.slug}/${type.slug}`}
</small> </small>
) : null} ) : null}
@@ -479,7 +479,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
</> </>
)} )}
<Dropdown modal={false}> <Dropdown modal={false}>
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}> <DropdownMenuTrigger asChild data-testid={`event-type-options-${type.id}`}>
<Button <Button
type="button" type="button"
variant="icon" variant="icon"
@@ -493,9 +493,9 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<DropdownMenuItem> <DropdownMenuItem>
<DropdownItem <DropdownItem
type="button" type="button"
data-testid={"event-type-edit-" + type.id} data-testid={`event-type-edit-${type.id}`}
StartIcon={Edit2} StartIcon={Edit2}
onClick={() => router.push("/event-types/" + type.id)}> onClick={() => router.push(`/event-types/${type.id}`)}>
{t("edit")} {t("edit")}
</DropdownItem> </DropdownItem>
</DropdownMenuItem> </DropdownMenuItem>
@@ -505,7 +505,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<DropdownMenuItem className="outline-none"> <DropdownMenuItem className="outline-none">
<DropdownItem <DropdownItem
type="button" type="button"
data-testid={"event-type-duplicate-" + type.id} data-testid={`event-type-duplicate-${type.id}`}
StartIcon={Copy} StartIcon={Copy}
onClick={() => openDuplicateModal(type, group)}> onClick={() => openDuplicateModal(type, group)}>
{t("duplicate")} {t("duplicate")}
@@ -555,7 +555,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
</div> </div>
<div className="min-w-9 mx-5 flex sm:hidden"> <div className="min-w-9 mx-5 flex sm:hidden">
<Dropdown> <Dropdown>
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}> <DropdownMenuTrigger asChild data-testid={`event-type-options-${type.id}`}>
<Button type="button" variant="icon" color="secondary" StartIcon={MoreHorizontal} /> <Button type="button" variant="icon" color="secondary" StartIcon={MoreHorizontal} />
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuPortal> <DropdownMenuPortal>
@@ -573,7 +573,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem className="outline-none"> <DropdownMenuItem className="outline-none">
<DropdownItem <DropdownItem
data-testid={"event-type-duplicate-" + type.id} data-testid={`event-type-duplicate-${type.id}`}
onClick={() => { onClick={() => {
navigator.clipboard.writeText(calLink); navigator.clipboard.writeText(calLink);
showToast(t("link_copied"), "success"); showToast(t("link_copied"), "success");
@@ -588,7 +588,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
{isNativeShare ? ( {isNativeShare ? (
<DropdownMenuItem className="outline-none"> <DropdownMenuItem className="outline-none">
<DropdownItem <DropdownItem
data-testid={"event-type-duplicate-" + type.id} data-testid={`event-type-duplicate-${type.id}`}
onClick={() => { onClick={() => {
navigator navigator
.share({ .share({
@@ -608,7 +608,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
{!readOnly && ( {!readOnly && (
<DropdownMenuItem className="outline-none"> <DropdownMenuItem className="outline-none">
<DropdownItem <DropdownItem
onClick={() => router.push("/event-types/" + type.id)} onClick={() => router.push(`/event-types/${type.id}`)}
StartIcon={Edit} StartIcon={Edit}
className="w-full rounded-none"> className="w-full rounded-none">
{t("edit")} {t("edit")}
@@ -620,7 +620,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<DropdownItem <DropdownItem
onClick={() => openDuplicateModal(type, group)} onClick={() => openDuplicateModal(type, group)}
StartIcon={Copy} StartIcon={Copy}
data-testid={"event-type-duplicate-" + type.id}> data-testid={`event-type-duplicate-${type.id}`}>
{t("duplicate")} {t("duplicate")}
</DropdownItem> </DropdownItem>
</DropdownMenuItem> </DropdownMenuItem>
+5 -6
View File
@@ -63,14 +63,13 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
const eventType = booking.eventType ? booking.eventType : getDefaultEvent(dynamicEventSlugRef); const eventType = booking.eventType ? booking.eventType : getDefaultEvent(dynamicEventSlugRef);
const eventPage = const eventPage = `${
(eventType.team eventType.team
? "team/" + eventType.team.slug ? `team/${eventType.team.slug}`
: dynamicEventSlugRef : dynamicEventSlugRef
? booking.dynamicGroupSlugRef ? booking.dynamicGroupSlugRef
: booking.user?.username || "rick") /* This shouldn't happen */ + : booking.user?.username || "rick" /* This shouldn't happen */
"/" + }/${eventType?.slug}`;
eventType?.slug;
const destinationUrl = new URLSearchParams(); const destinationUrl = new URLSearchParams();
destinationUrl.set("rescheduleUid", seatReferenceUid || bookingId); destinationUrl.set("rescheduleUid", seatReferenceUid || bookingId);
@@ -0,0 +1,11 @@
import PageWrapper from "@components/PageWrapper";
import { getLayout } from "@components/auth/layouts/AdminLayout";
import OAuthView from "./oAuthView";
const OAuthPage = () => <OAuthView />;
OAuthPage.getLayout = getLayout;
OAuthPage.PageWrapper = PageWrapper;
export default OAuthPage;
@@ -0,0 +1,151 @@
import { useState } from "react";
import { useForm } from "react-hook-form";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc";
import { Meta, Form, Button, TextField, showToast, Tooltip, ImageUploader, Avatar } from "@calcom/ui";
import { Clipboard } from "@calcom/ui/components/icon";
import { Plus } from "@calcom/ui/components/icon";
type FormValues = {
name: string;
redirectUri: string;
logo: string;
};
export default function OAuthView() {
const oAuthForm = useForm<FormValues>();
const [clientSecret, setClientSecret] = useState("");
const [clientId, setClientId] = useState("");
const [logo, setLogo] = useState("");
const { t } = useLocale();
const mutation = trpc.viewer.oAuth.addClient.useMutation({
onSuccess: async (data) => {
setClientSecret(data.clientSecret);
setClientId(data.clientId);
showToast(`Successfully added ${data.name} as new client`, "success");
},
onError: (error) => {
showToast(`Adding clientfailed: ${error.message}`, "error");
},
});
return (
<div>
<Meta title="OAuth" description="Add new OAuth Clients" />
{!clientId ? (
<Form
form={oAuthForm}
handleSubmit={(values) => {
mutation.mutate({
name: values.name,
redirectUri: values.redirectUri,
logo: values.logo,
});
}}>
<div className="">
<TextField
{...oAuthForm.register("name")}
label="Client name"
type="text"
id="name"
placeholder=""
className="mb-3"
required
/>
<TextField
{...oAuthForm.register("redirectUri")}
label="Redirect URI"
type="text"
id="redirectUri"
placeholder=""
required
/>
<div className="mb-5 mt-5 flex items-center">
<Avatar
alt=""
fallback={<Plus className="text-subtle h-6 w-6" />}
className="mr-5 items-center"
imageSrc={logo}
size="lg"
/>
<ImageUploader
target="avatar"
id="avatar-upload"
buttonMsg="Upload Logo"
handleAvatarChange={(newLogo: string) => {
setLogo(newLogo);
oAuthForm.setValue("logo", newLogo);
}}
imageSrc={logo}
/>
</div>
</div>
<Button type="submit" className="mt-3">
{t("add_client")}
</Button>
</Form>
) : (
<div>
<div className="text-emphasis mb-5 text-xl font-semibold">{oAuthForm.getValues("name")}</div>
<div className="mb-2 font-medium">Client Id</div>
<div className="flex">
<code className="bg-subtle text-default w-full truncate rounded-md rounded-r-none py-[6px] pl-2 pr-2 align-middle font-mono">
{" "}
{clientId}
</code>
<Tooltip side="top" content="Copy to Clipboard">
<Button
onClick={() => {
navigator.clipboard.writeText(clientId);
showToast("Client ID copied!", "success");
}}
type="button"
className="rounded-l-none text-base"
StartIcon={Clipboard}>
{t("copy")}
</Button>
</Tooltip>
</div>
{clientSecret ? (
<>
<div className="mb-2 mt-4 font-medium">Client Secret</div>
<div className="flex">
<code className="bg-subtle text-default w-full truncate rounded-md rounded-r-none py-[6px] pl-2 pr-2 align-middle font-mono">
{" "}
{clientSecret}
</code>
<Tooltip side="top" content="Copy to Clipboard">
<Button
onClick={() => {
navigator.clipboard.writeText(clientSecret);
setClientSecret("");
showToast("Client secret copied!", "success");
}}
type="button"
className="rounded-l-none text-base"
StartIcon={Clipboard}>
{t("copy")}
</Button>
</Tooltip>
</div>
<div className="text-subtle text-sm">{t("copy_client_secret_info")}</div>
</>
) : (
<></>
)}
<Button
onClick={() => {
setClientId("");
setLogo("");
oAuthForm.reset();
}}
className="mt-5">
{t("add_new_client")}
</Button>
</div>
)}
</div>
);
}
@@ -190,7 +190,7 @@ const CalendarsView = () => {
} }
<div className="flex-grow truncate pl-2"> <div className="flex-grow truncate pl-2">
<ListItemTitle component="h3" className="mb-1 space-x-2 rtl:space-x-reverse"> <ListItemTitle component="h3" className="mb-1 space-x-2 rtl:space-x-reverse">
<Link href={"/apps/" + item.integration.slug}> <Link href={`/apps/${item.integration.slug}`}>
{item.integration.name || item.integration.title} {item.integration.name || item.integration.title}
</Link> </Link>
{data?.destinationCalendar?.credentialId === item.credentialId && ( {data?.destinationCalendar?.credentialId === item.credentialId && (
+13 -6
View File
@@ -86,13 +86,20 @@ const ProfileView = () => {
const utils = trpc.useContext(); const utils = trpc.useContext();
const { update } = useSession(); const { update } = useSession();
const [fetchedImgSrc, setFetchedImgSrc] = useState<string | undefined>(); const [fetchedImgSrc, setFetchedImgSrc] = useState<string | undefined>(undefined);
const { data: user, isLoading } = trpc.viewer.me.useQuery(undefined, { const { data: user, isLoading } = trpc.viewer.me.useQuery(undefined, {
onSuccess: (userData) => { onSuccess: async (userData) => {
fetch(userData.avatar).then((res) => { try {
if (res.url) setFetchedImgSrc(res.url); if (!userData.organization) {
}); const res = await fetch(userData.avatar);
if (res.url) setFetchedImgSrc(res.url);
} else {
setFetchedImgSrc("");
}
} catch (err) {
setFetchedImgSrc("");
}
}, },
}); });
const updateProfileMutation = trpc.viewer.updateProfile.useMutation({ const updateProfileMutation = trpc.viewer.updateProfile.useMutation({
@@ -218,7 +225,7 @@ const ProfileView = () => {
[ErrorCode.ThirdPartyIdentityProviderEnabled]: t("account_created_with_identity_provider"), [ErrorCode.ThirdPartyIdentityProviderEnabled]: t("account_created_with_identity_provider"),
}; };
if (isLoading || !user || !fetchedImgSrc) if (isLoading || !user || fetchedImgSrc === undefined)
return ( return (
<SkeletonLoader title={t("profile")} description={t("profile_description", { appName: APP_NAME })} /> <SkeletonLoader title={t("profile")} description={t("profile_description", { appName: APP_NAME })} />
); );
+1 -1
View File
@@ -281,7 +281,7 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
return { return {
redirect: { redirect: {
permanent: false, permanent: false,
destination: "/auth/login?callbackUrl=" + `${WEBAPP_URL}/${ctx.query.callbackUrl}`, destination: `/auth/login?callbackUrl=${WEBAPP_URL}/${ctx.query.callbackUrl}`,
}, },
}; };
} }
+3 -3
View File
@@ -102,7 +102,7 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain }
items={type.users.map((user) => ({ items={type.users.map((user) => ({
alt: user.name || "", alt: user.name || "",
title: user.name || "", title: user.name || "",
image: "/" + user.username + "/avatar.png" || "", image: `/${user.username}/avatar.png` || "",
}))} }))}
/> />
</div> </div>
@@ -160,7 +160,7 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain }
<div className="space-y-6" data-testid="event-types"> <div className="space-y-6" data-testid="event-types">
<div className="overflow-hidden rounded-sm border dark:border-gray-900"> <div className="overflow-hidden rounded-sm border dark:border-gray-900">
<div className="text-muted p-8 text-center"> <div className="text-muted p-8 text-center">
<h2 className="font-cal text-emphasis mb-2 text-3xl">{" " + t("org_no_teams_yet")}</h2> <h2 className="font-cal text-emphasis mb-2 text-3xl">{` ${t("org_no_teams_yet")}`}</h2>
<p className="text-emphasis mx-auto max-w-md">{t("org_no_teams_yet_description")}</p> <p className="text-emphasis mx-auto max-w-md">{t("org_no_teams_yet_description")}</p>
</div> </div>
</div> </div>
@@ -324,7 +324,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
...type, ...type,
users: type.users.map((user) => ({ users: type.users.map((user) => ({
...user, ...user,
avatar: "/" + user.username + "/avatar.png", avatar: `/${user.username}/avatar.png`,
})), })),
descriptionAsSafeHTML: markdownToSafeHTML(type.description), descriptionAsSafeHTML: markdownToSafeHTML(type.description),
})) ?? null; })) ?? null;
+2 -2
View File
@@ -95,12 +95,12 @@ export default function JoinCall(props: JoinCallPageProps) {
<meta property="og:image" content={SEO_IMG_OGIMG_VIDEO} /> <meta property="og:image" content={SEO_IMG_OGIMG_VIDEO} />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content={`${WEBSITE_URL}/video`} /> <meta property="og:url" content={`${WEBSITE_URL}/video`} />
<meta property="og:title" content={APP_NAME + " Video"} /> <meta property="og:title" content={`${APP_NAME} Video`} />
<meta property="og:description" content={t("quick_video_meeting")} /> <meta property="og:description" content={t("quick_video_meeting")} />
<meta property="twitter:image" content={SEO_IMG_OGIMG_VIDEO} /> <meta property="twitter:image" content={SEO_IMG_OGIMG_VIDEO} />
<meta property="twitter:card" content="summary_large_image" /> <meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={`${WEBSITE_URL}/video`} /> <meta property="twitter:url" content={`${WEBSITE_URL}/video`} />
<meta property="twitter:title" content={APP_NAME + " Video"} /> <meta property="twitter:title" content={`${APP_NAME} Video`} />
<meta property="twitter:description" content={t("quick_video_meeting")} /> <meta property="twitter:description" content={t("quick_video_meeting")} />
</Head> </Head>
<div style={{ zIndex: 2, position: "relative" }}> <div style={{ zIndex: 2, position: "relative" }}>
+1 -1
View File
@@ -44,7 +44,7 @@ export default function MeetingUnavailable(props: inferSSRProps<typeof getServer
</h2> </h2>
<p className="text-subtle text-center"> <p className="text-subtle text-center">
<Calendar className="-mt-1 mr-1 inline-block h-4 w-4" /> <Calendar className="-mt-1 mr-1 inline-block h-4 w-4" />
{dayjs(props.booking.startTime).format(detectBrowserTimeFormat + ", dddd DD MMMM YYYY")} {dayjs(props.booking.startTime).format(`${detectBrowserTimeFormat}, dddd DD MMMM YYYY`)}
</p> </p>
</div> </div>
</div> </div>
@@ -24,7 +24,7 @@ export default function MeetingNotStarted(props: inferSSRProps<typeof getServerS
<h2 className="mb-2 text-center font-medium">{props.booking.title}</h2> <h2 className="mb-2 text-center font-medium">{props.booking.title}</h2>
<p className="text-subtle text-center"> <p className="text-subtle text-center">
<Calendar className="-mt-1 mr-1 inline-block h-4 w-4" /> <Calendar className="-mt-1 mr-1 inline-block h-4 w-4" />
{dayjs(props.booking.startTime).format(detectBrowserTimeFormat + ", dddd DD MMMM YYYY")} {dayjs(props.booking.startTime).format(`${detectBrowserTimeFormat}, dddd DD MMMM YYYY`)}
</p> </p>
</> </>
} }
+1 -1
View File
@@ -23,7 +23,7 @@ const otherNonExistingRoutePrefixes = ["forms", "router", "success", "cancel"];
// book$ ensures that only /book is excluded from rewrite(which is at the end always) and not /booked // book$ ensures that only /book is excluded from rewrite(which is at the end always) and not /booked
let subdomainRegExp = (exports.subdomainRegExp = getSubdomainRegExp( let subdomainRegExp = (exports.subdomainRegExp = getSubdomainRegExp(
process.env.NEXT_PUBLIC_WEBAPP_URL || "https://" + process.env.VERCEL_URL process.env.NEXT_PUBLIC_WEBAPP_URL || `https://${process.env.VERCEL_URL}`
)); ));
exports.orgHostPath = `^(?<orgSlug>${subdomainRegExp})\\.(?!vercel\.app).*`; exports.orgHostPath = `^(?<orgSlug>${subdomainRegExp})\\.(?!vercel\.app).*`;
+1 -1
View File
@@ -28,7 +28,7 @@ export const createPaymentsFixture = (page: Page) => {
}, },
}, },
data: {}, data: {},
externalId: "DEMO_PAYMENT_FROM_DB_" + Date.now(), externalId: `DEMO_PAYMENT_FROM_DB_${Date.now()}`,
booking: { booking: {
connect: { connect: {
id: bookingId, id: bookingId,
-2
View File
@@ -556,8 +556,6 @@ export async function apiLogin(
export async function setupEventWithPrice(eventType: Pick<Prisma.EventType, "id">, page: Page) { export async function setupEventWithPrice(eventType: Pick<Prisma.EventType, "id">, page: Page) {
await page.goto(`/event-types/${eventType?.id}?tabName=apps`); await page.goto(`/event-types/${eventType?.id}?tabName=apps`);
await page.locator("div > .ml-auto").first().click(); await page.locator("div > .ml-auto").first().click();
await page.locator(".text-black > .bg-default > div > div:nth-child(2)").first().click();
await page.getByTestId("select-option-usd").click();
await page.getByPlaceholder("Price").fill("100"); await page.getByPlaceholder("Price").fill("100");
await page.getByTestId("update-eventtype").click(); await page.getByTestId("update-eventtype").click();
} }
+239
View File
@@ -0,0 +1,239 @@
import { expect } from "@playwright/test";
import { randomString } from "@calcom/lib/random";
import prisma from "@calcom/prisma";
import { test } from "./lib/fixtures";
test.describe.configure({ mode: "parallel" });
const createTeamsAndMembership = async (userIdOne: number, userIdTwo: number) => {
const teamOne = await prisma.team.create({
data: {
name: "test-insights",
slug: `test-insights-${Date.now()}-${randomString(5)}}`,
},
});
const teamTwo = await prisma.team.create({
data: {
name: "test-insights-2",
slug: `test-insights-2-${Date.now()}-${randomString(5)}}`,
},
});
if (!userIdOne || !userIdTwo || !teamOne || !teamTwo) {
throw new Error("Failed to create test data");
}
// create memberships
await prisma.membership.create({
data: {
userId: userIdOne,
teamId: teamOne.id,
accepted: true,
role: "ADMIN",
},
});
await prisma.membership.create({
data: {
teamId: teamTwo.id,
userId: userIdOne,
accepted: true,
role: "ADMIN",
},
});
await prisma.membership.create({
data: {
teamId: teamOne.id,
userId: userIdTwo,
accepted: true,
role: "MEMBER",
},
});
await prisma.membership.create({
data: {
teamId: teamTwo.id,
userId: userIdTwo,
accepted: true,
role: "MEMBER",
},
});
return { teamOne, teamTwo };
};
test.afterAll(async ({ users }) => {
await users.deleteAll();
});
test.describe("Insights", async () => {
test("should be able to go to insights as admins", async ({ page, users }) => {
const user = await users.create();
const userTwo = await users.create();
await createTeamsAndMembership(user.id, userTwo.id);
await user.apiLogin();
// go to insights page
await page.goto("/insights");
await page.waitForLoadState("networkidle");
// expect url to have isAll and TeamId in query params
expect(page.url()).toContain("isAll=false");
expect(page.url()).toContain("teamId=");
});
test("should be able to go to insights as members", async ({ page, users }) => {
const user = await users.create();
const userTwo = await users.create();
await userTwo.apiLogin();
await createTeamsAndMembership(user.id, userTwo.id);
// go to insights page
await page.goto("/insights");
await page.waitForLoadState("networkidle");
// expect url to have isAll and TeamId in query params
expect(page.url()).toContain("isAll=false");
expect(page.url()).not.toContain("teamId=");
});
test("team select filter should have 2 teams and your account option only as member", async ({
page,
users,
}) => {
const user = await users.create();
const userTwo = await users.create();
await user.apiLogin();
await createTeamsAndMembership(user.id, userTwo.id);
// go to insights page
await page.goto("/insights");
await page.waitForLoadState("networkidle");
// get div from team select filter with this class flex flex-col gap-0.5 [&>*:first-child]:mt-1 [&>*:last-child]:mb-1
await page.getByTestId("dashboard-shell").getByText("Team: test-insights").click();
await page
.locator('div[class="flex flex-col gap-0.5 [&>*:first-child]:mt-1 [&>*:last-child]:mb-1"]')
.click();
const teamSelectFilter = await page.locator(
'div[class="hover:bg-muted flex items-center py-2 pl-3 pr-2.5 hover:cursor-pointer"]'
);
await expect(teamSelectFilter).toHaveCount(3);
});
test("Insights Organization should have isAll option true", async ({ users, page }) => {
const owner = await users.create(undefined, {
hasTeam: true,
isUnpublished: true,
isOrg: true,
hasSubteam: true,
});
await owner.apiLogin();
await page.goto("/insights");
await page.waitForLoadState("networkidle");
await page.getByTestId("dashboard-shell").getByText("All").nth(1).click();
const teamSelectFilter = await page.locator(
'div[class="hover:bg-muted flex items-center py-2 pl-3 pr-2.5 hover:cursor-pointer"]'
);
await expect(teamSelectFilter).toHaveCount(4);
});
test("should have all option in team-and-self filter as admin", async ({ page, users }) => {
const owner = await users.create();
const member = await users.create();
await createTeamsAndMembership(owner.id, member.id);
await owner.apiLogin();
await page.goto("/insights");
// get div from team select filter with this class flex flex-col gap-0.5 [&>*:first-child]:mt-1 [&>*:last-child]:mb-1
await page.getByTestId("dashboard-shell").getByText("Team: test-insights").click();
await page
.locator('div[class="flex flex-col gap-0.5 [&>*:first-child]:mt-1 [&>*:last-child]:mb-1"]')
.click();
const teamSelectFilter = await page.locator(
'div[class="hover:bg-muted flex items-center py-2 pl-3 pr-2.5 hover:cursor-pointer"]'
);
await expect(teamSelectFilter).toHaveCount(3);
});
test("should be able to switch between teams and self profile for insights", async ({ page, users }) => {
const owner = await users.create();
const member = await users.create();
await createTeamsAndMembership(owner.id, member.id);
await owner.apiLogin();
await page.goto("/insights");
// get div from team select filter with this class flex flex-col gap-0.5 [&>*:first-child]:mt-1 [&>*:last-child]:mb-1
await page.getByTestId("dashboard-shell").getByText("Team: test-insights").click();
await page
.locator('div[class="flex flex-col gap-0.5 [&>*:first-child]:mt-1 [&>*:last-child]:mb-1"]')
.click();
const teamSelectFilter = await page.locator(
'div[class="hover:bg-muted flex items-center py-2 pl-3 pr-2.5 hover:cursor-pointer"]'
);
await expect(teamSelectFilter).toHaveCount(3);
// switch to self profile
await page.getByTestId("dashboard-shell").getByText("Your Account").click();
// switch to team 1
await page.getByTestId("dashboard-shell").getByText("test-insights").nth(0).click();
// switch to team 2
await page.getByTestId("dashboard-shell").getByText("test-insights-2").click();
});
test("should be able to switch between memberUsers", async ({ page, users }) => {
const owner = await users.create();
const member = await users.create();
await createTeamsAndMembership(owner.id, member.id);
await owner.apiLogin();
await page.goto("/insights");
await page.getByText("Add filter").click();
await page.getByRole("button", { name: "User" }).click();
// <div class="flex select-none truncate font-medium" data-state="closed">People</div>
await page.locator('div[class="flex select-none truncate font-medium"]').getByText("People").click();
await page
.locator('div[class="hover:bg-muted flex items-center py-2 pl-3 pr-2.5 hover:cursor-pointer"]')
.nth(0)
.click();
await page.waitForLoadState("networkidle");
await page
.locator('div[class="hover:bg-muted flex items-center py-2 pl-3 pr-2.5 hover:cursor-pointer"]')
.nth(1)
.click();
await page.waitForLoadState("networkidle");
// press escape button to close the filter
await page.keyboard.press("Escape");
await page.getByRole("button", { name: "Clear" }).click();
// expect for "Team: test-insight" text in page
expect(await page.locator("text=Team: test-insights").isVisible()).toBeTruthy();
});
});
+2 -2
View File
@@ -23,7 +23,7 @@ export const nextServer = async ({ port = 3000 } = { port: 3000 }) => {
process.env.PLAYWRIGHT_TEST_BASE_URL = process.env.PLAYWRIGHT_TEST_BASE_URL =
process.env.NEXT_PUBLIC_WEBAPP_URL = process.env.NEXT_PUBLIC_WEBAPP_URL =
process.env.NEXT_PUBLIC_WEBSITE_URL = process.env.NEXT_PUBLIC_WEBSITE_URL =
"http://localhost:" + port; `http://localhost:${port}`;
const app = next({ const app = next({
dev: dev, dev: dev,
port, port,
@@ -46,7 +46,7 @@ export const nextServer = async ({ port = 3000 } = { port: 3000 }) => {
resolve(server); resolve(server);
}); });
server.on("error", (error) => { server.on("error", (error) => {
if (error) throw new Error("Could not start Next.js server -" + error.message); if (error) throw new Error(`Could not start Next.js server - ${error.message}`);
}); });
}); });
return server; return server;
+227
View File
@@ -0,0 +1,227 @@
import { expect } from "@playwright/test";
import { randomBytes } from "crypto";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { generateSecret } from "@calcom/trpc/server/routers/viewer/oAuth/addClient.handler";
import { test } from "./lib/fixtures";
test.afterEach(async ({ users }) => {
await users.deleteAll();
});
let client: {
clientId: string;
redirectUri: string;
orginalSecret: string;
name: string;
clientSecret: string;
logo: string | null;
};
test.describe("OAuth Provider", () => {
test.beforeAll(async () => {
client = await createTestCLient();
});
test("should create valid access toke & refresh token for user", async ({ page, users }) => {
const user = await users.create({ username: "test user", name: "test user" });
await user.apiLogin();
await page.goto(
`auth/oauth2/authorize?client_id=${client.clientId}&redirect_uri=${client.redirectUri}&response_type=code&scope=READ_PROFILE&state=1234`
);
await page.waitForLoadState("networkidle");
await page.getByTestId("allow-button").click();
await page.waitForFunction(() => {
return window.location.href.startsWith("https://example.com");
});
const url = new URL(page.url());
// authorization code that is returned to client with redirect uri
const code = url.searchParams.get("code");
// request token with authorization code
const tokenResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/token`, {
body: JSON.stringify({
code,
client_id: client.clientId,
client_secret: client.orginalSecret,
grant_type: "authorization_code",
redirect_uri: client.redirectUri,
}),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const tokenData = await tokenResponse.json();
// test if token is valid
const meResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/me`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${tokenData.access_token}`,
},
});
const meData = await meResponse.json();
// check if user access token is valid
expect(meData.username.startsWith("test user")).toBe(true);
// request new token with refresh token
const refreshTokenResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/refreshToken`, {
body: JSON.stringify({
refresh_token: tokenData.refresh_token,
client_id: client.clientId,
client_secret: client.orginalSecret,
grant_type: "refresh_token",
}),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const refreshTokenData = await refreshTokenResponse.json();
expect(refreshTokenData.access_token).not.toBe(tokenData.access_token);
const validTokenResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/me`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${tokenData.access_token}`,
},
});
expect(meData.username.startsWith("test user")).toBe(true);
});
test("should create valid access toke & refresh token for team", async ({ page, users }) => {
const user = await users.create({ username: "test user", name: "test user" }, { hasTeam: true });
await user.apiLogin();
await page.goto(
`auth/oauth2/authorize?client_id=${client.clientId}&redirect_uri=${client.redirectUri}&response_type=code&scope=READ_PROFILE&state=1234`
);
await page.waitForLoadState("networkidle");
await page.locator("#account-select").click();
await page.locator("#react-select-2-option-1").click();
await page.getByTestId("allow-button").click();
await page.waitForFunction(() => {
return window.location.href.startsWith("https://example.com");
});
const url = new URL(page.url());
// authorization code that is returned to client with redirect uri
const code = url.searchParams.get("code");
// request token with authorization code
const tokenResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/token`, {
body: JSON.stringify({
code,
client_id: client.clientId,
client_secret: client.orginalSecret,
grant_type: "authorization_code",
redirect_uri: client.redirectUri,
}),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const tokenData = await tokenResponse.json();
// test if token is valid
const meResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/me`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${tokenData.access_token}`,
},
});
const meData = await meResponse.json();
// check if team access token is valid
expect(meData.username.endsWith("Team Team")).toBe(true);
// request new token with refresh token
const refreshTokenResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/refreshToken`, {
body: JSON.stringify({
refresh_token: tokenData.refresh_token,
client_id: client.clientId,
client_secret: client.orginalSecret,
grant_type: "refresh_token",
}),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const refreshTokenData = await refreshTokenResponse.json();
expect(refreshTokenData.access_token).not.toBe(tokenData.access_token);
const validTokenResponse = await fetch(`${WEBAPP_URL}/api/auth/oauth/me`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${tokenData.access_token}`,
},
});
expect(meData.username.endsWith("Team Team")).toBe(true);
});
test("redirect not logged-in users to login page and after forward to authorization page", async ({
page,
users,
}) => {
const user = await users.create({ username: "test-user", name: "test user" });
await page.goto(
`auth/oauth2/authorize?client_id=${client.clientId}&redirect_uri=${client.redirectUri}&response_type=code&scope=READ_PROFILE&state=1234`
);
// check if user is redirected to login page
await expect(page.getByRole("heading", { name: "Welcome back" })).toBeVisible();
await page.locator("#email").fill(user.email);
await page.locator("#password").fill(user.username || "");
await page.locator('[type="submit"]').click();
await page.waitForSelector("#account-select");
await expect(page.getByText("test user")).toBeVisible();
});
});
const createTestCLient = async () => {
const [hashedSecret, secret] = generateSecret();
const clientId = randomBytes(32).toString("hex");
const client = await prisma.oAuthClient.create({
data: {
name: "Test Client",
clientId,
clientSecret: hashedSecret,
redirectUri: "https://example.com",
},
});
return { ...client, orginalSecret: secret };
};
+34
View File
@@ -200,4 +200,38 @@ test.describe("Payment app", () => {
// Expect "Getting started with Paypal APP" to be displayed // Expect "Getting started with Paypal APP" to be displayed
expect(await page.locator("text=Getting started with Paypal APP").first()).toBeTruthy(); expect(await page.locator("text=Getting started with Paypal APP").first()).toBeTruthy();
}); });
/**
* For now almost all the payment apps show display "This app has not been setup yet"
* this can change in the future
*/
test("Should not display App is not setup already for non payment app", async ({ page, users }) => {
// We will use google analytics app for this test
const user = await users.create();
await user.apiLogin();
// Any event should work here
const paymentEvent = user.eventTypes.find((item) => item.slug === "paid");
if (!paymentEvent) {
throw new Error("No payment event found");
}
await prisma.credential.create({
data: {
type: "ga4_analytics",
userId: user.id,
appId: "ga4",
invalid: false,
key: {},
},
});
await page.goto(`event-types/${paymentEvent.id}?tabName=apps`);
await page.locator("#event-type-form").getByRole("switch").click();
// make sure Tracking ID is displayed
expect(await page.locator("text=Tracking ID").first()).toBeTruthy();
await page.getByLabel("Tracking ID").click();
await page.getByLabel("Tracking ID").fill("demo");
await page.getByTestId("update-eventtype").click();
});
}); });
+24
View File
@@ -0,0 +1,24 @@
import { expect } from "@playwright/test";
import { test } from "./lib/fixtures";
test.describe.configure({ mode: "parallel" });
test.afterEach(({ users }) => users.deleteAll());
test.describe("Teams", () => {
test("Profile page is loaded for users in Organization", async ({ page, users }) => {
const teamMatesObj = [{ name: "teammate-1" }, { name: "teammate-2" }];
const owner = await users.create(undefined, {
hasTeam: true,
isOrg: true,
hasSubteam: true,
teammates: teamMatesObj,
});
await owner.apiLogin();
await page.goto("/settings/my-account/profile");
// check if user avatar is loaded
await expect(page.locator('[data-testid="organization-avatar"]')).toBeVisible();
});
});
@@ -423,6 +423,7 @@
"booking_created": "Booking Created", "booking_created": "Booking Created",
"booking_rejected": "Booking Rejected", "booking_rejected": "Booking Rejected",
"booking_requested": "Booking Requested", "booking_requested": "Booking Requested",
"booking_payment_initiated": "Booking Payment Initiated",
"meeting_ended": "Meeting Ended", "meeting_ended": "Meeting Ended",
"form_submitted": "Form Submitted", "form_submitted": "Form Submitted",
"booking_paid": "Booking Paid", "booking_paid": "Booking Paid",
@@ -2054,15 +2055,33 @@
"team_no_event_types": "This team has no event types", "team_no_event_types": "This team has no event types",
"seat_options_doesnt_multiple_durations": "Seat option doesn't support multiple durations", "seat_options_doesnt_multiple_durations": "Seat option doesn't support multiple durations",
"include_calendar_event": "Include calendar event", "include_calendar_event": "Include calendar event",
"oAuth": "OAuth",
"recently_added":"Recently added", "recently_added":"Recently added",
"no_members_found": "No members found", "no_members_found": "No members found",
"event_setup_length_error":"Event Setup: The duration must be at least 1 minute.", "event_setup_length_error":"Event Setup: The duration must be at least 1 minute.",
"availability_schedules":"Availability Schedules", "availability_schedules":"Availability Schedules",
"unauthorized":"Unauthorized",
"access_cal_account": "{{clientName}} would like access to your {{appName}} account",
"select_account_team": "Select account or team",
"allow_client_to": "This will allow {{clientName}} to",
"associate_with_cal_account":"Associate you with your personal info from {{clientName}}",
"see_personal_info":"See your personal info, including any personal info you've made publicly available",
"see_primary_email_address":"See your primary email address",
"connect_installed_apps":"Connect to your installed apps",
"access_event_type": "Read, edit, delete your event-types",
"access_availability": "Read, edit, delete your availability",
"access_bookings": "Read, edit, delete your bookings",
"allow_client_to_do": "Allow {{clientName}} to do this?",
"oauth_access_information": "By clicking allow, you allow this app to use your information in accordance with their terms of service and privacy policy. You can remove access in the {{appName}} App Store.",
"allow": "Allow",
"view_only_edit_availability_not_onboarded":"This user has not completed onboarding. You will not be able to set their availability until they have completed onboarding.", "view_only_edit_availability_not_onboarded":"This user has not completed onboarding. You will not be able to set their availability until they have completed onboarding.",
"view_only_edit_availability":"You are viewing this user's availability. You can only edit your own availability.", "view_only_edit_availability":"You are viewing this user's availability. You can only edit your own availability.",
"edit_users_availability":"Edit user's availability: {{username}}", "edit_users_availability":"Edit user's availability: {{username}}",
"resend_invitation": "Resend invitation", "resend_invitation": "Resend invitation",
"invitation_resent": "The invitation was resent.", "invitation_resent": "The invitation was resent.",
"add_client": "Add client",
"copy_client_secret_info": "After copying the secret you won't be able to view it anymore",
"add_new_client": "Add new Client",
"this_app_is_not_setup_already": "This app has not been setup yet", "this_app_is_not_setup_already": "This app has not been setup yet",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
} }
@@ -7,17 +7,32 @@
"second_other": "{{count}} segundo", "second_other": "{{count}} segundo",
"upgrade_now": "Eguneratu orain", "upgrade_now": "Eguneratu orain",
"accept_invitation": "Onartu gonbidapena", "accept_invitation": "Onartu gonbidapena",
"calcom_explained": "{{appName}}-ek bilerak programatzeko azpiegitura eskaintzen du guztiontzat.",
"calcom_explained_new_user": "Bukatu zure {{appName}} kontua konfiguratzen! Bileren programazio-arazo guztiak konpontzeko urrats gutxi batzuk besterik ez zaizkizu geratzen.",
"have_any_questions": "Galderarik? Laguntzeko gaude.", "have_any_questions": "Galderarik? Laguntzeko gaude.",
"reset_password_subject": "{{appName}}: Pasahitza berrezartzeko argibideak", "reset_password_subject": "{{appName}}: Pasahitza berrezartzeko argibideak",
"verify_email_subject": "{{appName}}: egiaztatu zure kontua", "verify_email_subject": "{{appName}}: egiaztatu zure kontua",
"check_your_email": "Begiratu zure emaila", "check_your_email": "Begiratu zure emaila",
"verify_email_page_body": "Email bat bidali dugu {{email}} helbidera. Garrantzitsua da zure email helbidea egiaztatzea, {{appName}}-tik mezuak eta egutegiko eguneratzeak ahalik eta hobekien jasoko dituzula bermatzeko.",
"verify_email_banner_body": "Egiaztatu zure email helbidea mezuak eta egutegiko eguneratzeak ahalik eta hobekien jasoko dituzula bermatzeko",
"verify_email_email_header": "Egiaztatu zure email helbidea", "verify_email_email_header": "Egiaztatu zure email helbidea",
"verify_email_email_button": "Egiaztatu emaila", "verify_email_email_button": "Egiaztatu emaila",
"verify_email_email_body": "Mesedez, egiaztatu zure email helbidea beheko botoia sakatuz.",
"verify_email_by_code_email_body": "Mesedez, egiaztatu zure email helbidea beheko kodea erabiliz.",
"verify_email_email_link_text": "Hemen duzu esteka, botoiak sakatzea gustuko ez baduzu:",
"email_verification_code": "Sartu egiaztatze-kodea",
"email_verification_code_placeholder": "Sartu zure email helbidera bidalitako egiaztatze-kodea",
"incorrect_email_verification_code": "Egiaztatze-kodea ez da zuzena.",
"email_sent": "Email mezua zuzen bidali da",
"email_not_sent": "Errore bat gertatu da email mezua bidaltzerakoan",
"event_declined_subject": "Baztertua: {{title}} {{date}}(e)an", "event_declined_subject": "Baztertua: {{title}} {{date}}(e)an",
"event_cancelled_subject": "Bertan behera: {{title}} {{date}}(e)an",
"event_request_declined": "Zure gertaera-eskaera baztertua izan da", "event_request_declined": "Zure gertaera-eskaera baztertua izan da",
"event_request_declined_recurring": "Zure gertaera errepikari-eskaera baztertua izan da", "event_request_declined_recurring": "Zure gertaera errepikari-eskaera baztertua izan da",
"event_request_cancelled": "Zure programatutako gertaera bertan behera utzi da",
"organizer": "Antolatzailea", "organizer": "Antolatzailea",
"need_to_reschedule_or_cancel": "Programazioa aldatu edo bertan behera utzi behar duzu?", "need_to_reschedule_or_cancel": "Programazioa aldatu edo bertan behera utzi behar duzu?",
"no_options_available": "Ez dago aukerarik eskuragarri",
"cancellation_reason": "Bertan behera uztearen arrazoia (aukerakoa)", "cancellation_reason": "Bertan behera uztearen arrazoia (aukerakoa)",
"cancellation_reason_placeholder": "Zergatik utzi duzu bertan behera?", "cancellation_reason_placeholder": "Zergatik utzi duzu bertan behera?",
"rejection_reason": "Errefusatzeko arrazoia", "rejection_reason": "Errefusatzeko arrazoia",
@@ -25,7 +40,11 @@
"rejection_reason_description": "Ziur zaude erreserba errefusatu nahi duzula? Erreserba-eskaera egin duen pertsonari jakinaraziko zaio. Arrazoi bat adieraz dezakezu behean.", "rejection_reason_description": "Ziur zaude erreserba errefusatu nahi duzula? Erreserba-eskaera egin duen pertsonari jakinaraziko zaio. Arrazoi bat adieraz dezakezu behean.",
"rejection_confirmation": "Errefusatu erreserba", "rejection_confirmation": "Errefusatu erreserba",
"manage_this_event": "Kudeatu gertaera hau", "manage_this_event": "Kudeatu gertaera hau",
"invite_team_member": "Gonbidatu taldekidea",
"invite_team_individual_segment": "Gonbidatu norbanakoa",
"invite_team_notifcation_badge": "Gon.",
"your_event_has_been_scheduled": "Zure gertaera programatu da", "your_event_has_been_scheduled": "Zure gertaera programatu da",
"your_event_has_been_scheduled_recurring": "Zure gertaera errepikaria programatu da",
"error_message": "Errore-mezua honakoa ian da: '{{errorMessage}}'", "error_message": "Errore-mezua honakoa ian da: '{{errorMessage}}'",
"refund_failed_subject": "Itzulketak huts egin du: {{name}} - {{date}} - {{eventType}}", "refund_failed_subject": "Itzulketak huts egin du: {{name}} - {{date}} - {{eventType}}",
"refund_failed": "Huts egin du itzulketak {{eventType}} gertaerarako, {{userName}}(r)ekin {{date}}(e)an.", "refund_failed": "Huts egin du itzulketak {{eventType}} gertaerarako, {{userName}}(r)ekin {{date}}(e)an.",
@@ -37,26 +56,79 @@
"refunded": "Itzulita", "refunded": "Itzulita",
"payment": "Ordainketa", "payment": "Ordainketa",
"pay_now": "Ordaindu orain", "pay_now": "Ordaindu orain",
"still_waiting_for_approval": "Gertaera bat onarpenaren zain dago",
"event_is_still_waiting": "Gertaera-eskaera oraindik zain dago: {{attendeeName}} - {{date}} - {{eventType}}",
"no_more_results": "Emaitza gehiagorik ez", "no_more_results": "Emaitza gehiagorik ez",
"no_results": "Emaitzarik ez", "no_results": "Emaitzarik ez",
"load_more_results": "Kargatu emaitza gehiago", "load_more_results": "Kargatu emaitza gehiago",
"integration_meeting_id": "{{integrationName}} bileraren IDa: {{meetingId}}",
"confirmed_event_type_subject": "Baieztatua: {{eventType}} {{name}}(r)ekin {{date}}(e)an", "confirmed_event_type_subject": "Baieztatua: {{eventType}} {{name}}(r)ekin {{date}}(e)an",
"new_event_request": "Gertaera berriaren eskaera: {{attendeeName}} - {{date}} - {{eventType}}",
"confirm_or_reject_request": "Baieztatu edo errefusatu eskaera", "confirm_or_reject_request": "Baieztatu edo errefusatu eskaera",
"check_bookings_page_to_confirm_or_reject": "Begiratu zure erreserba-orrialdea erreserba baieztatu edo errefusatzeko.", "check_bookings_page_to_confirm_or_reject": "Begiratu zure erreserba-orrialdea erreserba baieztatu edo errefusatzeko.",
"event_awaiting_approval": "Gertaera bat zure onarpenaren zain dago", "event_awaiting_approval": "Gertaera bat zure onarpenaren zain dago",
"event_awaiting_approval_recurring": "Gertaera errepikari bat zure onarpenaren zain dago",
"someone_requested_an_event": "Norbaitek zure egutegian gertaera bat programatzeko eskaera egin du.",
"someone_requested_password_reset": "Norbaitek zure pasahitza aldatzeko esteka bat eskatu du.",
"password_reset_email_sent": "Email helbide hau gure sisteman baldin badago, berrezartzeko email mezu bat jaso behar zenuke.",
"password_reset_instructions": "Ez baduzu eskaera hau egin, segurua da email mezu honi kasurik ez egitea, eta zure pasahitza ez da aldatuko.",
"event_awaiting_approval_subject": "Onarpenaren zain: {{title}} {{date}}(e)an",
"event_still_awaiting_approval": "Gertaera bat zure onarpenaren zain dago oraindik",
"booking_submitted_subject": "Erreserba bidalita: {{title}} {{date}}(e)an", "booking_submitted_subject": "Erreserba bidalita: {{title}} {{date}}(e)an",
"download_recording_subject": "Deskargatu grabaketa: {{title}} {{date}}(e)an",
"download_your_recording": "Deskargatu zure grabaketa",
"your_meeting_has_been_booked": "Zure bileraren erreserba egin da",
"event_type_has_been_rescheduled_on_time_date": "Zure {{title}} getaeraren programazioa aldatu egin da {{date}}(e)ra.", "event_type_has_been_rescheduled_on_time_date": "Zure {{title}} getaeraren programazioa aldatu egin da {{date}}(e)ra.",
"event_has_been_rescheduled": "Eguneratuta - Zure gertaeraren programazioa aldatu egin da",
"request_reschedule_subtitle": "{{organizer}}(e)k erreserba bertan behera utzi du eta beste denbora-tarte bat hautatzeko eskatu dizu.",
"request_reschedule_title_organizer": "Beste denbora-tarte bat hautatzeko eskatu diozu {{attendee}}(r)i",
"hi_user_name": "Kaixo {{name}}", "hi_user_name": "Kaixo {{name}}",
"ics_event_title": "{{eventType}} {{name}}(r)ekin", "ics_event_title": "{{eventType}} {{name}}(r)ekin",
"notes": "Oharrak", "notes": "Oharrak",
"manage_my_bookings": "Kudeatu nire erreserbak", "manage_my_bookings": "Kudeatu nire erreserbak",
"rejected_event_type_with_organizer": "Errefusatua: {{eventType}} {{organizer}}(r)ekin {{date}}(e)an", "rejected_event_type_with_organizer": "Errefusatua: {{eventType}} {{organizer}}(r)ekin {{date}}(e)an",
"hi": "Kaixo", "hi": "Kaixo",
"use_link_to_reset_password": "Erabili beheko esteka pasahitza berrezartzeko",
"hey_there": "Kaixo,",
"forgot_your_password_calcom": "Pasahitza ahaztu duzu? - {{appName}}",
"dismiss": "Alde batera utzi",
"no_data_yet": "Ez dago daturik",
"ping_test": "Ping testa",
"upcoming": "Laster",
"recurring": "Errepikariak",
"past": "Iraganekoak",
"choose_a_file": "Hautatu fitxategi bat...",
"upload_image": "Igo irudia",
"upload_target": "Igo {{target}}",
"no_target": "Ez dago {{target}}(r)ik",
"view_notifications": "Ikusi jakinarazpenak",
"view_public_page": "Ikusi orrialde publikoa",
"copy_public_page_link": "Kopiatu orrialde publikoaren esteka",
"sign_out": "Saioa itxi",
"add_another": "Gehitu beste bat",
"install_another": "Instalatu beste bat",
"unavailable": "Ez eskuragarri",
"set_work_schedule": "Ezarri zure laneko ordutegia",
"change_bookings_availability": "Aldatu noiz zauden prest erreserbak jasotzeko", "change_bookings_availability": "Aldatu noiz zauden prest erreserbak jasotzeko",
"select": "Hautatu...",
"text": "Testua",
"multiline_text": "Lerro ugaritako testua",
"number": "Zenbakia",
"checkbox": "Kontrol-laukia",
"is_required": "Derrigorrezkoa da",
"required": "Derrigorrezkoa",
"optional": "Hautazkoa",
"input_type": "Sarrera-mota",
"rejected": "Baztertua",
"unconfirmed": "Baieztatu gabea",
"guests": "Gonbidatuak",
"create_account": "Sortu kontua",
"confirm_password": "Baieztatu pasahitza",
"create_booking_link_with_calcom": "Sor ezazu zeure erreserba-esteka {{appName}}(e)kin", "create_booking_link_with_calcom": "Sor ezazu zeure erreserba-esteka {{appName}}(e)kin",
"user_needs_to_confirm_or_reject_booking": "{{user}}(e)k erreserba baieztatu edo errefusatu behar du oraindik.", "user_needs_to_confirm_or_reject_booking": "{{user}}(e)k erreserba baieztatu edo errefusatu behar du oraindik.",
"booking_submitted": "Zure erreserba bidali da", "booking_submitted": "Zure erreserba bidali da",
"booking_confirmed": "Zure erreserba baieztatu da", "booking_confirmed": "Zure erreserba baieztatu da",
"bookerlayout_column_view": "Zutabea",
"back_to_bookings": "Itzuli erreserbatara", "back_to_bookings": "Itzuli erreserbatara",
"really_cancel_booking": "Benetan bertan behera utzi nahi duzu zure erreserba?", "really_cancel_booking": "Benetan bertan behera utzi nahi duzu zure erreserba?",
"cannot_cancel_booking": "Ezin duzu erreserba hau bertan behera utzi", "cannot_cancel_booking": "Ezin duzu erreserba hau bertan behera utzi",
+1 -1
View File
@@ -1,4 +1,4 @@
import prismaMock from "../../../../tests/libs/__mocks__/prisma"; import prismaMock from "../../../../tests/libs/__mocks__/prismaMock";
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
@@ -1,4 +1,4 @@
import prismaMock from "../../../../tests/libs/__mocks__/prisma"; import prismaMock from "../../../../tests/libs/__mocks__/prismaMock";
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
+24 -26
View File
@@ -1,20 +1,18 @@
import CalendarManagerMock from "../../../../tests/libs/__mocks__/CalendarManager"; import CalendarManagerMock from "../../../../tests/libs/__mocks__/CalendarManager";
import prismaMock from "../../../../tests/libs/__mocks__/prisma"; import prismock from "../../../../tests/libs/__mocks__/prisma";
import { diff } from "jest-diff"; import { diff } from "jest-diff";
import { describe, expect, vi, beforeEach, afterEach, test } from "vitest"; import { describe, expect, vi, beforeEach, afterEach, test } from "vitest";
import prisma from "@calcom/prisma";
import type { BookingStatus } from "@calcom/prisma/enums"; import type { BookingStatus } from "@calcom/prisma/enums";
import type { Slot } from "@calcom/trpc/server/routers/viewer/slots/types"; import type { Slot } from "@calcom/trpc/server/routers/viewer/slots/types";
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util"; import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
import { getDate, getGoogleCalendarCredential, createBookingScenario } from "../utils/bookingScenario"; import {
getDate,
// TODO: Mock properly getGoogleCalendarCredential,
prismaMock.eventType.findUnique.mockResolvedValue(null); createBookingScenario,
// @ts-expect-error Prisma v5 typings are not yet available } from "../utils/bookingScenario/bookingScenario";
prismaMock.user.findMany.mockResolvedValue([]);
vi.mock("@calcom/lib/constants", () => ({ vi.mock("@calcom/lib/constants", () => ({
IS_PRODUCTION: true, IS_PRODUCTION: true,
@@ -146,13 +144,13 @@ const TestData = {
}; };
const cleanup = async () => { const cleanup = async () => {
await prisma.eventType.deleteMany(); await prismock.eventType.deleteMany();
await prisma.user.deleteMany(); await prismock.user.deleteMany();
await prisma.schedule.deleteMany(); await prismock.schedule.deleteMany();
await prisma.selectedCalendar.deleteMany(); await prismock.selectedCalendar.deleteMany();
await prisma.credential.deleteMany(); await prismock.credential.deleteMany();
await prisma.booking.deleteMany(); await prismock.booking.deleteMany();
await prisma.app.deleteMany(); await prismock.app.deleteMany();
}; };
beforeEach(async () => { beforeEach(async () => {
@@ -201,7 +199,7 @@ describe("getSchedule", () => {
apps: [TestData.apps.googleCalendar], apps: [TestData.apps.googleCalendar],
}; };
// An event with one accepted booking // An event with one accepted booking
createBookingScenario(scenarioData); await createBookingScenario(scenarioData);
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({ const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
input: { input: {
@@ -228,7 +226,7 @@ describe("getSchedule", () => {
const { dateString: plus3DateString } = getDate({ dateIncrement: 3 }); const { dateString: plus3DateString } = getDate({ dateIncrement: 3 });
// An event with one accepted booking // An event with one accepted booking
createBookingScenario({ await createBookingScenario({
// An event with length 30 minutes, slotInterval 45 minutes, and minimumBookingNotice 1440 minutes (24 hours) // An event with length 30 minutes, slotInterval 45 minutes, and minimumBookingNotice 1440 minutes (24 hours)
eventTypes: [ eventTypes: [
{ {
@@ -354,7 +352,7 @@ describe("getSchedule", () => {
}); });
test("slots are available as per `length`, `slotInterval` of the event", async () => { test("slots are available as per `length`, `slotInterval` of the event", async () => {
createBookingScenario({ await createBookingScenario({
eventTypes: [ eventTypes: [
{ {
id: 1, id: 1,
@@ -453,7 +451,7 @@ describe("getSchedule", () => {
})() })()
); );
createBookingScenario({ await createBookingScenario({
eventTypes: [ eventTypes: [
{ {
id: 1, id: 1,
@@ -569,7 +567,7 @@ describe("getSchedule", () => {
apps: [TestData.apps.googleCalendar], apps: [TestData.apps.googleCalendar],
}; };
createBookingScenario(scenarioData); await createBookingScenario(scenarioData);
const scheduleForEventOnADayWithNonCalBooking = await getSchedule({ const scheduleForEventOnADayWithNonCalBooking = await getSchedule({
input: { input: {
@@ -643,7 +641,7 @@ describe("getSchedule", () => {
apps: [TestData.apps.googleCalendar], apps: [TestData.apps.googleCalendar],
}; };
createBookingScenario(scenarioData); await createBookingScenario(scenarioData);
const scheduleForEventOnADayWithCalBooking = await getSchedule({ const scheduleForEventOnADayWithCalBooking = await getSchedule({
input: { input: {
@@ -701,7 +699,7 @@ describe("getSchedule", () => {
apps: [TestData.apps.googleCalendar], apps: [TestData.apps.googleCalendar],
}; };
createBookingScenario(scenarioData); await createBookingScenario(scenarioData);
const schedule = await getSchedule({ const schedule = await getSchedule({
input: { input: {
@@ -765,7 +763,7 @@ describe("getSchedule", () => {
], ],
}; };
createBookingScenario(scenarioData); await createBookingScenario(scenarioData);
const scheduleForEventOnADayWithDateOverride = await getSchedule({ const scheduleForEventOnADayWithDateOverride = await getSchedule({
input: { input: {
@@ -790,7 +788,7 @@ describe("getSchedule", () => {
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 }); const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 }); const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
createBookingScenario({ await createBookingScenario({
eventTypes: [ eventTypes: [
// A Collective Event Type hosted by this user // A Collective Event Type hosted by this user
{ {
@@ -885,7 +883,7 @@ describe("getSchedule", () => {
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 }); const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 }); const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
createBookingScenario({ await createBookingScenario({
eventTypes: [ eventTypes: [
// An event having two users with one accepted booking // An event having two users with one accepted booking
{ {
@@ -1010,7 +1008,7 @@ describe("getSchedule", () => {
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 }); const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
const { dateString: plus3DateString } = getDate({ dateIncrement: 3 }); const { dateString: plus3DateString } = getDate({ dateIncrement: 3 });
createBookingScenario({ await createBookingScenario({
eventTypes: [ eventTypes: [
// An event having two users with one accepted booking // An event having two users with one accepted booking
{ {
@@ -1,4 +1,4 @@
import prismaMock from "../../../../tests/libs/__mocks__/prisma"; import prismaMock from "../../../../tests/libs/__mocks__/prismaMock";
import type { EventType } from "@prisma/client"; import type { EventType } from "@prisma/client";
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it, vi } from "vitest";
+1 -1
View File
@@ -1,4 +1,4 @@
import prismaMock from "../../../../tests/libs/__mocks__/prisma"; import prismaMock from "../../../../tests/libs/__mocks__/prismaMock";
import { expect, it } from "vitest"; import { expect, it } from "vitest";
-754
View File
@@ -1,754 +0,0 @@
import appStoreMock from "../../../../tests/libs/__mocks__/app-store";
import i18nMock from "../../../../tests/libs/__mocks__/libServerI18n";
import prismaMock from "../../../../tests/libs/__mocks__/prisma";
import type {
EventType as PrismaEventType,
User as PrismaUser,
Booking as PrismaBooking,
App as PrismaApp,
} from "@prisma/client";
import type { Prisma } from "@prisma/client";
import type { WebhookTriggerEvents } from "@prisma/client";
import { v4 as uuidv4 } from "uuid";
import { expect } from "vitest";
import "vitest-fetch-mock";
import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
import logger from "@calcom/lib/logger";
import type { SchedulingType } from "@calcom/prisma/enums";
import type { BookingStatus } from "@calcom/prisma/enums";
import type { EventBusyDate } from "@calcom/types/Calendar";
import type { Fixtures } from "@calcom/web/test/fixtures/fixtures";
type App = {
slug: string;
dirName: string;
};
type InputWebhook = {
appId: string | null;
userId?: number | null;
teamId?: number | null;
eventTypeId?: number;
active: boolean;
eventTriggers: WebhookTriggerEvents[];
subscriberUrl: string;
};
/**
* Data to be mocked
*/
type ScenarioData = {
// hosts: { id: number; eventTypeId?: number; userId?: number; isFixed?: boolean }[];
/**
* Prisma would return these eventTypes
*/
eventTypes: InputEventType[];
/**
* Prisma would return these users
*/
users: InputUser[];
/**
* Prisma would return these apps
*/
apps?: App[];
bookings?: InputBooking[];
webhooks?: InputWebhook[];
};
type InputCredential = typeof TestData.credentials.google;
type InputSelectedCalendar = typeof TestData.selectedCalendars.google;
type InputUser = typeof TestData.users.example & { id: number } & {
credentials?: InputCredential[];
selectedCalendars?: InputSelectedCalendar[];
schedules: {
id: number;
name: string;
availability: {
userId: number | null;
eventTypeId: number | null;
days: number[];
startTime: Date;
endTime: Date;
date: string | null;
}[];
timeZone: string;
}[];
};
type InputEventType = {
id: number;
title?: string;
length?: number;
offsetStart?: number;
slotInterval?: number;
minimumBookingNotice?: number;
/**
* These user ids are `ScenarioData["users"]["id"]`
*/
users?: { id: number }[];
hosts?: { id: number }[];
schedulingType?: SchedulingType;
beforeEventBuffer?: number;
afterEventBuffer?: number;
requiresConfirmation?: boolean;
};
type InputBooking = {
userId?: number;
eventTypeId: number;
startTime: string;
endTime: string;
title?: string;
status: BookingStatus;
attendees?: { email: string }[];
};
const Timezones = {
"+5:30": "Asia/Kolkata",
"+6:00": "Asia/Dhaka",
};
function addEventTypes(eventTypes: InputEventType[], usersStore: InputUser[]) {
const baseEventType = {
title: "Base EventType Title",
slug: "base-event-type-slug",
timeZone: null,
beforeEventBuffer: 0,
afterEventBuffer: 0,
schedulingType: null,
//TODO: What is the purpose of periodStartDate and periodEndDate? Test these?
periodStartDate: new Date("2022-01-21T09:03:48.000Z"),
periodEndDate: new Date("2022-01-21T09:03:48.000Z"),
periodCountCalendarDays: false,
periodDays: 30,
seatsPerTimeSlot: null,
metadata: {},
minimumBookingNotice: 0,
offsetStart: 0,
};
const foundEvents: Record<number, boolean> = {};
const eventTypesWithUsers = eventTypes.map((eventType) => {
if (!eventType.slotInterval && !eventType.length) {
throw new Error("eventTypes[number]: slotInterval or length must be defined");
}
if (foundEvents[eventType.id]) {
throw new Error(`eventTypes[number]: id ${eventType.id} is not unique`);
}
foundEvents[eventType.id] = true;
const users =
eventType.users?.map((userWithJustId) => {
return usersStore.find((user) => user.id === userWithJustId.id);
}) || [];
return {
...baseEventType,
...eventType,
workflows: [],
users,
};
});
logger.silly("TestData: Creating EventType", eventTypes);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const eventTypeMock = ({ where }) => {
return new Promise((resolve) => {
const eventType = eventTypesWithUsers.find((e) => e.id === where.id) as unknown as PrismaEventType & {
users: PrismaUser[];
};
resolve(eventType);
});
};
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
prismaMock.eventType.findUnique.mockImplementation(eventTypeMock);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
prismaMock.eventType.findUniqueOrThrow.mockImplementation(eventTypeMock);
}
async function addBookings(bookings: InputBooking[], eventTypes: InputEventType[]) {
logger.silly("TestData: Creating Bookings", bookings);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
prismaMock.booking.findMany.mockImplementation((findManyArg) => {
// @ts-expect-error Prisma v5 breaks this
const where = findManyArg?.where || {};
return new Promise((resolve) => {
resolve(
// @ts-expect-error Prisma v5 breaks this
bookings
// We can improve this filter to support the entire where clause but that isn't necessary yet. So, handle what we know we pass to `findMany` and is needed
.filter((booking) => {
/**
* A user is considered busy within a given time period if there
* is a booking they own OR host. This function mocks some of the logic
* for each condition. For details see the following ticket:
* https://github.com/calcom/cal.com/issues/6374
*/
// ~~ FIRST CONDITION ensures that this booking is owned by this user
// and that the status is what we want
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const statusIn = where.OR[0].status?.in || [];
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const userIdIn = where.OR[0].userId?.in || [];
const firstConditionMatches =
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
statusIn.includes(booking.status) &&
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(booking.userId === where.OR[0].userId || userIdIn.includes(booking.userId));
// We return this booking if either condition is met
return firstConditionMatches;
})
.map((booking) => ({
uid: uuidv4(),
title: "Test Booking Title",
...booking,
eventType: eventTypes.find((eventType) => eventType.id === booking.eventTypeId),
})) as unknown as PrismaBooking[]
);
});
});
}
async function addWebhooks(webhooks: InputWebhook[]) {
prismaMock.webhook.findMany.mockResolvedValue(
// @ts-expect-error Prisma v5 breaks this
webhooks.map((webhook) => {
return {
...webhook,
payloadTemplate: null,
secret: null,
id: uuidv4(),
createdAt: new Date(),
userId: webhook.userId || null,
eventTypeId: webhook.eventTypeId || null,
teamId: webhook.teamId || null,
};
})
);
}
function addUsers(users: InputUser[]) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
prismaMock.user.findUniqueOrThrow.mockImplementation((findUniqueArgs) => {
return new Promise((resolve) => {
// @ts-expect-error Prisma v5 breaks this
resolve({
// @ts-expect-error Prisma v5 breaks this
email: `IntegrationTestUser${findUniqueArgs?.where.id}@example.com`,
} as unknown as PrismaUser);
});
});
prismaMock.user.findMany.mockResolvedValue(
// @ts-expect-error Prisma v5 breaks this
users.map((user) => {
return {
...user,
username: `IntegrationTestUser${user.id}`,
email: `IntegrationTestUser${user.id}@example.com`,
};
}) as unknown as PrismaUser[]
);
}
export async function createBookingScenario(data: ScenarioData) {
logger.silly("TestData: Creating Scenario", data);
addUsers(data.users);
const eventType = addEventTypes(data.eventTypes, data.users);
if (data.apps) {
// @ts-expect-error Prisma v5 breaks this
prismaMock.app.findMany.mockResolvedValue(data.apps as PrismaApp[]);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
const appMock = ({ where: { slug: whereSlug } }) => {
return new Promise((resolve) => {
if (!data.apps) {
resolve(null);
return;
}
const foundApp = data.apps.find(({ slug }) => slug == whereSlug);
//TODO: Pass just the app name in data.apps and maintain apps in a separate object or load them dyamically
resolve(
({
...foundApp,
...(foundApp?.slug ? TestData.apps[foundApp.slug as keyof typeof TestData.apps] || {} : {}),
enabled: true,
createdAt: new Date(),
updatedAt: new Date(),
categories: [],
} as PrismaApp) || null
);
});
};
// FIXME: How do we know which app to return?
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
prismaMock.app.findUnique.mockImplementation(appMock);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
prismaMock.app.findFirst.mockImplementation(appMock);
}
data.bookings = data.bookings || [];
allowSuccessfulBookingCreation();
addBookings(data.bookings, data.eventTypes);
// mockBusyCalendarTimes([]);
addWebhooks(data.webhooks || []);
return {
eventType,
};
}
/**
* This fn indents to /ally compute day, month, year for the purpose of testing.
* We are not using DayJS because that's actually being tested by this code.
* - `dateIncrement` adds the increment to current day
* - `monthIncrement` adds the increment to current month
* - `yearIncrement` adds the increment to current year
*/
export const getDate = (
param: { dateIncrement?: number; monthIncrement?: number; yearIncrement?: number } = {}
) => {
let { dateIncrement, monthIncrement, yearIncrement } = param;
dateIncrement = dateIncrement || 0;
monthIncrement = monthIncrement || 0;
yearIncrement = yearIncrement || 0;
let _date = new Date().getDate() + dateIncrement;
let year = new Date().getFullYear() + yearIncrement;
// Make it start with 1 to match with DayJS requiremet
let _month = new Date().getMonth() + monthIncrement + 1;
// If last day of the month(As _month is plus 1 already it is going to be the 0th day of next month which is the last day of current month)
const lastDayOfMonth = new Date(year, _month, 0).getDate();
const numberOfDaysForNextMonth = +_date - +lastDayOfMonth;
if (numberOfDaysForNextMonth > 0) {
_date = numberOfDaysForNextMonth;
_month = _month + 1;
}
if (_month === 13) {
_month = 1;
year = year + 1;
}
const date = _date < 10 ? "0" + _date : _date;
const month = _month < 10 ? "0" + _month : _month;
return {
date,
month,
year,
dateString: `${year}-${month}-${date}`,
};
};
export function getMockedCredential({
metadataLookupKey,
key,
}: {
metadataLookupKey: string;
key: {
expiry_date?: number;
token_type?: string;
access_token?: string;
refresh_token?: string;
scope: string;
};
}) {
return {
type: appStoreMetadata[metadataLookupKey as keyof typeof appStoreMetadata].type,
appId: appStoreMetadata[metadataLookupKey as keyof typeof appStoreMetadata].slug,
key: {
expiry_date: Date.now() + 1000000,
token_type: "Bearer",
access_token: "ACCESS_TOKEN",
refresh_token: "REFRESH_TOKEN",
...key,
},
};
}
export function getGoogleCalendarCredential() {
return getMockedCredential({
metadataLookupKey: "googlecalendar",
key: {
scope:
"https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar.readonly",
},
});
}
export function getZoomAppCredential() {
return getMockedCredential({
metadataLookupKey: "zoomvideo",
key: {
scope: "meeting:writed",
},
});
}
export const TestData = {
selectedCalendars: {
google: {
integration: "google_calendar",
externalId: "john@example.com",
},
},
credentials: {
google: getGoogleCalendarCredential(),
},
schedules: {
IstWorkHours: {
id: 1,
name: "9:30AM to 6PM in India - 4:00AM to 12:30PM in GMT",
availability: [
{
userId: null,
eventTypeId: null,
days: [0, 1, 2, 3, 4, 5, 6],
startTime: new Date("1970-01-01T09:30:00.000Z"),
endTime: new Date("1970-01-01T18:00:00.000Z"),
date: null,
},
],
timeZone: Timezones["+5:30"],
},
IstWorkHoursWithDateOverride: (dateString: string) => ({
id: 1,
name: "9:30AM to 6PM in India - 4:00AM to 12:30PM in GMT but with a Date Override for 2PM to 6PM IST(in GST time it is 8:30AM to 12:30PM)",
availability: [
{
userId: null,
eventTypeId: null,
days: [0, 1, 2, 3, 4, 5, 6],
startTime: new Date("1970-01-01T09:30:00.000Z"),
endTime: new Date("1970-01-01T18:00:00.000Z"),
date: null,
},
{
userId: null,
eventTypeId: null,
days: [0, 1, 2, 3, 4, 5, 6],
startTime: new Date(`1970-01-01T14:00:00.000Z`),
endTime: new Date(`1970-01-01T18:00:00.000Z`),
date: dateString,
},
],
timeZone: Timezones["+5:30"],
}),
},
users: {
example: {
name: "Example",
email: "example@example.com",
username: "example",
defaultScheduleId: 1,
timeZone: Timezones["+5:30"],
},
},
apps: {
"google-calendar": {
slug: "google-calendar",
dirName: "whatever",
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
keys: {
expiry_date: Infinity,
client_id: "client_id",
client_secret: "client_secret",
redirect_uris: ["http://localhost:3000/auth/callback"],
},
},
"daily-video": {
slug: "daily-video",
dirName: "whatever",
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
keys: {
expiry_date: Infinity,
api_key: "",
scale_plan: "false",
client_id: "client_id",
client_secret: "client_secret",
redirect_uris: ["http://localhost:3000/auth/callback"],
},
},
},
};
function allowSuccessfulBookingCreation() {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
prismaMock.booking.create.mockImplementation(function (booking) {
return booking.data;
});
}
export class MockError extends Error {
constructor(message: string) {
super(message);
this.name = "MockError";
}
}
export function getOrganizer({
name,
email,
id,
schedules,
credentials,
selectedCalendars,
}: {
name: string;
email: string;
id: number;
schedules: InputUser["schedules"];
credentials?: InputCredential[];
selectedCalendars?: InputSelectedCalendar[];
}) {
return {
...TestData.users.example,
name,
email,
id,
schedules,
credentials,
selectedCalendars,
};
}
export function getScenarioData({
organizer,
eventTypes,
usersApartFromOrganizer = [],
apps = [],
webhooks,
}: // hosts = [],
{
organizer: ReturnType<typeof getOrganizer>;
eventTypes: ScenarioData["eventTypes"];
apps: ScenarioData["apps"];
usersApartFromOrganizer?: ScenarioData["users"];
webhooks?: ScenarioData["webhooks"];
// hosts?: ScenarioData["hosts"];
}) {
const users = [organizer, ...usersApartFromOrganizer];
eventTypes.forEach((eventType) => {
if (
eventType.users?.filter((eventTypeUser) => {
return !users.find((userToCreate) => userToCreate.id === eventTypeUser.id);
}).length
) {
throw new Error(`EventType ${eventType.id} has users that are not present in ScenarioData["users"]`);
}
});
return {
// hosts: [...hosts],
eventTypes: [...eventTypes],
users,
apps: [...apps],
webhooks,
};
}
export function mockEnableEmailFeature() {
// @ts-expect-error Prisma v5 breaks this
prismaMock.feature.findMany.mockResolvedValue([
{
slug: "emails",
// It's a kill switch
enabled: false,
},
]);
}
export function mockNoTranslations() {
// @ts-expect-error FIXME
i18nMock.getTranslation.mockImplementation(() => {
return new Promise((resolve) => {
const identityFn = (key: string) => key;
resolve(identityFn);
});
});
}
export function mockCalendarToHaveNoBusySlots(metadataLookupKey: keyof typeof appStoreMetadata) {
const appStoreLookupKey = metadataLookupKey;
appStoreMock.default[appStoreLookupKey as keyof typeof appStoreMock.default].mockResolvedValue({
lib: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
CalendarService: function MockCalendarService() {
return {
createEvent: () => {
return Promise.resolve({
type: "daily_video",
id: "dailyEventName",
password: "dailyvideopass",
url: "http://dailyvideo.example.com",
});
},
getAvailability: (): Promise<EventBusyDate[]> => {
return new Promise((resolve) => {
resolve([]);
});
},
};
},
},
});
}
export function mockSuccessfulVideoMeetingCreation({
metadataLookupKey,
appStoreLookupKey,
}: {
metadataLookupKey: string;
appStoreLookupKey?: string;
}) {
appStoreLookupKey = appStoreLookupKey || metadataLookupKey;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
appStoreMock.default[appStoreLookupKey as keyof typeof appStoreMock.default].mockImplementation(() => {
return new Promise((resolve) => {
resolve({
lib: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
VideoApiAdapter: () => ({
createMeeting: () => {
return Promise.resolve({
type: appStoreMetadata[metadataLookupKey as keyof typeof appStoreMetadata].type,
id: "MOCK_ID",
password: "MOCK_PASS",
url: `http://mock-${metadataLookupKey}.example.com`,
});
},
}),
},
});
});
});
}
export function mockErrorOnVideoMeetingCreation({
metadataLookupKey,
appStoreLookupKey,
}: {
metadataLookupKey: string;
appStoreLookupKey?: string;
}) {
appStoreLookupKey = appStoreLookupKey || metadataLookupKey;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
appStoreMock.default[appStoreLookupKey].mockImplementation(() => {
return new Promise((resolve) => {
resolve({
lib: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
VideoApiAdapter: () => ({
createMeeting: () => {
throw new MockError("Error creating Video meeting");
},
}),
},
});
});
});
}
export function expectWebhookToHaveBeenCalledWith(
subscriberUrl: string,
data: {
triggerEvent: WebhookTriggerEvents;
payload: { metadata: Record<string, unknown>; responses: Record<string, unknown> };
}
) {
const fetchCalls = fetchMock.mock.calls;
const webhookFetchCall = fetchCalls.find((call) => call[0] === subscriberUrl);
if (!webhookFetchCall) {
throw new Error(`Webhook not called with ${subscriberUrl}`);
}
expect(webhookFetchCall[0]).toBe(subscriberUrl);
const body = webhookFetchCall[1]?.body;
const parsedBody = JSON.parse((body as string) || "{}");
console.log({ payload: parsedBody.payload });
expect(parsedBody.triggerEvent).toBe(data.triggerEvent);
parsedBody.payload.metadata.videoCallUrl = parsedBody.payload.metadata.videoCallUrl
? parsedBody.payload.metadata.videoCallUrl.replace(/\/video\/[a-zA-Z0-9]{22}/, "/video/DYNAMIC_UID")
: parsedBody.payload.metadata.videoCallUrl;
expect(parsedBody.payload.metadata).toContain(data.payload.metadata);
expect(parsedBody.payload.responses).toEqual(data.payload.responses);
}
export function expectWorkflowToBeTriggered() {
// TODO: Implement this.
}
export function expectBookingToBeInDatabase(booking: Partial<Prisma.BookingCreateInput>) {
const createBookingCalledWithArgs = prismaMock.booking.create.mock.calls[0];
expect(createBookingCalledWithArgs[0].data).toEqual(expect.objectContaining(booking));
}
export function getBooker({ name, email }: { name: string; email: string }) {
return {
name,
email,
};
}
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace jest {
interface Matchers<R> {
toHaveEmail(expectedEmail: { htmlToContain?: string; to: string }): R;
}
}
}
expect.extend({
toHaveEmail(
testEmail: ReturnType<Fixtures["emails"]["get"]>[number],
expectedEmail: {
//TODO: Support email HTML parsing to target specific elements
htmlToContain?: string;
to: string;
}
) {
let isHtmlContained = true;
let isToAddressExpected = true;
if (expectedEmail.htmlToContain) {
isHtmlContained = testEmail.html.includes(expectedEmail.htmlToContain);
}
isToAddressExpected = expectedEmail.to === testEmail.to;
return {
pass: isHtmlContained && isToAddressExpected,
message: () => {
if (!isHtmlContained) {
return `Email HTML is not as expected. Expected:"${expectedEmail.htmlToContain}" isn't contained in "${testEmail.html}"`;
}
return `Email To address is not as expected. Expected:${expectedEmail.to} isn't contained in ${testEmail.to}`;
},
};
},
});
@@ -0,0 +1,88 @@
import prismaMock from "../../../../../tests/libs/__mocks__/prisma";
import type { Payment, Prisma, PaymentOption, Booking } from "@prisma/client";
import { v4 as uuidv4 } from "uuid";
import "vitest-fetch-mock";
import { sendAwaitingPaymentEmail } from "@calcom/emails";
import logger from "@calcom/lib/logger";
import type { CalendarEvent } from "@calcom/types/Calendar";
import type { IAbstractPaymentService } from "@calcom/types/PaymentService";
export function getMockPaymentService() {
function createPaymentLink(/*{ paymentUid, name, email, date }*/) {
return "http://mock-payment.example.com/";
}
const paymentUid = uuidv4();
const externalId = uuidv4();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
class MockPaymentService implements IAbstractPaymentService {
// TODO: We shouldn't need to implement adding a row to Payment table but that's a requirement right now.
// We should actually delegate table creation to the core app. Here, only the payment app specific logic should come
async create(
payment: Pick<Prisma.PaymentUncheckedCreateInput, "amount" | "currency">,
bookingId: Booking["id"],
userId: Booking["userId"],
username: string | null,
bookerName: string | null,
bookerEmail: string,
paymentOption: PaymentOption
) {
const paymentCreateData = {
id: 1,
uid: paymentUid,
appId: null,
bookingId,
// booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
fee: 10,
success: true,
refunded: false,
data: {},
externalId,
paymentOption,
amount: payment.amount,
currency: payment.currency,
};
const paymentData = prismaMock.payment.create({
data: paymentCreateData,
});
logger.silly("Created mock payment", JSON.stringify({ paymentData }));
return paymentData;
}
async afterPayment(
event: CalendarEvent,
booking: {
user: { email: string | null; name: string | null; timeZone: string } | null;
id: number;
startTime: { toISOString: () => string };
uid: string;
},
paymentData: Payment
): Promise<void> {
// TODO: App implementing PaymentService is supposed to send email by itself at the moment.
await sendAwaitingPaymentEmail({
...event,
paymentInfo: {
link: createPaymentLink(/*{
paymentUid: paymentData.uid,
name: booking.user?.name,
email: booking.user?.email,
date: booking.startTime.toISOString(),
}*/),
paymentOption: paymentData.paymentOption || "ON_BOOKING",
amount: paymentData.amount,
currency: paymentData.currency,
},
});
}
}
return {
paymentUid,
externalId,
MockPaymentService,
};
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,646 @@
import prismaMock from "../../../../../tests/libs/__mocks__/prisma";
import type { WebhookTriggerEvents, Booking, BookingReference } from "@prisma/client";
import ical from "node-ical";
import { expect } from "vitest";
import "vitest-fetch-mock";
import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";
import { BookingStatus } from "@calcom/prisma/enums";
import type { CalendarEvent } from "@calcom/types/Calendar";
import type { Fixtures } from "@calcom/web/test/fixtures/fixtures";
import type { InputEventType } from "./bookingScenario";
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace jest {
interface Matchers<R> {
toHaveEmail(
expectedEmail: {
//TODO: Support email HTML parsing to target specific elements
htmlToContain?: string;
to: string;
noIcs?: true;
ics?: {
filename: string;
iCalUID: string;
};
},
to: string
): R;
}
}
}
expect.extend({
toHaveEmail(
emails: Fixtures["emails"],
expectedEmail: {
//TODO: Support email HTML parsing to target specific elements
htmlToContain?: string;
to: string;
ics: {
filename: string;
iCalUID: string;
};
noIcs: true;
},
to: string
) {
const testEmail = emails.get().find((email) => email.to.includes(to));
const emailsToLog = emails
.get()
.map((email) => ({ to: email.to, html: email.html, ics: email.icalEvent }));
if (!testEmail) {
logger.silly("All Emails", JSON.stringify({ numEmails: emailsToLog.length, emailsToLog }));
return {
pass: false,
message: () => `No email sent to ${to}`,
};
}
const ics = testEmail.icalEvent;
const icsObject = ics?.content ? ical.sync.parseICS(ics?.content) : null;
let isHtmlContained = true;
let isToAddressExpected = true;
const isIcsFilenameExpected = expectedEmail.ics ? ics?.filename === expectedEmail.ics.filename : true;
const isIcsUIDExpected = expectedEmail.ics
? !!(icsObject ? icsObject[expectedEmail.ics.iCalUID] : null)
: true;
if (expectedEmail.htmlToContain) {
isHtmlContained = testEmail.html.includes(expectedEmail.htmlToContain);
}
isToAddressExpected = expectedEmail.to === testEmail.to;
if (!isHtmlContained || !isToAddressExpected) {
logger.silly("All Emails", JSON.stringify({ numEmails: emailsToLog.length, emailsToLog }));
}
return {
pass:
isHtmlContained &&
isToAddressExpected &&
(expectedEmail.noIcs ? true : isIcsFilenameExpected && isIcsUIDExpected),
message: () => {
if (!isHtmlContained) {
return `Email HTML is not as expected. Expected:"${expectedEmail.htmlToContain}" isn't contained in "${testEmail.html}"`;
}
if (!isToAddressExpected) {
return `Email To address is not as expected. Expected:${expectedEmail.to} isn't equal to ${testEmail.to}`;
}
if (!isIcsFilenameExpected) {
return `ICS Filename is not as expected. Expected:${expectedEmail.ics.filename} isn't equal to ${ics?.filename}`;
}
if (!isIcsUIDExpected) {
return `ICS UID is not as expected. Expected:${
expectedEmail.ics.iCalUID
} isn't present in ${JSON.stringify(icsObject)}`;
}
throw new Error("Unknown error");
},
};
},
});
export function expectWebhookToHaveBeenCalledWith(
subscriberUrl: string,
data: {
triggerEvent: WebhookTriggerEvents;
payload: Record<string, unknown> | null;
}
) {
const fetchCalls = fetchMock.mock.calls;
const webhooksToSubscriberUrl = fetchCalls.filter((call) => {
return call[0] === subscriberUrl;
});
logger.silly("Scanning fetchCalls for webhook", safeStringify(fetchCalls));
const webhookFetchCall = webhooksToSubscriberUrl.find((call) => {
const body = call[1]?.body;
const parsedBody = JSON.parse((body as string) || "{}");
return parsedBody.triggerEvent === data.triggerEvent;
});
if (!webhookFetchCall) {
throw new Error(
`Webhook not sent to ${subscriberUrl} for ${data.triggerEvent}. All webhooks: ${JSON.stringify(
webhooksToSubscriberUrl
)}`
);
}
expect(webhookFetchCall[0]).toBe(subscriberUrl);
const body = webhookFetchCall[1]?.body;
const parsedBody = JSON.parse((body as string) || "{}");
expect(parsedBody.triggerEvent).toBe(data.triggerEvent);
if (parsedBody.payload.metadata?.videoCallUrl) {
parsedBody.payload.metadata.videoCallUrl = parsedBody.payload.metadata.videoCallUrl
? parsedBody.payload.metadata.videoCallUrl.replace(/\/video\/[a-zA-Z0-9]{22}/, "/video/DYNAMIC_UID")
: parsedBody.payload.metadata.videoCallUrl;
}
if (data.payload) {
if (data.payload.metadata !== undefined) {
expect(parsedBody.payload.metadata).toEqual(expect.objectContaining(data.payload.metadata));
}
if (data.payload.responses !== undefined)
expect(parsedBody.payload.responses).toEqual(expect.objectContaining(data.payload.responses));
const { responses: _1, metadata: _2, ...remainingPayload } = data.payload;
expect(parsedBody.payload).toEqual(expect.objectContaining(remainingPayload));
}
}
export function expectWorkflowToBeTriggered() {
// TODO: Implement this.
}
export async function expectBookingToBeInDatabase(
booking: Partial<Booking> & Pick<Booking, "uid"> & { references?: Partial<BookingReference>[] }
) {
const actualBooking = await prismaMock.booking.findUnique({
where: {
uid: booking.uid,
},
include: {
references: true,
},
});
const { references, ...remainingBooking } = booking;
expect(actualBooking).toEqual(expect.objectContaining(remainingBooking));
expect(actualBooking?.references).toEqual(
expect.arrayContaining((references || []).map((reference) => expect.objectContaining(reference)))
);
}
export function expectSuccessfulBookingCreationEmails({
emails,
organizer,
booker,
iCalUID,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string };
booker: { email: string; name: string };
iCalUID: string;
}) {
expect(emails).toHaveEmail(
{
htmlToContain: "<title>confirmed_event_type_subject</title>",
to: `${organizer.email}`,
ics: {
filename: "event.ics",
iCalUID: iCalUID,
},
},
`${organizer.email}`
);
expect(emails).toHaveEmail(
{
htmlToContain: "<title>confirmed_event_type_subject</title>",
to: `${booker.name} <${booker.email}>`,
ics: {
filename: "event.ics",
iCalUID: iCalUID,
},
},
`${booker.name} <${booker.email}>`
);
}
export function expectBrokenIntegrationEmails({
emails,
organizer,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string };
}) {
// Broken Integration email is only sent to the Organizer
expect(emails).toHaveEmail(
{
htmlToContain: "<title>broken_integration</title>",
to: `${organizer.email}`,
// No ics goes in case of broken integration email it seems
// ics: {
// filename: "event.ics",
// iCalUID: iCalUID,
// },
},
`${organizer.email}`
);
// expect(emails).toHaveEmail(
// {
// htmlToContain: "<title>confirmed_event_type_subject</title>",
// to: `${booker.name} <${booker.email}>`,
// },
// `${booker.name} <${booker.email}>`
// );
}
export function expectCalendarEventCreationFailureEmails({
emails,
organizer,
booker,
iCalUID,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string };
booker: { email: string; name: string };
iCalUID: string;
}) {
expect(emails).toHaveEmail(
{
htmlToContain: "<title>broken_integration</title>",
to: `${organizer.email}`,
ics: {
filename: "event.ics",
iCalUID,
},
},
`${organizer.email}`
);
expect(emails).toHaveEmail(
{
htmlToContain: "<title>calendar_event_creation_failure_subject</title>",
to: `${booker.name} <${booker.email}>`,
ics: {
filename: "event.ics",
iCalUID,
},
},
`${booker.name} <${booker.email}>`
);
}
export function expectSuccessfulBookingRescheduledEmails({
emails,
organizer,
booker,
iCalUID,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string };
booker: { email: string; name: string };
iCalUID: string;
}) {
expect(emails).toHaveEmail(
{
htmlToContain: "<title>event_type_has_been_rescheduled_on_time_date</title>",
to: `${organizer.email}`,
ics: {
filename: "event.ics",
iCalUID,
},
},
`${organizer.email}`
);
expect(emails).toHaveEmail(
{
htmlToContain: "<title>event_type_has_been_rescheduled_on_time_date</title>",
to: `${booker.name} <${booker.email}>`,
ics: {
filename: "event.ics",
iCalUID,
},
},
`${booker.name} <${booker.email}>`
);
}
export function expectAwaitingPaymentEmails({
emails,
booker,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string };
booker: { email: string; name: string };
}) {
expect(emails).toHaveEmail(
{
htmlToContain: "<title>awaiting_payment_subject</title>",
to: `${booker.name} <${booker.email}>`,
noIcs: true,
},
`${booker.email}`
);
}
export function expectBookingRequestedEmails({
emails,
organizer,
booker,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string };
booker: { email: string; name: string };
}) {
expect(emails).toHaveEmail(
{
htmlToContain: "<title>event_awaiting_approval_subject</title>",
to: `${organizer.email}`,
noIcs: true,
},
`${organizer.email}`
);
expect(emails).toHaveEmail(
{
htmlToContain: "<title>booking_submitted_subject</title>",
to: `${booker.email}`,
noIcs: true,
},
`${booker.email}`
);
}
export function expectBookingRequestedWebhookToHaveBeenFired({
booker,
location,
subscriberUrl,
paidEvent,
eventType,
}: {
organizer: { email: string; name: string };
booker: { email: string; name: string };
subscriberUrl: string;
location: string;
paidEvent?: boolean;
eventType: InputEventType;
}) {
// There is an inconsistency in the way we send the data to the webhook for paid events and unpaid events. Fix that and then remove this if statement.
if (!paidEvent) {
expectWebhookToHaveBeenCalledWith(subscriberUrl, {
triggerEvent: "BOOKING_REQUESTED",
payload: {
eventTitle: eventType.title,
eventDescription: eventType.description,
metadata: {
// In a Pending Booking Request, we don't send the video call url
},
responses: {
name: { label: "your_name", value: booker.name },
email: { label: "email_address", value: booker.email },
location: {
label: "location",
value: { optionValue: "", value: location },
},
},
},
});
} else {
expectWebhookToHaveBeenCalledWith(subscriberUrl, {
triggerEvent: "BOOKING_REQUESTED",
payload: {
eventTitle: eventType.title,
eventDescription: eventType.description,
metadata: {
// In a Pending Booking Request, we don't send the video call url
},
responses: {
name: { label: "name", value: booker.name },
email: { label: "email", value: booker.email },
location: {
label: "location",
value: { optionValue: "", value: location },
},
},
},
});
}
}
export function expectBookingCreatedWebhookToHaveBeenFired({
booker,
location,
subscriberUrl,
paidEvent,
videoCallUrl,
}: {
organizer: { email: string; name: string };
booker: { email: string; name: string };
subscriberUrl: string;
location: string;
paidEvent?: boolean;
videoCallUrl?: string | null;
}) {
if (!paidEvent) {
expectWebhookToHaveBeenCalledWith(subscriberUrl, {
triggerEvent: "BOOKING_CREATED",
payload: {
metadata: {
...(videoCallUrl ? { videoCallUrl } : null),
},
responses: {
name: { label: "your_name", value: booker.name },
email: { label: "email_address", value: booker.email },
location: {
label: "location",
value: { optionValue: "", value: location },
},
},
},
});
} else {
expectWebhookToHaveBeenCalledWith(subscriberUrl, {
triggerEvent: "BOOKING_CREATED",
payload: {
// FIXME: File this bug and link ticket here. This is a bug in the code. metadata must be sent here like other BOOKING_CREATED webhook
metadata: null,
responses: {
name: { label: "name", value: booker.name },
email: { label: "email", value: booker.email },
location: {
label: "location",
value: { optionValue: "", value: location },
},
},
},
});
}
}
export function expectBookingRescheduledWebhookToHaveBeenFired({
booker,
location,
subscriberUrl,
videoCallUrl,
}: {
organizer: { email: string; name: string };
booker: { email: string; name: string };
subscriberUrl: string;
location: string;
paidEvent?: boolean;
videoCallUrl?: string;
}) {
expectWebhookToHaveBeenCalledWith(subscriberUrl, {
triggerEvent: "BOOKING_RESCHEDULED",
payload: {
metadata: {
...(videoCallUrl ? { videoCallUrl } : null),
},
responses: {
name: { label: "your_name", value: booker.name },
email: { label: "email_address", value: booker.email },
location: {
label: "location",
value: { optionValue: "", value: location },
},
},
},
});
}
export function expectBookingPaymentIntiatedWebhookToHaveBeenFired({
booker,
location,
subscriberUrl,
paymentId,
}: {
organizer: { email: string; name: string };
booker: { email: string; name: string };
subscriberUrl: string;
location: string;
paymentId: number;
}) {
expectWebhookToHaveBeenCalledWith(subscriberUrl, {
triggerEvent: "BOOKING_PAYMENT_INITIATED",
payload: {
paymentId: paymentId,
metadata: {
// In a Pending Booking Request, we don't send the video call url
},
responses: {
name: { label: "your_name", value: booker.name },
email: { label: "email_address", value: booker.email },
location: {
label: "location",
value: { optionValue: "", value: location },
},
},
},
});
}
export function expectSuccessfulCalendarEventCreationInCalendar(
calendarMock: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createEventCalls: any[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateEventCalls: any[];
},
expected: {
calendarId: string | null;
videoCallUrl: string;
}
) {
expect(calendarMock.createEventCalls.length).toBe(1);
const call = calendarMock.createEventCalls[0];
const calEvent = call[0];
expect(calEvent).toEqual(
expect.objectContaining({
destinationCalendar: expected.calendarId
? [
expect.objectContaining({
externalId: expected.calendarId,
}),
]
: null,
videoCallData: expect.objectContaining({
url: expected.videoCallUrl,
}),
})
);
}
export function expectSuccessfulCalendarEventUpdationInCalendar(
calendarMock: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createEventCalls: any[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateEventCalls: any[];
},
expected: {
externalCalendarId: string;
calEvent: Partial<CalendarEvent>;
uid: string;
}
) {
expect(calendarMock.updateEventCalls.length).toBe(1);
const call = calendarMock.updateEventCalls[0];
const uid = call[0];
const calendarEvent = call[1];
const externalId = call[2];
expect(uid).toBe(expected.uid);
expect(calendarEvent).toEqual(expect.objectContaining(expected.calEvent));
expect(externalId).toBe(expected.externalCalendarId);
}
export function expectSuccessfulVideoMeetingCreationInCalendar(
videoMock: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createMeetingCalls: any[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateMeetingCalls: any[];
},
expected: {
externalCalendarId: string;
calEvent: Partial<CalendarEvent>;
uid: string;
}
) {
expect(videoMock.createMeetingCalls.length).toBe(1);
const call = videoMock.createMeetingCalls[0];
const uid = call[0];
const calendarEvent = call[1];
const externalId = call[2];
expect(uid).toBe(expected.uid);
expect(calendarEvent).toEqual(expect.objectContaining(expected.calEvent));
expect(externalId).toBe(expected.externalCalendarId);
}
export function expectSuccessfulVideoMeetingUpdationInCalendar(
videoMock: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createMeetingCalls: any[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateMeetingCalls: any[];
},
expected: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
bookingRef: any;
calEvent: Partial<CalendarEvent>;
}
) {
expect(videoMock.updateMeetingCalls.length).toBe(1);
const call = videoMock.updateMeetingCalls[0];
const bookingRef = call[0];
const calendarEvent = call[1];
expect(bookingRef).toEqual(expect.objectContaining(expected.bookingRef));
expect(calendarEvent).toEqual(expect.objectContaining(expected.calEvent));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function expectBookingInDBToBeRescheduledFromTo({ from, to }: { from: any; to: any }) {
// Expect previous booking to be cancelled
await expectBookingToBeInDatabase({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...from,
status: BookingStatus.CANCELLED,
});
// Expect new booking to be created
await expectBookingToBeInDatabase({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...to,
status: BookingStatus.ACCEPTED,
});
}
+3
View File
@@ -78,6 +78,7 @@
"@playwright/test": "^1.31.2", "@playwright/test": "^1.31.2",
"@snaplet/copycat": "^0.3.0", "@snaplet/copycat": "^0.3.0",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@types/jsonwebtoken": "^9.0.3",
"c8": "^7.13.0", "c8": "^7.13.0",
"dotenv-checker": "^1.1.5", "dotenv-checker": "^1.1.5",
"husky": "^8.0.0", "husky": "^8.0.0",
@@ -86,7 +87,9 @@
"jsdom": "^22.0.0", "jsdom": "^22.0.0",
"lint-staged": "^12.5.0", "lint-staged": "^12.5.0",
"mailhog": "^4.16.0", "mailhog": "^4.16.0",
"node-ical": "^0.16.1",
"prettier": "^2.8.6", "prettier": "^2.8.6",
"prismock": "^1.21.1",
"tsc-absolute": "^1.0.0", "tsc-absolute": "^1.0.0",
"typescript": "^4.9.4", "typescript": "^4.9.4",
"vitest": "^0.34.3", "vitest": "^0.34.3",
@@ -208,7 +208,7 @@ export const AppForm = ({
</Text> </Text>
<Text> <Text>
Tip : Go and change the logo of your {isTemplate ? "template" : "app"} by replacing{" "} Tip : Go and change the logo of your {isTemplate ? "template" : "app"} by replacing{" "}
{getAppDirPath(slug, isTemplate) + "/static/icon.svg"} {`${getAppDirPath(slug, isTemplate)}/static/icon.svg`}
</Text> </Text>
<Newline /> <Newline />
<Text bold underline color="blue"> <Text bold underline color="blue">
@@ -12,7 +12,7 @@ export function Message({
if (message.showInProgressIndicator) { if (message.showInProgressIndicator) {
const interval = setInterval(() => { const interval = setInterval(() => {
setProgressText((progressText) => { setProgressText((progressText) => {
return progressText.length > 3 ? "" : progressText + "."; return progressText.length > 3 ? "" : `${progressText}.`;
}); });
}, 1000); }, 1000);
return () => { return () => {
+9 -3
View File
@@ -1,7 +1,7 @@
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import { APP_STORE_PATH, TEMPLATES_PATH, IS_WINDOWS_PLATFORM} from "./constants"; import { APP_STORE_PATH, TEMPLATES_PATH, IS_WINDOWS_PLATFORM } from "./constants";
import execSync from "./utils/execSync"; import execSync from "./utils/execSync";
const slugify = (str: string) => { const slugify = (str: string) => {
@@ -70,7 +70,11 @@ export const BaseAppFork = {
const appDirPath = getAppDirPath(slug, isTemplate); const appDirPath = getAppDirPath(slug, isTemplate);
if (!editMode) { if (!editMode) {
await execSync(IS_WINDOWS_PLATFORM ? `mkdir ${appDirPath}` : `mkdir -p ${appDirPath}`); await execSync(IS_WINDOWS_PLATFORM ? `mkdir ${appDirPath}` : `mkdir -p ${appDirPath}`);
await execSync(IS_WINDOWS_PLATFORM ? `xcopy "${TEMPLATES_PATH}\\${template}\\*" "${appDirPath}" /e /i` : `cp -r ${TEMPLATES_PATH}/${template}/* ${appDirPath}`); await execSync(
IS_WINDOWS_PLATFORM
? `xcopy "${TEMPLATES_PATH}\\${template}\\*" "${appDirPath}" /e /i`
: `cp -r ${TEMPLATES_PATH}/${template}/* ${appDirPath}`
);
} else { } else {
if (!oldSlug) { if (!oldSlug) {
throw new Error("oldSlug is required when editMode is true"); throw new Error("oldSlug is required when editMode is true");
@@ -79,7 +83,9 @@ export const BaseAppFork = {
// We need to rename only if they are different // We need to rename only if they are different
const oldAppDirPath = getAppDirPath(oldSlug, isTemplate); const oldAppDirPath = getAppDirPath(oldSlug, isTemplate);
await execSync(IS_WINDOWS_PLATFORM ? `move ${oldAppDirPath} ${appDirPath}` : `mv ${oldAppDirPath} ${appDirPath}`); await execSync(
IS_WINDOWS_PLATFORM ? `move ${oldAppDirPath} ${appDirPath}` : `mv ${oldAppDirPath} ${appDirPath}`
);
} }
} }
updatePackageJson({ slug, appDirPath, appDescription: description }); updatePackageJson({ slug, appDirPath, appDescription: description });
+5 -2
View File
@@ -1,11 +1,13 @@
## App Contribution Guidelines ## App Contribution Guidelines
#### `DESCRIPTION.md` #### `DESCRIPTION.md`
1. images - include atleast 4 images (do we have a recommended size here?). Can show app in use and/or installation steps 1. images - include atleast 4 images (do we have a recommended size here?). Can show app in use and/or installation steps
2. add only file name for images, path not required. i.e. `1.jpeg`, not `/app-store/zohocalendar/1.jpeg` 2. add only file name for images, path not required. i.e. `1.jpeg`, not `/app-store/zohocalendar/1.jpeg`
3. description should include what the integration with Cal allows the user to do e.g. `Allows you to sync Cal bookings with your Zoho Calendar` 3. description should include what the integration with Cal allows the user to do e.g. `Allows you to sync Cal bookings with your Zoho Calendar`
#### `README.md` #### `README.md`
1. Include installation instructions and links to the app's website. 1. Include installation instructions and links to the app's website.
2. For url use `<baseUrl>/api/integrations`, rather than `<Cal.com>/api/integrations` 2. For url use `<baseUrl>/api/integrations`, rather than `<Cal.com>/api/integrations`
@@ -16,7 +18,8 @@
2. description here should not exceed 10 words (this is arbitrary, but should not be long otherwise it's truncated in the app store) 2. description here should not exceed 10 words (this is arbitrary, but should not be long otherwise it's truncated in the app store)
#### Others #### Others
1. Add API documentation links in comments for files `api`, `lib` and `types`
1. Add API documentation links in comments for files `api`, `lib` and `types`
2. Use [`AppDeclarativeHandler`](../types/AppHandler.d.ts) across all apps. Whatever isn't supported in it, support that. 2. Use [`AppDeclarativeHandler`](../types/AppHandler.d.ts) across all apps. Whatever isn't supported in it, support that.
3. README should be added in the respective app and can be linked in main README [like this](https://github.com/calcom/cal.com/pull/10429/files/155ac84537d12026f595551fe3542e810b029714#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R509) 3. README should be added in the respective app and can be linked in main README [like this](https://github.com/calcom/cal.com/pull/10429/files/155ac84537d12026f595551fe3542e810b029714#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R509)
4. Also, no env variables should be added by an app. They should be [added in `zod.ts`](https://github.com/calcom/cal.com/blob/main/packages/app-store/jitsivideo/zod.ts) and then they would be automatically available to be modified by the cal.com app admin. In local development you can open /settings/admin with the admin credentials (see [seed.ts](packages/prisma/seed.ts)) 4. Also, no env variables should be added by an app. They should be [added in `zod.ts`](https://github.com/calcom/cal.com/blob/main/packages/app-store/jitsivideo/zod.ts) and then they would be automatically available to be modified by the cal.com app admin. In local development you can open /settings/admin with the admin credentials (see [seed.ts](packages/prisma/seed.ts))
+2 -2
View File
@@ -44,7 +44,7 @@ export default function AppCard({
<div className="flex w-full flex-col gap-2 sm:flex-row sm:gap-0"> <div className="flex w-full flex-col gap-2 sm:flex-row sm:gap-0">
{/* Don't know why but w-[42px] isn't working, started happening when I started using next/dynamic */} {/* Don't know why but w-[42px] isn't working, started happening when I started using next/dynamic */}
<Link <Link
href={"/apps/" + app.slug} href={`/apps/${app.slug}`}
className={classNames(app?.isInstalled ? "mr-[11px]" : "mr-3", "h-auto w-10 rounded-sm")}> className={classNames(app?.isInstalled ? "mr-[11px]" : "mr-3", "h-auto w-10 rounded-sm")}>
<img <img
className={classNames( className={classNames(
@@ -116,7 +116,7 @@ export default function AppCard({
{app?.isInstalled && switchChecked && <hr className="border-subtle" />} {app?.isInstalled && switchChecked && <hr className="border-subtle" />}
{app?.isInstalled && switchChecked ? ( {app?.isInstalled && switchChecked ? (
app.isSetupAlready ? ( app.isSetupAlready === undefined || app.isSetupAlready ? (
<div className="relative p-4 pt-5 text-sm [&_input]:mb-0 [&_input]:leading-4"> <div className="relative p-4 pt-5 text-sm [&_input]:mb-0 [&_input]:leading-4">
<Link href={`/apps/${app.slug}/setup`} className="absolute right-4 top-4"> <Link href={`/apps/${app.slug}/setup`} className="absolute right-4 top-4">
<Settings className="text-default h-4 w-4" aria-hidden="true" /> <Settings className="text-default h-4 w-4" aria-hidden="true" />
+1 -1
View File
@@ -42,7 +42,7 @@ export const getCalendar = async (credential: CredentialPayload | null): Promise
log.warn(`calendar of type ${calendarType} is not implemented`); log.warn(`calendar of type ${calendarType} is not implemented`);
return null; return null;
} }
log.info("calendarApp", calendarApp.lib.CalendarService); log.info("Got calendarApp", calendarApp.lib.CalendarService);
const CalendarService = calendarApp.lib.CalendarService; const CalendarService = calendarApp.lib.CalendarService;
return new CalendarService(credential); return new CalendarService(credential);
}; };
@@ -64,7 +64,7 @@ function useAddAppMutation(_type: App["type"] | null, allOptions?: UseAddAppMuta
const stateStr = encodeURIComponent(JSON.stringify(state)); const stateStr = encodeURIComponent(JSON.stringify(state));
const searchParams = `?state=${stateStr}${teamId ? `&teamId=${teamId}` : ""}`; const searchParams = `?state=${stateStr}${teamId ? `&teamId=${teamId}` : ""}`;
const res = await fetch(`/api/integrations/${type}/add` + searchParams); const res = await fetch(`/api/integrations/${type}/add${searchParams}`);
if (!res.ok) { if (!res.ok) {
const errorBody = await res.json(); const errorBody = await res.json();
@@ -111,9 +111,14 @@ export const AlbyPaymentComponent = (props: IAlbyPaymentComponentProps) => {
)} )}
<Link target="_blank" href="https://getalby.com"> <Link target="_blank" href="https://getalby.com">
<div className="mt-4 flex items-center text-sm"> <div className="mt-4 flex items-center text-sm">
Powered by Powered by&nbsp;
<img title="Alby" src="/app-store/alby/icon.svg" alt="Alby" className="h-8 w-8" /> <img title="Alby" src="/app-store/alby/logo.svg" alt="Alby" className="h-8 dark:hidden" />
Alby <img
title="Alby"
src="/app-store/alby/logo-dark.svg"
alt="Alby"
className="hidden h-8 dark:block"
/>
</div> </div>
</Link> </Link>
</div> </div>
@@ -1,6 +1,7 @@
import type { GetServerSidePropsContext } from "next"; import type { GetServerSidePropsContext } from "next";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import prisma from "@calcom/prisma";
import { getAlbyKeys } from "../../lib/getAlbyKeys"; import { getAlbyKeys } from "../../lib/getAlbyKeys";
import type { IAlbySetupProps } from "./index"; import type { IAlbySetupProps } from "./index";
+14 -3
View File
@@ -120,6 +120,17 @@ function AlbySetupPage(props: IAlbySetupProps) {
return <div className="absolute z-50 flex h-screen w-full items-center bg-gray-200" />; return <div className="absolute z-50 flex h-screen w-full items-center bg-gray-200" />;
} }
const albyIcon = (
<>
<img className="h-16 w-16 dark:hidden" src="/api/app-store/alby/icon-borderless.svg" alt="Alby Icon" />
<img
className="hidden h-16 w-16 dark:block"
src="/api/app-store/alby/icon-borderless-dark.svg"
alt="Alby Icon"
/>
</>
);
return ( return (
<div className="bg-default flex h-screen"> <div className="bg-default flex h-screen">
{showContent ? ( {showContent ? (
@@ -138,13 +149,13 @@ function AlbySetupPage(props: IAlbySetupProps) {
}} }}
type="button" type="button"
onClick={connectWithAlby}> onClick={connectWithAlby}>
<img className="h-8 w-8" src="/api/app-store/alby/icon2.svg" alt="Alby Logo" /> {albyIcon}
<span className="mr-2">Connect with Alby</span> <span className="mr-2">Connect with Alby</span>
</button> </button>
</> </>
) : ( ) : (
<> <>
<img className="h-16 w-16" src="/api/app-store/alby/icon2.svg" alt="Alby Logo" /> {albyIcon}
<p>Alby Connected!</p> <p>Alby Connected!</p>
<Badge>Email: {props.email}</Badge> <Badge>Email: {props.email}</Badge>
<Badge>Lightning Address: {props.lightningAddress}</Badge> <Badge>Lightning Address: {props.lightningAddress}</Badge>
@@ -152,7 +163,7 @@ function AlbySetupPage(props: IAlbySetupProps) {
)} )}
{/* TODO: remove when invoices are generated using user identifier */} {/* TODO: remove when invoices are generated using user identifier */}
<div className="mt-4 rounded bg-blue-50 p-3 text-sm text-blue-700"> <div className="mt-4 rounded bg-blue-50 p-3 text-sm text-blue-700 dark:bg-blue-950 dark:text-blue-300">
<Info className="mb-0.5 inline-flex h-4 w-4" /> Your Alby lightning address will be used to <Info className="mb-0.5 inline-flex h-4 w-4" /> Your Alby lightning address will be used to
generate invoices. If you update your lightning address, please disconnect and setup the Alby generate invoices. If you update your lightning address, please disconnect and setup the Alby
app again. app again.
@@ -0,0 +1,16 @@
<svg width="490" height="489" viewBox="0 0 490 489" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M90.0776 181.767C97.3318 182.509 104.344 181.661 110.765 179.495L110.917 179.632L111.159 179.874C83.8531 210.92 64.5892 251.099 56.6382 295.564C51.0044 327.034 67.8907 357.293 95.8477 370.605C141.418 392.293 192.395 404.423 246.143 404.423C299.891 404.423 349.823 392.535 395.03 371.272C423.093 358.066 440.1 327.822 434.557 296.306C426.697 251.599 407.024 211.481 379.976 179.965C345.825 140.15 380.082 179.798 380.082 179.798C380.082 179.798 391.819 182.342 398.119 181.903C422.427 180.222 442.024 160.368 443.387 136.03C445.007 106.877 421.018 82.9028 391.865 84.5384C367.86 85.8863 348.127 105.014 346.082 128.973C345.446 136.439 346.506 143.618 348.914 150.145L348.521 150.539L348.294 150.766C318.822 129.033 283.671 116.221 245.552 116.221C207.433 116.221 172.04 129.124 142.493 151.008L142.266 150.781L141.903 150.418L141.191 149.706C143.508 143.224 144.507 136.106 143.826 128.715C141.66 104.878 121.972 85.9015 98.0739 84.5536C68.8599 82.918 44.8708 106.907 46.5065 136.091C47.8392 159.777 66.4671 179.344 90.0624 181.782L90.0776 181.767Z" fill="white" stroke="white" stroke-width="19.962"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M104.98 351.417C85.2161 342.012 73.7213 320.886 77.5681 299.335C85.6099 254.325 106.07 214.797 134.451 186.083C138.783 181.691 143.311 177.572 147.991 173.695C175.69 150.872 209.281 137.514 245.492 137.514C281.703 137.514 315.051 150.781 342.69 173.453C347.385 177.299 351.913 181.434 356.26 185.811C384.928 214.691 405.555 254.582 413.537 300.016C417.338 321.597 405.737 342.724 385.913 352.053C343.478 372.014 296.09 383.175 246.098 383.175C196.105 383.175 147.718 371.787 104.95 351.417H104.98Z" fill="#FFDF6F"/>
<path d="M95.5749 121.279L82.6111 134.243L113.446 165.078C118.822 161.988 123.35 157.566 126.561 152.265L95.5749 121.279Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.287 96.6087C375.448 96.2756 358.183 113.056 357.986 132.895C357.91 140.15 359.955 146.934 363.529 152.659L394.894 121.294L407.857 134.258L376.796 165.305C382.944 168.727 390.184 170.454 397.847 169.803C415.505 168.303 429.772 153.977 431.195 136.318C432.922 114.903 416.232 96.9571 395.287 96.6087ZM363.529 152.659L349.233 166.94C353.927 170.817 358.44 174.967 362.772 179.329L376.796 165.305C371.374 162.276 366.8 157.914 363.529 152.659ZM422.593 298.441C414.339 251.463 392.879 209.709 362.772 179.329L356.29 185.811C351.943 181.434 347.415 177.314 342.72 173.468L349.233 166.94C320.034 142.709 284.353 128.367 245.507 128.367C206.661 128.367 170.753 142.8 141.494 167.198L148.006 173.71C143.311 177.572 138.798 181.706 134.466 186.098L127.985 179.616C98.1648 209.815 76.8714 251.19 68.5419 297.745C63.9379 323.551 77.7498 348.615 101.042 359.701C145.007 380.631 194.212 392.353 246.128 392.353C298.044 392.353 346.219 380.874 389.85 360.353C413.219 349.342 427.152 324.293 422.593 298.441ZM382.036 343.754C340.812 363.169 294.742 374.013 246.128 374.013C197.514 374.013 150.489 362.942 108.917 343.148C92.6976 335.424 83.5048 318.235 86.5943 300.97C94.3635 257.505 113.991 219.81 140.948 192.565L154.533 180.237C180.642 158.989 212.052 146.692 245.507 146.692C278.961 146.692 310.129 158.883 336.193 179.98L349.808 192.293C377.038 219.689 396.832 257.732 404.541 301.606C407.585 318.917 398.316 336.106 382.036 343.754ZM126.576 152.28C123.365 157.581 118.837 161.988 113.461 165.093L127.985 179.616C132.316 175.225 136.814 171.09 141.494 167.198L126.576 152.28ZM126.576 152.28C130.059 146.541 132.013 139.771 131.877 132.562C131.483 112.495 114.536 96.215 94.4695 96.6087C73.5548 97.0328 56.9411 114.949 58.6676 136.318C60.1063 154.067 74.5089 168.425 92.2584 169.818C100.012 170.424 107.297 168.606 113.461 165.093L82.6264 134.258L95.5902 121.294L126.576 152.28Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M407.857 134.258L376.796 165.305C371.374 162.276 366.8 157.914 363.529 152.659L394.894 121.295L407.857 134.258Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M362.772 179.329L356.29 185.811C351.943 181.434 347.415 177.315 342.72 173.468L349.232 166.94C353.927 170.817 358.44 174.967 362.772 179.329Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M148.006 173.71C143.311 177.572 138.798 181.706 134.467 186.098L127.985 179.616C132.316 175.225 136.814 171.09 141.494 167.198L148.006 173.71Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M126.576 152.28C123.366 157.581 118.837 161.988 113.461 165.093L82.6265 134.258L95.5903 121.295L126.576 152.28Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M407.857 134.243L376.796 165.29C371.374 162.261 366.8 157.899 363.529 152.644L394.894 121.279L407.857 134.243Z" fill="black"/>
<path d="M349.232 166.925L342.705 173.453C347.4 177.299 351.928 181.434 356.275 185.811L362.757 179.329C358.425 174.952 353.912 170.817 349.232 166.94V166.925Z" fill="black"/>
<path d="M141.478 167.183C136.799 171.075 132.301 175.225 127.969 179.601L134.451 186.083C138.783 181.691 143.311 177.572 147.99 173.695L141.478 167.183Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M140.873 329.064C124.971 322.582 115.536 305.665 121.048 289.4C138.041 239.241 187.624 202.924 246.143 202.924C304.662 202.924 354.245 239.226 371.253 289.4C376.766 305.665 367.33 322.597 351.429 329.064C318.943 342.3 283.399 349.585 246.158 349.585C208.918 349.585 173.373 342.3 140.888 329.064H140.873Z" fill="black"/>
<path d="M288.321 305.59C305.2 305.59 318.883 294.646 318.883 281.146C318.883 267.646 305.2 256.703 288.321 256.703C271.442 256.703 257.759 267.646 257.759 281.146C257.759 294.646 271.442 305.59 288.321 305.59Z" fill="white"/>
<path d="M200.845 305.605C217.724 305.605 231.407 294.661 231.407 281.161C231.407 267.661 217.724 256.718 200.845 256.718C183.966 256.718 170.283 267.661 170.283 281.161C170.283 294.661 183.966 305.605 200.845 305.605Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

@@ -0,0 +1,11 @@
<svg width="490" height="489" viewBox="0 0 490 489" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="36.675" cy="36.675" r="36.675" transform="matrix(-1 0 0 1 131.308 101.468)" fill="black"/>
<path d="M88.52 132.641L156.98 201.101" stroke="black" stroke-width="18.3375"/>
<circle cx="394.145" cy="138.143" r="36.675" fill="black"/>
<path d="M400.869 132.641L332.409 201.101" stroke="black" stroke-width="18.3375"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M105.043 356.993C85.276 347.583 73.7721 326.451 77.6256 304.901C94.165 212.406 163.093 143.033 245.611 143.033C328.33 143.033 397.391 212.743 413.716 305.573C417.513 327.163 405.915 348.285 386.081 357.618C343.64 377.591 296.235 388.755 246.222 388.755C195.69 388.755 147.82 377.358 105.043 356.993Z" fill="#FFDF6F"/>
<path d="M413.716 305.573L422.746 303.985L413.716 305.573ZM386.081 357.618L382.177 349.322L386.081 357.618ZM86.6512 306.515C102.633 217.14 168.694 152.201 245.611 152.201V133.864C157.491 133.864 85.6973 207.672 68.6 303.287L86.6512 306.515ZM245.611 152.201C322.713 152.201 388.911 217.457 404.686 307.161L422.746 303.985C405.872 208.028 333.946 133.864 245.611 133.864V152.201ZM382.177 349.322C340.932 368.732 294.857 379.586 246.222 379.586V397.924C297.613 397.924 346.348 386.449 389.985 365.914L382.177 349.322ZM246.222 379.586C197.082 379.586 150.556 368.505 108.984 348.714L101.102 365.272C145.084 386.21 194.298 397.924 246.222 397.924V379.586ZM404.686 307.161C407.73 324.47 398.462 341.659 382.177 349.322L389.985 365.914C413.369 354.91 427.296 329.855 422.746 303.985L404.686 307.161ZM68.6 303.287C63.9824 329.11 77.7983 354.178 101.102 365.272L108.984 348.714C92.7538 340.988 83.5618 323.792 86.6512 306.515L68.6 303.287Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M140.311 333.998C124.4 327.518 114.962 310.589 120.475 294.317C137.477 244.138 187.075 207.825 245.611 207.825C304.148 207.825 353.745 244.138 370.748 294.317C376.261 310.589 366.823 327.518 350.912 333.998C318.414 347.233 282.864 354.525 245.611 354.525C208.358 354.525 172.808 347.233 140.311 333.998Z" fill="black"/>
<ellipse cx="287.788" cy="286.065" rx="30.5625" ry="24.45" fill="white"/>
<ellipse cx="200.295" cy="286.08" rx="30.5625" ry="24.45" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

-11
View File
@@ -1,11 +0,0 @@
<svg width="554" height="554" viewBox="0 0 554 554" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M127.7 202.4C107.431 202.4 90.9999 185.969 90.9999 165.7C90.9999 145.431 107.431 129 127.7 129C147.969 129 164.4 145.431 164.4 165.7C164.4 185.969 147.969 202.4 127.7 202.4Z" fill="black"/>
<path d="M121.6 160.2L190.1 228.7" stroke="black" stroke-width="18.3"/>
<path d="M427.2 202.4C447.469 202.4 463.9 185.969 463.9 165.7C463.9 145.431 447.469 129 427.2 129C406.931 129 390.5 145.431 390.5 165.7C390.5 185.969 406.931 202.4 427.2 202.4Z" fill="black"/>
<path d="M434 160.2L365.5 228.7" stroke="black" stroke-width="18.3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M138.1 384.6C128.451 380.122 120.543 372.597 115.592 363.182C110.641 353.768 108.922 342.987 110.7 332.5C127.3 240 196.2 170.6 278.7 170.6C361.4 170.6 430.5 240.3 446.8 333.2C448.539 343.695 446.779 354.47 441.792 363.867C436.805 373.263 428.866 380.759 419.2 385.2C375.441 405.799 327.664 416.454 279.3 416.4C228.8 416.4 180.9 405 138.1 384.6Z" fill="#FFDF6F"/>
<path d="M119.8 334.2C135.8 244.7 201.8 179.8 278.8 179.8V161.5C190.6 161.5 118.8 235.3 101.7 330.9L119.7 334.1L119.8 334.2ZM278.8 179.8C355.8 179.8 422 245.1 437.8 334.8L455.8 331.6C439 235.6 367 161.5 278.8 161.5V179.8ZM415.3 376.9C372.76 396.917 326.314 407.265 279.3 407.2V425.5C330.7 425.5 379.4 414 423.1 393.5L415.3 376.9ZM279.3 407.2C230.2 407.2 183.7 396.1 142.1 376.3L134.2 392.9C178.2 413.9 227.4 425.5 279.3 425.5V407.2ZM437.8 334.8C440.8 352.1 431.6 369.3 415.3 376.9L423.1 393.5C446.5 382.5 460.4 357.5 455.8 331.5L437.8 334.8ZM101.7 330.8C99.5558 343.269 101.577 356.098 107.451 367.303C113.325 378.509 122.725 387.47 134.2 392.8L142.1 376.3C134.267 372.688 127.84 366.599 123.81 358.973C119.78 351.347 118.371 342.606 119.8 334.1L101.6 330.9L101.7 330.8Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M173.4 361.6C157.5 355.1 148.1 338.2 153.6 321.9C170.6 271.7 220.2 235.4 278.7 235.4C337.2 235.4 386.8 271.7 403.8 321.9C409.4 338.2 399.9 355.1 384 361.6C350.559 375.19 314.796 382.153 278.7 382.1C241.5 382.1 205.9 374.8 173.4 361.6Z" fill="black"/>
<path d="M320.9 338.1C337.8 338.1 351.5 327.176 351.5 313.7C351.5 300.224 337.8 289.3 320.9 289.3C304 289.3 290.3 300.224 290.3 313.7C290.3 327.176 304 338.1 320.9 338.1Z" fill="white"/>
<path d="M233.4 338.1C250.3 338.1 264 327.176 264 313.7C264 300.224 250.3 289.3 233.4 289.3C216.5 289.3 202.8 300.224 202.8 313.7C202.8 327.176 216.5 338.1 233.4 338.1Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

@@ -0,0 +1,17 @@
<svg width="1211" height="525" viewBox="0 0 1211 525" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M90.0776 187.767C97.3318 188.509 104.344 187.661 110.765 185.495L110.917 185.632L111.159 185.874C83.8531 216.92 64.5892 257.099 56.6382 301.564C51.0044 333.034 67.8907 363.293 95.8477 376.605C141.418 398.293 192.395 410.423 246.143 410.423C299.891 410.423 349.823 398.535 395.03 377.272C423.093 364.066 440.1 333.822 434.557 302.306C426.697 257.599 407.024 217.481 379.976 185.965C345.825 146.15 380.082 185.798 380.082 185.798C380.082 185.798 391.819 188.342 398.119 187.903C422.427 186.222 442.024 166.368 443.387 142.03C445.007 112.877 421.018 88.9028 391.865 90.5384C367.86 91.8863 348.127 111.014 346.082 134.973C345.446 142.439 346.506 149.618 348.914 156.145L348.521 156.539L348.294 156.766C318.822 135.033 283.671 122.221 245.552 122.221C207.433 122.221 172.04 135.124 142.493 157.008L142.266 156.781L141.903 156.418L141.191 155.706C143.508 149.224 144.507 142.106 143.826 134.715C141.66 110.878 121.972 91.9015 98.0739 90.5536C68.8599 88.918 44.8708 112.907 46.5065 142.091C47.8392 165.777 66.4671 185.344 90.0624 187.782L90.0776 187.767Z" fill="white" stroke="white" stroke-width="19.962"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M104.98 357.417C85.2161 348.012 73.7213 326.886 77.5681 305.335C85.6099 260.325 106.07 220.797 134.451 192.083C138.783 187.691 143.311 183.572 147.991 179.695C175.69 156.872 209.281 143.514 245.492 143.514C281.703 143.514 315.051 156.781 342.69 179.453C347.385 183.299 351.913 187.434 356.26 191.811C384.928 220.691 405.555 260.582 413.537 306.016C417.338 327.597 405.737 348.724 385.913 358.053C343.478 378.014 296.09 389.175 246.098 389.175C196.105 389.175 147.718 377.787 104.95 357.417H104.98Z" fill="#FFDF6F"/>
<path d="M95.5749 127.279L82.6111 140.243L113.446 171.078C118.822 167.988 123.35 163.566 126.561 158.265L95.5749 127.279Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M395.287 102.609C375.448 102.276 358.183 119.056 357.986 138.895C357.91 146.15 359.955 152.934 363.529 158.659L394.894 127.294L407.857 140.258L376.796 171.305C382.944 174.727 390.184 176.454 397.847 175.803C415.505 174.303 429.772 159.977 431.195 142.318C432.922 120.903 416.232 102.957 395.287 102.609ZM363.529 158.659L349.233 172.94C353.927 176.817 358.44 180.967 362.772 185.329L376.796 171.305C371.374 168.276 366.8 163.914 363.529 158.659ZM422.593 304.441C414.339 257.463 392.879 215.709 362.772 185.329L356.29 191.811C351.943 187.434 347.415 183.314 342.72 179.468L349.233 172.94C320.034 148.709 284.353 134.367 245.507 134.367C206.661 134.367 170.753 148.8 141.494 173.198L148.006 179.71C143.311 183.572 138.798 187.706 134.466 192.098L127.985 185.616C98.1648 215.815 76.8714 257.19 68.5419 303.745C63.9379 329.551 77.7498 354.615 101.042 365.701C145.007 386.631 194.212 398.353 246.128 398.353C298.044 398.353 346.219 386.874 389.85 366.353C413.219 355.342 427.152 330.293 422.593 304.441ZM382.036 349.754C340.812 369.169 294.742 380.013 246.128 380.013C197.514 380.013 150.489 368.942 108.917 349.148C92.6976 341.424 83.5048 324.235 86.5943 306.97C94.3635 263.505 113.991 225.81 140.948 198.565L154.533 186.237C180.642 164.989 212.052 152.692 245.507 152.692C278.961 152.692 310.129 164.883 336.193 185.98L349.808 198.293C377.038 225.689 396.832 263.732 404.541 307.606C407.585 324.917 398.316 342.106 382.036 349.754ZM126.576 158.28C123.365 163.581 118.837 167.988 113.461 171.093L127.985 185.616C132.316 181.225 136.814 177.09 141.494 173.198L126.576 158.28ZM126.576 158.28C130.059 152.541 132.013 145.771 131.877 138.562C131.483 118.495 114.536 102.215 94.4695 102.609C73.5548 103.033 56.9411 120.949 58.6676 142.318C60.1063 160.067 74.5089 174.425 92.2584 175.818C100.012 176.424 107.297 174.606 113.461 171.093L82.6264 140.258L95.5902 127.294L126.576 158.28Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M407.857 140.258L376.796 171.305C371.374 168.276 366.8 163.914 363.529 158.659L394.894 127.295L407.857 140.258Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M362.772 185.329L356.29 191.811C351.943 187.434 347.415 183.315 342.72 179.468L349.232 172.94C353.927 176.817 358.44 180.967 362.772 185.329Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M148.006 179.71C143.311 183.572 138.798 187.706 134.467 192.098L127.985 185.616C132.316 181.225 136.814 177.09 141.494 173.198L148.006 179.71Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M126.576 158.28C123.366 163.581 118.837 167.988 113.461 171.093L82.6265 140.258L95.5903 127.295L126.576 158.28Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M407.857 140.243L376.796 171.29C371.374 168.261 366.8 163.899 363.529 158.644L394.894 127.279L407.857 140.243Z" fill="black"/>
<path d="M349.232 172.925L342.705 179.453C347.4 183.299 351.928 187.434 356.275 191.811L362.757 185.329C358.425 180.952 353.912 176.817 349.232 172.94V172.925Z" fill="black"/>
<path d="M141.478 173.183C136.799 177.075 132.301 181.225 127.969 185.601L134.451 192.083C138.783 187.691 143.311 183.572 147.99 179.695L141.478 173.183Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M140.873 335.064C124.971 328.582 115.536 311.665 121.048 295.4C138.041 245.241 187.624 208.924 246.143 208.924C304.662 208.924 354.245 245.226 371.253 295.4C376.766 311.665 367.33 328.597 351.429 335.064C318.943 348.3 283.399 355.585 246.158 355.585C208.918 355.585 173.373 348.3 140.888 335.064H140.873Z" fill="black"/>
<path d="M288.321 311.59C305.2 311.59 318.883 300.646 318.883 287.146C318.883 273.646 305.2 262.703 288.321 262.703C271.442 262.703 257.759 273.646 257.759 287.146C257.759 300.646 271.442 311.59 288.321 311.59Z" fill="white"/>
<path d="M200.845 311.605C217.724 311.605 231.407 300.661 231.407 287.161C231.407 273.661 217.724 262.718 200.845 262.718C183.966 262.718 170.283 273.661 170.283 287.161C170.283 300.661 183.966 311.605 200.845 311.605Z" fill="white"/>
<path d="M674.375 263.384L652.621 204.2L631.826 263.384H674.375ZM624.468 134.459H682.693L763.95 349.441L706.686 355.199L691.01 309.132H615.831L600.795 352H542.891L624.468 134.459ZM838.15 352H779.926V129.661L838.15 126.142V352ZM899.496 352H870.064V129.661L928.288 126.142V322.888L899.496 352ZM909.413 257.306L893.098 219.876C896.937 215.184 901.842 210.705 907.814 206.44C913.999 201.961 920.823 198.335 928.288 195.563C935.753 192.79 943.43 191.404 951.322 191.404C966.677 191.404 980.327 194.283 992.27 200.042C1004.21 205.8 1013.6 214.651 1020.42 226.594C1027.46 238.538 1030.98 253.787 1030.98 272.342C1030.98 290.683 1027.46 306.039 1020.42 318.409C1013.6 330.779 1004 340.057 991.631 346.242C979.474 352.427 965.185 355.519 948.762 355.519C942.364 355.519 935.966 354.559 929.568 352.64C923.383 350.72 917.198 347.734 911.013 343.682C905.041 339.417 899.069 333.872 893.098 327.047L909.413 292.816C915.598 298.575 921.676 303.053 927.648 306.252C933.62 309.238 939.378 310.731 944.923 310.731C949.829 310.731 954.201 309.238 958.04 306.252C961.879 303.267 964.971 298.895 967.317 293.136C969.663 287.378 970.836 280.553 970.836 272.662C970.836 264.77 969.663 258.159 967.317 252.827C965.185 247.282 961.985 243.123 957.72 240.351C953.668 237.578 948.549 236.192 942.364 236.192C937.246 236.192 932.02 238.111 926.688 241.95C921.357 245.789 915.598 250.908 909.413 257.306ZM1088.57 352.64L1089.85 349.121L1034.18 206.44L1087.93 191.084L1119.6 284.498L1149.35 196.842H1207.25L1139.11 370.235C1135.91 378.553 1130.69 386.231 1123.44 393.269C1116.19 400.307 1107.76 406.279 1098.16 411.184C1088.57 416.089 1078.65 419.715 1068.41 422.061L1048.9 376.953C1054.02 374.82 1059.35 372.474 1064.89 369.915C1070.65 367.356 1075.77 364.583 1080.25 361.597C1084.73 358.612 1087.5 355.626 1088.57 352.64Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

+12
View File
@@ -0,0 +1,12 @@
<svg width="1211" height="525" viewBox="0 0 1211 525" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="36.675" cy="36.675" r="36.675" transform="matrix(-1 0 0 1 131.308 101.468)" fill="black"/>
<path d="M88.52 132.641L156.98 201.101" stroke="black" stroke-width="18.3375"/>
<circle cx="394.145" cy="138.143" r="36.675" fill="black"/>
<path d="M400.869 132.641L332.409 201.101" stroke="black" stroke-width="18.3375"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M105.043 356.993C85.276 347.583 73.7721 326.451 77.6256 304.901C94.165 212.406 163.093 143.033 245.611 143.033C328.33 143.033 397.391 212.743 413.716 305.573C417.513 327.163 405.915 348.285 386.081 357.618C343.64 377.591 296.235 388.755 246.222 388.755C195.69 388.755 147.82 377.358 105.043 356.993Z" fill="#FFDF6F"/>
<path d="M413.716 305.573L422.746 303.985L413.716 305.573ZM386.081 357.618L382.177 349.322L386.081 357.618ZM86.6512 306.515C102.633 217.14 168.694 152.201 245.611 152.201V133.864C157.491 133.864 85.6973 207.672 68.6 303.287L86.6512 306.515ZM245.611 152.201C322.713 152.201 388.911 217.457 404.686 307.161L422.746 303.985C405.872 208.028 333.946 133.864 245.611 133.864V152.201ZM382.177 349.322C340.932 368.732 294.857 379.586 246.222 379.586V397.924C297.613 397.924 346.348 386.449 389.985 365.914L382.177 349.322ZM246.222 379.586C197.082 379.586 150.556 368.505 108.984 348.714L101.102 365.272C145.084 386.21 194.298 397.924 246.222 397.924V379.586ZM404.686 307.161C407.73 324.47 398.462 341.659 382.177 349.322L389.985 365.914C413.369 354.91 427.296 329.855 422.746 303.985L404.686 307.161ZM68.6 303.287C63.9824 329.11 77.7983 354.178 101.102 365.272L108.984 348.714C92.7538 340.988 83.5618 323.792 86.6512 306.515L68.6 303.287Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M140.311 333.998C124.4 327.518 114.962 310.589 120.475 294.317C137.477 244.138 187.075 207.825 245.611 207.825C304.148 207.825 353.745 244.138 370.748 294.317C376.261 310.589 366.823 327.518 350.912 333.998C318.414 347.233 282.864 354.525 245.611 354.525C208.358 354.525 172.808 347.233 140.311 333.998Z" fill="black"/>
<ellipse cx="287.788" cy="286.065" rx="30.5625" ry="24.45" fill="white"/>
<ellipse cx="200.295" cy="286.08" rx="30.5625" ry="24.45" fill="white"/>
<path d="M674.32 263.36L652.56 204.16L631.76 263.36H674.32ZM624.4 134.4H682.64L763.92 349.44L706.64 355.2L690.96 309.12H615.76L600.72 352H542.8L624.4 134.4ZM838.14 352H779.9V129.6L838.14 126.08V352ZM899.503 352H870.063V129.6L928.303 126.08V322.88L899.503 352ZM909.423 257.28L893.103 219.84C896.943 215.147 901.849 210.667 907.823 206.4C914.009 201.92 920.836 198.293 928.303 195.52C935.769 192.747 943.449 191.36 951.343 191.36C966.703 191.36 980.356 194.24 992.303 200C1004.25 205.76 1013.64 214.613 1020.46 226.56C1027.5 238.507 1031.02 253.76 1031.02 272.32C1031.02 290.667 1027.5 306.027 1020.46 318.4C1013.64 330.773 1004.04 340.053 991.663 346.24C979.503 352.427 965.209 355.52 948.783 355.52C942.383 355.52 935.983 354.56 929.583 352.64C923.396 350.72 917.209 347.733 911.023 343.68C905.049 339.413 899.076 333.867 893.103 327.04L909.423 292.8C915.609 298.56 921.689 303.04 927.663 306.24C933.636 309.227 939.396 310.72 944.943 310.72C949.849 310.72 954.223 309.227 958.063 306.24C961.903 303.253 964.996 298.88 967.343 293.12C969.689 287.36 970.863 280.533 970.863 272.64C970.863 264.747 969.689 258.133 967.343 252.8C965.209 247.253 962.009 243.093 957.743 240.32C953.689 237.547 948.569 236.16 942.383 236.16C937.263 236.16 932.036 238.08 926.703 241.92C921.369 245.76 915.609 250.88 909.423 257.28ZM1088.62 352.64L1089.9 349.12L1034.22 206.4L1087.98 191.04L1119.66 284.48L1149.42 196.8H1207.34L1139.19 370.24C1135.98 378.56 1130.76 386.24 1123.5 393.28C1116.25 400.32 1107.83 406.293 1098.22 411.2C1088.62 416.107 1078.7 419.733 1068.46 422.08L1048.94 376.96C1054.06 374.827 1059.4 372.48 1064.94 369.92C1070.7 367.36 1075.82 364.587 1080.3 361.6C1084.78 358.613 1087.56 355.627 1088.62 352.64Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -11,6 +11,7 @@ import { appKeysSchema as giphy_zod_ts } from "./giphy/zod";
import { appKeysSchema as googlecalendar_zod_ts } from "./googlecalendar/zod"; import { appKeysSchema as googlecalendar_zod_ts } from "./googlecalendar/zod";
import { appKeysSchema as gtm_zod_ts } from "./gtm/zod"; import { appKeysSchema as gtm_zod_ts } from "./gtm/zod";
import { appKeysSchema as hubspot_zod_ts } from "./hubspot/zod"; import { appKeysSchema as hubspot_zod_ts } from "./hubspot/zod";
import { appKeysSchema as intercom_zod_ts } from "./intercom/zod";
import { appKeysSchema as jitsivideo_zod_ts } from "./jitsivideo/zod"; import { appKeysSchema as jitsivideo_zod_ts } from "./jitsivideo/zod";
import { appKeysSchema as larkcalendar_zod_ts } from "./larkcalendar/zod"; import { appKeysSchema as larkcalendar_zod_ts } from "./larkcalendar/zod";
import { appKeysSchema as make_zod_ts } from "./make/zod"; import { appKeysSchema as make_zod_ts } from "./make/zod";
@@ -45,6 +46,7 @@ export const appKeysSchemas = {
googlecalendar: googlecalendar_zod_ts, googlecalendar: googlecalendar_zod_ts,
gtm: gtm_zod_ts, gtm: gtm_zod_ts,
hubspot: hubspot_zod_ts, hubspot: hubspot_zod_ts,
intercom: intercom_zod_ts,
jitsivideo: jitsivideo_zod_ts, jitsivideo: jitsivideo_zod_ts,
larkcalendar: larkcalendar_zod_ts, larkcalendar: larkcalendar_zod_ts,
make: make_zod_ts, make: make_zod_ts,
@@ -28,6 +28,7 @@ import { metadata as googlevideo__metadata_ts } from "./googlevideo/_metadata";
import gtm_config_json from "./gtm/config.json"; import gtm_config_json from "./gtm/config.json";
import { metadata as hubspot__metadata_ts } from "./hubspot/_metadata"; import { metadata as hubspot__metadata_ts } from "./hubspot/_metadata";
import { metadata as huddle01video__metadata_ts } from "./huddle01video/_metadata"; import { metadata as huddle01video__metadata_ts } from "./huddle01video/_metadata";
import intercom_config_json from "./intercom/config.json";
import { metadata as jitsivideo__metadata_ts } from "./jitsivideo/_metadata"; import { metadata as jitsivideo__metadata_ts } from "./jitsivideo/_metadata";
import { metadata as larkcalendar__metadata_ts } from "./larkcalendar/_metadata"; import { metadata as larkcalendar__metadata_ts } from "./larkcalendar/_metadata";
import make_config_json from "./make/config.json"; import make_config_json from "./make/config.json";
@@ -101,6 +102,7 @@ export const appStoreMetadata = {
gtm: gtm_config_json, gtm: gtm_config_json,
hubspot: hubspot__metadata_ts, hubspot: hubspot__metadata_ts,
huddle01video: huddle01video__metadata_ts, huddle01video: huddle01video__metadata_ts,
intercom: intercom_config_json,
jitsivideo: jitsivideo__metadata_ts, jitsivideo: jitsivideo__metadata_ts,
larkcalendar: larkcalendar__metadata_ts, larkcalendar: larkcalendar__metadata_ts,
make: make_config_json, make: make_config_json,
@@ -11,6 +11,7 @@ import { appDataSchema as giphy_zod_ts } from "./giphy/zod";
import { appDataSchema as googlecalendar_zod_ts } from "./googlecalendar/zod"; import { appDataSchema as googlecalendar_zod_ts } from "./googlecalendar/zod";
import { appDataSchema as gtm_zod_ts } from "./gtm/zod"; import { appDataSchema as gtm_zod_ts } from "./gtm/zod";
import { appDataSchema as hubspot_zod_ts } from "./hubspot/zod"; import { appDataSchema as hubspot_zod_ts } from "./hubspot/zod";
import { appDataSchema as intercom_zod_ts } from "./intercom/zod";
import { appDataSchema as jitsivideo_zod_ts } from "./jitsivideo/zod"; import { appDataSchema as jitsivideo_zod_ts } from "./jitsivideo/zod";
import { appDataSchema as larkcalendar_zod_ts } from "./larkcalendar/zod"; import { appDataSchema as larkcalendar_zod_ts } from "./larkcalendar/zod";
import { appDataSchema as make_zod_ts } from "./make/zod"; import { appDataSchema as make_zod_ts } from "./make/zod";
@@ -45,6 +46,7 @@ export const appDataSchemas = {
googlecalendar: googlecalendar_zod_ts, googlecalendar: googlecalendar_zod_ts,
gtm: gtm_zod_ts, gtm: gtm_zod_ts,
hubspot: hubspot_zod_ts, hubspot: hubspot_zod_ts,
intercom: intercom_zod_ts,
jitsivideo: jitsivideo_zod_ts, jitsivideo: jitsivideo_zod_ts,
larkcalendar: larkcalendar_zod_ts, larkcalendar: larkcalendar_zod_ts,
make: make_zod_ts, make: make_zod_ts,
@@ -28,6 +28,7 @@ export const apiHandlers = {
gtm: import("./gtm/api"), gtm: import("./gtm/api"),
hubspot: import("./hubspot/api"), hubspot: import("./hubspot/api"),
huddle01video: import("./huddle01video/api"), huddle01video: import("./huddle01video/api"),
intercom: import("./intercom/api"),
jitsivideo: import("./jitsivideo/api"), jitsivideo: import("./jitsivideo/api"),
larkcalendar: import("./larkcalendar/api"), larkcalendar: import("./larkcalendar/api"),
make: import("./make/api"), make: import("./make/api"),
+1 -3
View File
@@ -24,9 +24,7 @@ async function handler(req: NextApiRequest) {
client_id, client_id,
}; };
const query = stringify(params); const query = stringify(params);
const url = `https://launchpad.37signals.com/authorization/new?${query}&redirect_uri=${ const url = `https://launchpad.37signals.com/authorization/new?${query}&redirect_uri=${WEBAPP_URL}/api/integrations/basecamp3/callback`;
WEBAPP_URL + "/api/integrations/basecamp3/callback"
}`;
return { url }; return { url };
} }
+1 -1
View File
@@ -11,7 +11,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const { code } = req.query; const { code } = req.query;
const { client_id, client_secret, user_agent } = await getAppKeysFromSlug("basecamp3"); const { client_id, client_secret, user_agent } = await getAppKeysFromSlug("basecamp3");
const redirectUri = WEBAPP_URL + "/api/integrations/basecamp3/callback"; const redirectUri = `${WEBAPP_URL}/api/integrations/basecamp3/callback`;
const params = new URLSearchParams({ const params = new URLSearchParams({
type: "web_server", type: "web_server",
@@ -105,14 +105,9 @@ export default class BasecampCalendarService implements Calendar {
minute: "numeric", minute: "numeric",
}); });
const baseString = `<div>Event title: ${event.title}<br/>Date and time: ${date}, ${startTime} - ${endTime} ${timeZone}<br/>View on Cal.com: <a target="_blank" rel="noreferrer" class="autolinked" data-behavior="truncate" href="https://app.cal.com/booking/${event.uid}">https://app.cal.com/booking/${event.uid}</a> `; const baseString = `<div>Event title: ${event.title}<br/>Date and time: ${date}, ${startTime} - ${endTime} ${timeZone}<br/>View on Cal.com: <a target="_blank" rel="noreferrer" class="autolinked" data-behavior="truncate" href="https://app.cal.com/booking/${event.uid}">https://app.cal.com/booking/${event.uid}</a> `;
const guestString = const guestString = `<br/>Guests: ${event.attendees.reduce((acc, attendee) => {
"<br/>Guests: " + return `${acc}<br/><a target=\"_blank\" rel=\"noreferrer\" class=\"autolinked\" data-behavior=\"truncate\" href=\"mailto:${attendee.email}\">${attendee.email}</a>`;
event.attendees.reduce((acc, attendee) => { }, "")}`;
return (
acc +
`<br/><a target=\"_blank\" rel=\"noreferrer\" class=\"autolinked\" data-behavior=\"truncate\" href=\"mailto:${attendee.email}\">${attendee.email}</a>`
);
}, "");
const videoString = event.videoCallData const videoString = event.videoCallData
? `<br/>Join on video: ${event.videoCallData.url}</div>` ? `<br/>Join on video: ${event.videoCallData.url}</div>`
+1 -1
View File
@@ -9,4 +9,4 @@ Example questions:
- Send an email with the title: What's my schedule? - Send an email with the title: What's my schedule?
- Forward an email from someone looking to meet you - Forward an email from someone looking to meet you
- - Ask to schedule a call with someone
+1 -1
View File
@@ -3,7 +3,7 @@
"name": "Cal.ai", "name": "Cal.ai",
"slug": "cal-ai", "slug": "cal-ai",
"type": "cal-ai_automation", "type": "cal-ai_automation",
"logo": "icon.svg", "logo": "icon.png",
"url": "https://cal.ai", "url": "https://cal.ai",
"variant": "automation", "variant": "automation",
"categories": ["automation"], "categories": ["automation"],
Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

-461
View File
@@ -1,461 +0,0 @@
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2598_16651)">
<rect width="512" height="512" rx="116" fill="url(#paint0_linear_2598_16651)"/>
<g opacity="0.8" filter="url(#filter0_f_2598_16651)">
<g filter="url(#filter1_f_2598_16651)">
<path d="M459.752 -356.036C371.918 -541.357 282.211 -564.038 262.704 -534.284C11.9602 -151.825 113.607 182.645 160.925 501.689C163.832 817.711 296.855 745.291 323.502 677.669C371.853 554.968 594.826 -71.0432 459.752 -356.036Z" fill="url(#paint1_linear_2598_16651)"/>
</g>
<g filter="url(#filter2_f_2598_16651)">
<path d="M386.061 10.9878C291.362 -138.674 274.942 -157.222 266.009 -135.187C200.258 53.5336 83.5663 451.975 142.806 535.978C272.543 715.699 304.478 714.254 327.559 673.264C350.64 632.275 504.435 198.065 386.061 10.9878Z" fill="url(#paint2_linear_2598_16651)"/>
</g>
<g filter="url(#filter3_f_2598_16651)">
<path d="M352.81 181.717C284.932 74.4428 273.162 61.1484 266.759 76.9425C219.631 212.213 135.989 497.806 178.451 558.016C271.443 686.836 294.333 685.8 310.877 656.42C327.421 627.04 437.657 315.809 352.81 181.717Z" fill="url(#paint3_linear_2598_16651)"/>
</g>
<g filter="url(#filter4_f_2598_16651)">
<path d="M224.077 683.611C109.625 539.5 -152.5 -24.9997 109.625 -175.07C121.524 -61.6035 222.881 395.531 261.837 585.217C282.871 420.872 380.08 89.0844 388.862 11.4926C388.862 11.4926 395.384 -3.03499 403.845 16.7034C693.501 -113 436.5 519.5 302.69 659.209C291.265 671.138 282.325 677.145 275.536 678.084C271.094 706.093 248.08 699.83 224.077 683.611Z" fill="url(#paint4_radial_2598_16651)"/>
</g>
</g>
<g filter="url(#filter5_d_2598_16651)">
<circle cx="87" cy="444" r="1" fill="white" fill-opacity="0.78" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter6_d_2598_16651)">
<circle cx="106" cy="430" r="1" fill="white" fill-opacity="0.78" shape-rendering="crispEdges"/>
</g>
<circle cx="85" cy="417" r="3" fill="white"/>
<circle cx="162" cy="397" r="2" fill="white"/>
<g filter="url(#filter7_f_2598_16651)">
<circle cx="115.786" cy="262.889" r="1.58974" fill="#D9D9D9"/>
</g>
<g filter="url(#filter8_f_2598_16651)">
<circle cx="443.803" cy="37.6751" r="1.58974" transform="rotate(180 443.803 37.6751)" fill="#D9D9D9"/>
</g>
<g filter="url(#filter9_f_2598_16651)">
<circle cx="144.59" cy="119.316" r="1.58974" transform="rotate(180 144.59 119.316)" fill="#D9D9D9"/>
</g>
<g filter="url(#filter10_f_2598_16651)">
<circle cx="160.487" cy="97.5897" r="1.58974" transform="rotate(180 160.487 97.5897)" fill="#D9D9D9"/>
</g>
<g filter="url(#filter11_f_2598_16651)">
<circle cx="58.0255" cy="53.0428" r="1.58974" transform="rotate(180 58.0255 53.0428)" fill="#D9D9D9"/>
</g>
<g filter="url(#filter12_f_2598_16651)">
<circle cx="148.111" cy="19.6581" r="1.58974" fill="#D9D9D9"/>
</g>
<g filter="url(#filter13_f_2598_16651)">
<circle cx="411.479" cy="280.906" r="1.58974" transform="rotate(180 411.479 280.906)" fill="#D9D9D9"/>
</g>
<g filter="url(#filter14_f_2598_16651)">
<circle cx="75.889" cy="145.914" r="1.58974" transform="rotate(180 75.889 145.914)" fill="#D9D9D9"/>
</g>
<g filter="url(#filter15_f_2598_16651)">
<circle cx="70.7435" cy="299.453" r="1.58974" transform="rotate(180 70.7435 299.453)" fill="#D9D9D9"/>
</g>
<circle cx="87.1709" cy="278.256" r="1.05983" transform="rotate(180 87.1709 278.256)" fill="#D9D9D9"/>
<circle cx="26.2307" cy="296.803" r="1.05983" transform="rotate(180 26.2307 296.803)" fill="#D9D9D9"/>
<circle cx="231.838" cy="360.393" r="1.05983" transform="rotate(180 231.838 360.393)" fill="#D9D9D9"/>
<circle cx="70.0598" cy="130.017" r="1.05983" fill="#D9D9D9"/>
<circle cx="1.05983" cy="1.05983" r="1.05983" transform="matrix(1 0 0 -1 98.2991 372.051)" fill="#D9D9D9"/>
<g filter="url(#filter16_d_2598_16651)">
<circle cx="256" cy="152.667" r="1" fill="white" fill-opacity="0.78" shape-rendering="crispEdges"/>
</g>
<circle cx="235" cy="139.667" r="3" fill="white"/>
<circle cx="312" cy="119.667" r="2" fill="white"/>
<circle cx="381.838" cy="83.0598" r="1.05983" transform="rotate(180 381.838 83.0598)" fill="#D9D9D9"/>
<circle cx="1.05983" cy="1.05983" r="1.05983" transform="matrix(1 0 0 -1 248.299 94.718)" fill="#D9D9D9"/>
<g filter="url(#filter17_d_2598_16651)">
<circle cx="311" cy="451.667" r="1" fill="white" fill-opacity="0.78" shape-rendering="crispEdges"/>
</g>
<circle cx="290" cy="438.667" r="3" fill="white"/>
<circle cx="367" cy="418.667" r="2" fill="white"/>
<circle cx="436.838" cy="382.06" r="1.05983" transform="rotate(180 436.838 382.06)" fill="#D9D9D9"/>
<circle cx="1.05983" cy="1.05983" r="1.05983" transform="matrix(1 0 0 -1 303.299 393.718)" fill="#D9D9D9"/>
<g filter="url(#filter18_ddiiii_2598_16651)">
<path d="M471.721 191.552C471.721 191.553 471.721 191.554 471.722 191.555L474.18 194.555C474.731 195.228 474.056 196.202 473.232 195.922L469.559 194.672C467.869 194.098 466.062 193.963 464.306 194.281C462.55 194.599 460.904 195.359 459.524 196.49L456.518 198.951C455.845 199.502 454.871 198.827 455.152 198.003L456.402 194.329C456.976 192.639 457.111 190.831 456.793 189.075C456.475 187.32 455.714 185.674 454.584 184.293L452.123 181.288C451.572 180.615 452.247 179.641 453.071 179.921L456.745 181.171C458.435 181.746 460.243 181.88 461.998 181.562C463.754 181.244 465.4 180.484 466.781 179.354L469.786 176.893C470.459 176.342 471.433 177.017 471.153 177.84L469.902 181.515C469.328 183.204 469.193 185.012 469.511 186.768C469.829 188.523 470.589 190.169 471.719 191.549C471.72 191.55 471.72 191.551 471.721 191.552V191.552Z" fill="url(#paint5_linear_2598_16651)"/>
</g>
<g filter="url(#filter19_ddiiii_2598_16651)">
<path d="M420.325 201.047C420.325 201.048 420.325 201.049 420.326 201.049L422.167 203.297C422.58 203.801 422.074 204.531 421.457 204.321L418.705 203.385C417.44 202.954 416.086 202.854 414.771 203.092C413.455 203.33 412.222 203.899 411.188 204.746L408.937 206.59C408.433 207.003 407.703 206.497 407.913 205.88L408.85 203.127C409.28 201.862 409.381 200.508 409.143 199.192C408.904 197.877 408.335 196.644 407.488 195.61L405.645 193.359C405.232 192.855 405.738 192.125 406.355 192.335L409.107 193.272C410.373 193.702 411.727 193.803 413.042 193.564C414.357 193.326 415.59 192.757 416.624 191.91L418.876 190.066C419.38 189.654 420.109 190.16 419.899 190.776L418.963 193.529C418.533 194.794 418.432 196.149 418.67 197.464C418.908 198.779 419.477 200.011 420.324 201.045C420.324 201.046 420.325 201.047 420.325 201.047V201.047Z" fill="url(#paint6_linear_2598_16651)"/>
</g>
<g filter="url(#filter20_ddiiii_2598_16651)">
<path d="M443.787 222.011C443.786 222.012 443.785 222.013 443.785 222.015L442.347 227.047C442.026 228.17 440.435 228.17 440.114 227.047L438.676 222.012C438.016 219.702 436.778 217.599 435.079 215.9C433.38 214.201 431.277 212.963 428.967 212.303L423.927 210.862C422.804 210.541 422.805 208.95 423.927 208.629L428.964 207.191C431.274 206.53 433.377 205.292 435.076 203.594C436.775 201.895 438.013 199.791 438.673 197.481L440.114 192.441C440.435 191.319 442.026 191.319 442.347 192.442L443.785 197.478C444.446 199.788 445.684 201.892 447.382 203.59C449.081 205.289 451.185 206.527 453.495 207.187L458.535 208.628C459.657 208.949 459.657 210.54 458.535 210.861L453.498 212.3C451.188 212.96 449.084 214.198 447.386 215.897C445.687 217.595 444.45 219.698 443.789 222.007C443.789 222.009 443.788 222.01 443.787 222.011V222.011Z" fill="url(#paint7_linear_2598_16651)"/>
</g>
<g filter="url(#filter21_f_2598_16651)">
<circle cx="441.23" cy="209.745" r="9.27931" fill="#BFACFF"/>
</g>
<g filter="url(#filter22_f_2598_16651)">
<circle cx="463.766" cy="188.535" r="9.27931" fill="#BFACFF"/>
</g>
<g filter="url(#filter23_f_2598_16651)">
<circle cx="412.73" cy="197.152" r="4.63965" fill="#BFACFF"/>
</g>
<g filter="url(#filter24_ddiiii_2598_16651)">
<path d="M101.933 323.303C66.6396 323.303 40 295.815 40 261.879C40 227.773 65.2821 200.116 101.933 200.116C121.276 200.116 134.681 206.054 145.371 218.78L128.572 233.373C121.446 225.907 112.623 222.174 101.933 222.174C79.0261 222.174 64.6034 240.16 64.6034 261.879C64.6034 283.598 79.0261 301.244 102.442 301.244C113.98 301.244 122.634 297.342 129.59 289.706L146.898 304.468C137.905 315.328 122.634 323.303 101.933 323.303Z" fill="url(#paint8_linear_2598_16651)"/>
<path d="M190.134 323.303C165.87 323.303 146.526 302.771 146.526 277.32C146.526 251.868 165.87 230.997 190.134 230.997C205.405 230.997 213.38 237.275 218.131 246.777V232.864H240.868V321.097H218.64V306.674C213.889 316.685 205.914 323.303 190.134 323.303ZM169.433 277.15C169.433 290.555 179.274 302.602 193.867 302.602C208.968 302.602 218.64 291.064 218.64 277.32C218.64 263.576 208.968 251.698 193.867 251.698C179.274 251.698 169.433 263.406 169.433 277.15Z" fill="url(#paint9_linear_2598_16651)"/>
<path d="M254.478 321.097V197.231H277.385V321.097H254.478Z" fill="url(#paint10_linear_2598_16651)"/>
<path d="M303.149 323.303C294.326 323.303 287.878 316.515 287.878 308.371C287.878 300.396 294.326 293.609 303.149 293.609C311.972 293.609 318.251 300.396 318.251 308.371C318.251 316.515 311.972 323.303 303.149 323.303Z" fill="url(#paint11_linear_2598_16651)"/>
<path d="M365.612 323.303C341.348 323.303 322.005 302.771 322.005 277.32C322.005 251.868 341.348 230.997 365.612 230.997C380.883 230.997 388.858 237.275 393.609 246.777V232.864H416.346V321.097H394.118V306.674C389.367 316.685 381.392 323.303 365.612 323.303ZM344.911 277.15C344.911 290.555 354.753 302.602 369.345 302.602C384.447 302.602 394.118 291.064 394.118 277.32C394.118 263.576 384.447 251.698 369.345 251.698C354.753 251.698 344.911 263.406 344.911 277.15Z" fill="url(#paint12_linear_2598_16651)"/>
<path d="M429.956 321.097V232.864H452.863V321.097H429.956Z" fill="url(#paint13_linear_2598_16651)"/>
</g>
</g>
<rect x="3" y="3" width="506" height="506" rx="113" stroke="url(#paint14_linear_2598_16651)" stroke-opacity="0.3" stroke-width="6"/>
<defs>
<filter id="filter0_f_2598_16651" x="-59.0337" y="-601.152" width="651.125" height="1393.45" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="28" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter1_f_2598_16651" x="3.55102" y="-641.642" width="595.558" height="1474.43" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="48.245" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter2_f_2598_16651" x="65.4873" y="-203.921" width="425.913" height="960.806" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="30.5237" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter3_f_2598_16651" x="95.3067" y="-0.0484848" width="360.731" height="744.13" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="35.7406" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter4_f_2598_16651" x="-66.9637" y="-239" width="666.985" height="1000.36" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="31.965" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter5_d_2598_16651" x="80" y="437" width="14" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.35 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2598_16651" result="shape"/>
</filter>
<filter id="filter6_d_2598_16651" x="99" y="423" width="14" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.35 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2598_16651" result="shape"/>
</filter>
<filter id="filter7_f_2598_16651" x="112.607" y="259.709" width="6.35893" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter8_f_2598_16651" x="440.624" y="34.4957" width="6.35917" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter9_f_2598_16651" x="141.41" y="116.137" width="6.35893" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter10_f_2598_16651" x="157.308" y="94.4103" width="6.35893" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter11_f_2598_16651" x="54.846" y="49.8634" width="6.35893" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter12_f_2598_16651" x="144.931" y="16.4786" width="6.35893" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter13_f_2598_16651" x="408.299" y="277.726" width="6.35917" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter14_f_2598_16651" x="72.7096" y="142.735" width="6.35893" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter15_f_2598_16651" x="67.5641" y="296.274" width="6.35893" height="6.35893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.794872" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter16_d_2598_16651" x="249" y="145.667" width="14" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.35 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2598_16651" result="shape"/>
</filter>
<filter id="filter17_d_2598_16651" x="304" y="444.667" width="14" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.35 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2598_16651" result="shape"/>
</filter>
<filter id="filter18_ddiiii_2598_16651" x="433.678" y="164.584" width="58.9478" height="61.1052" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="8.29324"/>
<feGaussianBlur stdDeviation="9.12257"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="3.45947"/>
<feGaussianBlur stdDeviation="7.7838"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.16 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_2598_16651" result="effect2_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_2598_16651" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-3.3173"/>
<feGaussianBlur stdDeviation="5.80527"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-6.05407"/>
<feGaussianBlur stdDeviation="12.1081"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.6775 0 0 0 0 0.625 0 0 0 0 1 0 0 0 0.66 0"/>
<feBlend mode="normal" in2="effect3_innerShadow_2598_16651" result="effect4_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="3.45947" operator="erode" in="SourceAlpha" result="effect5_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="5.1892"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_2598_16651" result="effect5_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="3.45947" operator="erode" in="SourceAlpha" result="effect6_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="3.8919"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_2598_16651" result="effect6_innerShadow_2598_16651"/>
</filter>
<filter id="filter19_ddiiii_2598_16651" x="391.828" y="180.847" width="44.1563" height="45.7724" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6.21227"/>
<feGaussianBlur stdDeviation="6.8335"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.5914"/>
<feGaussianBlur stdDeviation="5.83066"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.16 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_2598_16651" result="effect2_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_2598_16651" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-2.48491"/>
<feGaussianBlur stdDeviation="4.34859"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-4.53496"/>
<feGaussianBlur stdDeviation="9.06991"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.6775 0 0 0 0 0.625 0 0 0 0 1 0 0 0 0.66 0"/>
<feBlend mode="normal" in2="effect3_innerShadow_2598_16651" result="effect4_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="2.5914" operator="erode" in="SourceAlpha" result="effect5_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="3.88711"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_2598_16651" result="effect5_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="2.5914" operator="erode" in="SourceAlpha" result="effect6_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="2.91533"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_2598_16651" result="effect6_innerShadow_2598_16651"/>
</filter>
<filter id="filter20_ddiiii_2598_16651" x="398.593" y="175.345" width="85.2761" height="88.1691" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="11.1329"/>
<feGaussianBlur stdDeviation="12.2461"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4.64399"/>
<feGaussianBlur stdDeviation="10.449"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.16 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_2598_16651" result="effect2_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_2598_16651" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-4.45314"/>
<feGaussianBlur stdDeviation="7.793"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-8.12698"/>
<feGaussianBlur stdDeviation="16.254"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.6775 0 0 0 0 0.625 0 0 0 0 1 0 0 0 0.66 0"/>
<feBlend mode="normal" in2="effect3_innerShadow_2598_16651" result="effect4_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="4.64399" operator="erode" in="SourceAlpha" result="effect5_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="6.96599"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_2598_16651" result="effect5_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="4.64399" operator="erode" in="SourceAlpha" result="effect6_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="5.22449"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_2598_16651" result="effect6_innerShadow_2598_16651"/>
</filter>
<filter id="filter21_f_2598_16651" x="417.951" y="186.466" width="46.5586" height="46.5586" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="7" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter22_f_2598_16651" x="440.487" y="165.256" width="46.5586" height="46.5586" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="7" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter23_f_2598_16651" x="394.09" y="178.512" width="37.2793" height="37.2793" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="7" result="effect1_foregroundBlur_2598_16651"/>
</filter>
<filter id="filter24_ddiiii_2598_16651" x="18.9041" y="183.231" width="455.055" height="170.756" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="9.58904"/>
<feGaussianBlur stdDeviation="10.5479"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="9"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.16 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_2598_16651" result="effect2_dropShadow_2598_16651"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_2598_16651" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-3.83562"/>
<feGaussianBlur stdDeviation="6.71233"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-7"/>
<feGaussianBlur stdDeviation="23.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.6775 0 0 0 0 0.625 0 0 0 0 1 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="effect3_innerShadow_2598_16651" result="effect4_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="4" operator="erode" in="SourceAlpha" result="effect5_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_2598_16651" result="effect5_innerShadow_2598_16651"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="4" operator="erode" in="SourceAlpha" result="effect6_innerShadow_2598_16651"/>
<feOffset/>
<feGaussianBlur stdDeviation="4.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_2598_16651" result="effect6_innerShadow_2598_16651"/>
</filter>
<linearGradient id="paint0_linear_2598_16651" x1="256" y1="0" x2="256" y2="512" gradientUnits="userSpaceOnUse">
<stop stop-color="#3E3C77"/>
<stop offset="1" stop-color="#53489C"/>
</linearGradient>
<linearGradient id="paint1_linear_2598_16651" x1="312.663" y1="728.181" x2="121.664" y2="-496.004" gradientUnits="userSpaceOnUse">
<stop stop-color="#0006F7"/>
<stop offset="0.445833" stop-color="#5B5D9D" stop-opacity="0.24"/>
<stop offset="1" stop-color="#5B5EEE" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint2_linear_2598_16651" x1="318.863" y1="705.437" x2="259.753" y2="-200.23" gradientUnits="userSpaceOnUse">
<stop stop-color="#721EF4"/>
<stop offset="1" stop-color="#2E0CFF" stop-opacity="0.03"/>
</linearGradient>
<linearGradient id="paint3_linear_2598_16651" x1="304.644" y1="679.481" x2="262.275" y2="30.3213" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="0.482292" stop-color="#7F30FF"/>
<stop offset="1" stop-color="#9D9FFF" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint4_radial_2598_16651" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(205.161 699.575) rotate(-52.9732) scale(816.922 1694.58)">
<stop stop-color="white"/>
<stop offset="0.314134" stop-color="#9B8DFF"/>
<stop offset="1" stop-color="#3518FF" stop-opacity="0"/>
</radialGradient>
<linearGradient id="paint5_linear_2598_16651" x1="450.206" y1="178.946" x2="476.098" y2="196.897" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint6_linear_2598_16651" x1="404.209" y1="191.605" x2="423.604" y2="205.051" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint7_linear_2598_16651" x1="441.231" y1="188.535" x2="441.231" y2="230.955" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint8_linear_2598_16651" x1="247.534" y1="197.231" x2="247.534" y2="323.303" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint9_linear_2598_16651" x1="247.534" y1="197.231" x2="247.534" y2="323.303" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint10_linear_2598_16651" x1="247.534" y1="197.231" x2="247.534" y2="323.303" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint11_linear_2598_16651" x1="247.534" y1="197.231" x2="247.534" y2="323.303" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint12_linear_2598_16651" x1="247.534" y1="197.231" x2="247.534" y2="323.303" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint13_linear_2598_16651" x1="247.534" y1="197.231" x2="247.534" y2="323.303" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E3E0F4"/>
</linearGradient>
<linearGradient id="paint14_linear_2598_16651" x1="256" y1="0" x2="256" y2="512" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0"/>
<stop offset="1" stop-color="#D8CEFF"/>
</linearGradient>
<clipPath id="clip0_2598_16651">
<rect width="512" height="512" rx="116" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 34 KiB

@@ -19,4 +19,3 @@ Every CalDav Provider is different and needs minor adjustments.
Follow our CalDav Roadmap here: <a class="text-blue-500" target="_blank" href="https://github.com/calcom/cal.com/issues/3457">https://github.com/calcom/cal.com/issues/3457</a>. Follow our CalDav Roadmap here: <a class="text-blue-500" target="_blank" href="https://github.com/calcom/cal.com/issues/3457">https://github.com/calcom/cal.com/issues/3457</a>.
If your CalDav connection is not working, please try another Calendar provider (Google Mail or another CalDav). If your CalDav connection is not working, please try another Calendar provider (Google Mail or another CalDav).
+3 -6
View File
@@ -49,12 +49,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
let message = e.message; let message = e.message;
if (e.message.indexOf("Invalid credentials") > -1 && url.indexOf("dav.php") > -1) { if (e.message.indexOf("Invalid credentials") > -1 && url.indexOf("dav.php") > -1) {
const parsedUrl = new URL(url); const parsedUrl = new URL(url);
const adminUrl = const adminUrl = `${parsedUrl.protocol}//${parsedUrl.hostname}${
parsedUrl.protocol + parsedUrl.port ? `:${parsedUrl.port}` : ""
"//" + }/admin/?/settings/standard/`;
parsedUrl.hostname +
(parsedUrl.port ? ":" + parsedUrl.port : "") +
"/admin/?/settings/standard/";
message = `Couldn\'t connect to caldav account, please verify WebDAV authentication type is set to "Basic"`; message = `Couldn\'t connect to caldav account, please verify WebDAV authentication type is set to "Basic"`;
return res.status(500).json({ message, actionUrl: adminUrl }); return res.status(500).json({ message, actionUrl: adminUrl });
} }
@@ -71,7 +71,7 @@ export const fetcher = async (endpoint: string, init?: RequestInit | undefined)
return fetch(`https://api.daily.co/v1${endpoint}`, { return fetch(`https://api.daily.co/v1${endpoint}`, {
method: "GET", method: "GET",
headers: { headers: {
Authorization: "Bearer " + api_key, Authorization: `Bearer ${api_key}`,
"Content-Type": "application/json", "Content-Type": "application/json",
...init?.headers, ...init?.headers,
}, },
+128 -16
View File
@@ -1,17 +1,129 @@
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0,0,400,400"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="path0" <g clip-path="url(#clip0_10423_610363)">
d="M100.400 142.062 C 99.630 142.280,98.394 143.076,97.654 143.830 C 96.914 144.583,95.997 145.200,95.616 145.200 C 94.776 145.200,93.802 146.248,93.389 147.598 C 93.221 148.147,92.560 149.054,91.919 149.613 C 90.024 151.267,90.020 151.390,90.010 199.645 C 89.999 248.545,90.014 248.945,91.940 250.744 C 92.571 251.334,93.229 252.262,93.401 252.808 C 93.751 253.916,95.054 255.200,95.829 255.200 C 96.107 255.200,96.710 255.808,97.169 256.550 C 98.373 258.498,94.832 258.400,164.273 258.400 C 231.741 258.400,231.099 258.418,231.949 256.552 C 232.208 255.983,233.149 255.250,234.197 254.801 C 235.357 254.304,236.005 253.774,236.014 253.314 C 236.021 252.921,236.375 251.880,236.800 251.000 C 237.225 250.120,237.579 249.119,237.586 248.776 C 237.594 248.434,237.864 247.804,238.187 247.376 C 238.696 246.704,238.776 240.392,238.787 200.426 C 238.801 149.852,238.967 154.051,236.799 149.949 C 236.610 149.591,236.332 148.647,236.183 147.850 C 235.956 146.640,235.591 146.227,233.964 145.342 C 232.893 144.759,231.907 143.938,231.774 143.518 C 231.641 143.098,231.052 142.539,230.466 142.277 C 229.079 141.657,102.567 141.447,100.400 142.062 " <rect width="24" height="24" rx="5.4375" fill="url(#paint0_linear_10423_610363)"/>
stroke="none" fill="#f9f9f9" fillRule="evenodd"></path> <mask id="mask0_10423_610363" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="-13" y="-13" width="50" height="50">
<path id="path1" <rect x="-12.0938" y="13.0312" width="35.5312" height="32.625" transform="rotate(-45 -12.0938 13.0312)" fill="url(#paint1_linear_10423_610363)"/>
d="M304.600 153.562 C 304.160 153.717,302.589 154.419,301.109 155.122 C 299.629 155.825,298.171 156.400,297.869 156.400 C 297.567 156.400,296.528 156.977,295.560 157.682 C 294.592 158.387,292.872 159.272,291.739 159.649 C 290.605 160.025,288.743 160.976,287.602 161.761 C 286.460 162.547,284.778 163.386,283.863 163.628 C 282.948 163.869,281.300 164.672,280.200 165.413 C 279.100 166.154,277.660 166.885,277.000 167.037 C 275.491 167.385,272.800 168.718,272.800 169.117 C 272.800 169.485,270.749 170.506,268.629 171.194 C 266.207 171.979,263.730 174.650,263.412 176.820 C 262.921 180.167,263.353 224.092,263.889 225.295 C 264.635 226.970,266.755 228.668,269.300 229.629 C 270.565 230.107,271.600 230.622,271.600 230.775 C 271.600 231.219,274.452 232.687,276.241 233.162 C 277.144 233.403,278.381 234.061,278.991 234.626 C 279.600 235.191,281.382 236.125,282.950 236.701 C 284.517 237.278,286.430 238.236,287.200 238.831 C 287.970 239.426,289.320 240.126,290.200 240.387 C 292.160 240.967,294.400 242.079,294.400 242.472 C 294.400 242.837,297.518 244.231,299.125 244.584 C 299.790 244.730,300.737 245.198,301.228 245.625 C 301.720 246.051,302.620 246.400,303.228 246.400 C 303.837 246.400,304.605 246.504,304.936 246.631 C 305.267 246.758,305.902 246.498,306.348 246.052 C 306.793 245.607,307.721 244.951,308.410 244.595 C 310.905 243.305,310.800 245.287,310.800 199.575 C 310.800 155.897,310.789 155.600,309.169 155.600 C 309.026 155.600,308.231 155.060,307.400 154.400 C 306.569 153.740,305.780 153.218,305.645 153.240 C 305.510 153.262,305.040 153.407,304.600 153.562 " </mask>
stroke="none" fill="#1be7b8" fillRule="evenodd"></path> <g mask="url(#mask0_10423_610363)">
<path id="path2" <path d="M0.828562 4.84823C0.580368 5.09642 0.199723 5.09045 -0.0389254 4.85181C-0.278767 4.61196 -0.295473 4.23967 -0.0377322 3.98193C0.0982974 3.8459 0.234327 3.7934 0.398995 3.80772L0.383483 4.02847C0.280864 4.02608 0.192564 4.06188 0.117389 4.13705C-0.0436984 4.29814 -0.0186403 4.52605 0.134095 4.67879C0.28683 4.83152 0.512353 4.85419 0.67702 4.68953C0.758161 4.60838 0.791572 4.52008 0.786799 4.41747L1.01232 4.39957C1.02545 4.53918 0.974138 4.70265 0.828562 4.84823ZM1.44882 4.22796C1.27819 4.3986 0.997779 4.39024 0.818792 4.21126C0.639806 4.03227 0.629067 3.74947 0.7997 3.57884C0.907092 3.47145 1.00732 3.45952 1.10756 3.49293L1.00971 3.39508L1.16961 3.23519L1.79009 3.85567L1.63378 4.01199L1.53235 3.91056C1.56934 4.01437 1.5598 4.11699 1.44882 4.22796ZM0.978687 4.04898C1.07295 4.14324 1.22688 4.15876 1.3295 4.05614C1.4357 3.94994 1.42257 3.80078 1.32592 3.70413C1.22927 3.60748 1.07773 3.59197 0.971527 3.69816C0.868909 3.80078 0.882034 3.95232 0.978687 4.04898ZM1.8858 3.75996L1.01474 2.88889L1.17582 2.72781L2.04689 3.59887L1.8858 3.75996ZM2.24359 3.4332C2.18154 3.49525 2.08847 3.49286 2.03119 3.43559C1.97511 3.3795 1.97272 3.28643 2.03477 3.22438C2.09682 3.16233 2.1887 3.16591 2.24478 3.222C2.30206 3.27927 2.30564 3.37115 2.24359 3.4332ZM2.69598 2.98081C2.51818 3.1586 2.23061 3.15502 2.05043 2.97484C1.87025 2.79467 1.86429 2.51187 2.05282 2.32095C2.16498 2.2064 2.30101 2.15867 2.4263 2.17895L2.40363 2.40447C2.33204 2.39016 2.25686 2.41044 2.20198 2.46533C2.09936 2.56795 2.11487 2.7171 2.21152 2.81376C2.30817 2.91041 2.46091 2.92234 2.56353 2.81972C2.62558 2.75767 2.63512 2.68608 2.62438 2.61091L2.84275 2.59539C2.85945 2.72904 2.81769 2.8591 2.69598 2.98081ZM3.29285 2.38394C3.10074 2.57605 2.81675 2.56889 2.63776 2.3899C2.45877 2.21092 2.45042 1.92573 2.64253 1.73362C2.83465 1.54151 3.11983 1.54986 3.29882 1.72885C3.4778 1.90783 3.48496 2.19183 3.29285 2.38394ZM2.79885 2.22882C2.8955 2.32547 3.04346 2.33979 3.14608 2.23717C3.2487 2.13455 3.23438 1.98659 3.13773 1.88994C3.04108 1.79328 2.89192 1.77777 2.7893 1.88039C2.68668 1.98301 2.7022 2.13216 2.79885 2.22882ZM3.67916 1.9666L3.05868 1.34612L3.21738 1.18741L3.30806 1.2781C3.27107 1.17667 3.29733 1.07883 3.39278 0.983369C3.47989 0.896263 3.59564 0.864045 3.71138 0.898649C3.67797 0.781711 3.69587 0.680286 3.80445 0.571701C3.9381 0.438057 4.13975 0.434478 4.29607 0.590792L4.67552 0.970244L4.51443 1.13133L4.17436 0.791257C4.06697 0.683865 3.96912 0.688638 3.89633 0.761426C3.82116 0.8366 3.80445 0.922514 3.92378 1.04184L4.26385 1.38191L4.10276 1.543L3.76269 1.20293C3.6553 1.09553 3.55507 1.10269 3.47512 1.18264C3.4071 1.25066 3.39278 1.35805 3.50018 1.46544L3.84025 1.80551L3.67916 1.9666Z" fill="white" fill-opacity="0.03"/>
d="M104.148 137.776 C 103.459 138.076,102.774 138.519,102.624 138.760 C 102.475 139.002,101.832 139.200,101.196 139.200 C 98.679 139.200,95.594 140.337,94.191 141.782 C 93.434 142.562,92.630 143.200,92.406 143.200 C 92.181 143.200,91.703 143.875,91.344 144.700 C 90.984 145.525,90.140 146.560,89.467 147.000 C 87.556 148.251,87.579 147.532,87.693 201.219 L 87.800 252.069 88.800 252.944 C 89.350 253.425,90.311 254.498,90.935 255.328 C 91.559 256.159,92.682 257.235,93.430 257.719 C 94.178 258.204,94.792 258.829,94.795 259.110 C 94.801 259.708,96.289 260.360,98.770 260.851 C 99.743 261.044,100.887 261.516,101.311 261.901 C 102.535 263.008,223.251 262.983,224.942 261.875 C 225.616 261.433,227.174 261.056,228.925 260.910 C 232.411 260.620,234.281 259.898,234.866 258.616 C 235.107 258.087,235.812 257.444,236.432 257.187 C 237.635 256.688,238.800 255.226,238.800 254.214 C 238.800 253.876,239.039 253.600,239.330 253.600 C 239.622 253.600,240.297 253.135,240.830 252.568 L 241.800 251.536 241.800 200.335 L 241.800 149.134 240.400 147.884 C 239.630 147.197,238.690 145.944,238.312 145.101 C 237.852 144.075,237.232 143.430,236.441 143.154 C 235.696 142.895,235.110 142.318,234.859 141.598 C 234.411 140.311,233.008 139.763,229.068 139.333 C 227.786 139.194,226.522 138.865,226.260 138.603 C 224.854 137.196,225.002 137.200,164.726 137.216 C 115.566 137.229,105.185 137.325,104.148 137.776 M230.299 140.581 C 231.013 140.751,232.363 141.600,233.299 142.466 C 234.235 143.333,235.488 144.338,236.085 144.699 C 236.684 145.061,237.282 145.862,237.419 146.487 C 237.556 147.110,238.076 148.110,238.574 148.710 C 240.721 151.291,240.592 148.280,240.713 198.600 C 240.829 246.814,240.750 249.650,239.248 251.152 C 238.800 251.600,238.071 252.676,237.629 253.543 C 237.187 254.410,236.187 255.514,235.407 255.995 C 234.628 256.477,233.798 257.231,233.563 257.670 C 232.125 260.355,229.256 260.458,160.200 260.300 C 96.040 260.154,98.009 260.223,96.185 258.055 C 95.663 257.435,94.598 256.495,93.818 255.964 C 93.037 255.434,92.310 254.730,92.202 254.400 C 92.094 254.070,91.396 253.117,90.652 252.283 C 88.728 250.126,88.809 252.440,88.804 199.526 C 88.800 148.835,88.746 150.246,90.767 148.075 C 91.445 147.347,92.000 146.583,92.000 146.379 C 92.000 145.965,94.367 143.600,94.781 143.600 C 94.926 143.600,95.721 142.979,96.550 142.220 C 97.645 141.217,98.567 140.772,99.928 140.589 C 100.958 140.450,101.980 140.273,102.200 140.195 C 103.020 139.904,229.052 140.284,230.299 140.581 M302.261 151.784 C 301.415 152.085,300.477 152.683,300.177 153.111 C 299.589 153.951,298.498 154.440,295.467 155.223 C 294.179 155.556,293.257 156.096,292.706 156.841 C 292.120 157.635,291.307 158.082,289.909 158.382 C 287.523 158.894,286.569 159.361,285.000 160.786 C 284.254 161.463,282.944 162.058,281.536 162.358 C 279.852 162.717,278.929 163.194,277.936 164.216 C 277.201 164.973,276.327 165.593,275.994 165.596 C 274.726 165.605,271.323 167.114,270.329 168.107 C 269.759 168.678,268.506 169.354,267.546 169.609 C 263.906 170.578,262.647 172.127,261.546 176.994 C 260.707 180.702,260.406 219.312,261.200 221.401 C 261.420 221.979,261.860 223.699,262.178 225.222 C 262.801 228.210,263.915 229.763,265.769 230.228 C 266.340 230.371,266.906 230.649,267.027 230.844 C 267.148 231.040,267.598 231.200,268.028 231.200 C 268.457 231.200,269.121 231.575,269.504 232.034 C 270.324 233.017,272.827 234.231,274.800 234.604 C 275.626 234.760,276.610 235.349,277.200 236.040 C 277.950 236.919,278.976 237.422,281.300 238.052 C 283.242 238.578,284.400 239.096,284.400 239.438 C 284.400 240.158,287.095 241.510,289.201 241.847 C 290.693 242.085,292.400 243.256,292.400 244.041 C 292.400 244.329,297.174 246.000,297.997 246.000 C 298.233 246.000,299.057 246.630,299.827 247.400 C 301.156 248.729,301.366 248.800,303.981 248.800 L 306.736 248.800 309.338 246.578 C 312.714 243.696,312.469 247.711,312.322 197.737 L 312.200 156.074 310.962 154.537 C 308.533 151.521,305.601 150.593,302.261 151.784 M307.400 154.400 C 308.231 155.060,309.026 155.600,309.169 155.600 C 310.789 155.600,310.800 155.897,310.800 199.575 C 310.800 245.287,310.905 243.305,308.410 244.595 C 307.721 244.951,306.793 245.607,306.348 246.052 C 305.902 246.498,305.267 246.758,304.936 246.631 C 304.605 246.504,303.837 246.400,303.228 246.400 C 302.620 246.400,301.720 246.051,301.228 245.625 C 300.737 245.198,299.790 244.730,299.125 244.584 C 297.518 244.231,294.400 242.837,294.400 242.472 C 294.400 242.079,292.160 240.967,290.200 240.387 C 289.320 240.126,287.970 239.426,287.200 238.831 C 286.430 238.236,284.517 237.278,282.950 236.701 C 281.382 236.125,279.600 235.191,278.991 234.626 C 278.381 234.061,277.144 233.403,276.241 233.162 C 274.452 232.687,271.600 231.219,271.600 230.775 C 271.600 230.622,270.565 230.107,269.300 229.629 C 266.755 228.668,264.635 226.970,263.889 225.295 C 263.353 224.092,262.921 180.167,263.412 176.820 C 263.730 174.650,266.207 171.979,268.629 171.194 C 270.749 170.506,272.800 169.485,272.800 169.117 C 272.800 Line truncated <path d="M-3.10467 11.6099C-3.35286 11.8581 -3.7335 11.8522 -3.97215 11.6135C-4.21199 11.3737 -4.2287 11.0014 -3.97096 10.7437C-3.83493 10.6076 -3.6989 10.5551 -3.53423 10.5694L-3.54975 10.7902C-3.65236 10.7878 -3.74066 10.8236 -3.81584 10.8988C-3.97693 11.0599 -3.95187 11.2878 -3.79913 11.4405C-3.6464 11.5932 -3.42087 11.6159 -3.25621 11.4512C-3.17507 11.3701 -3.14166 11.2818 -3.14643 11.1792L-2.92091 11.1613C-2.90778 11.3009 -2.95909 11.4644 -3.10467 11.6099ZM-2.4844 10.9897C-2.65504 11.1603 -2.93545 11.152 -3.11444 10.973C-3.29342 10.794 -3.30416 10.5112 -3.13353 10.3406C-3.02614 10.2332 -2.9259 10.2212 -2.82567 10.2546L-2.92352 10.1568L-2.76362 9.9969L-2.14314 10.6174L-2.29945 10.7737L-2.40088 10.6723C-2.36389 10.7761 -2.37343 10.8787 -2.4844 10.9897ZM-2.95454 10.8107C-2.86027 10.905 -2.70635 10.9205 -2.60373 10.8179C-2.49753 10.7117 -2.51065 10.5625 -2.60731 10.4658C-2.70396 10.3692 -2.8555 10.3537 -2.9617 10.4599C-3.06432 10.5625 -3.05119 10.714 -2.95454 10.8107ZM-2.04742 10.5217L-2.91849 9.65061L-2.7574 9.48952L-1.88634 10.3606L-2.04742 10.5217ZM-1.68964 10.1949C-1.75169 10.257 -1.84476 10.2546 -1.90204 10.1973C-1.95812 10.1412 -1.9605 10.0481 -1.89846 9.9861C-1.83641 9.92405 -1.74453 9.92763 -1.68844 9.98371C-1.63117 10.041 -1.62759 10.1329 -1.68964 10.1949ZM-1.23725 9.74253C-1.41504 9.92032 -1.70261 9.91674 -1.88279 9.73656C-2.06297 9.55638 -2.06894 9.27359 -1.88041 9.08267C-1.76824 8.96812 -1.63221 8.92039 -1.50692 8.94067L-1.52959 9.16619C-1.60119 9.15187 -1.67636 9.17216 -1.73125 9.22705C-1.83387 9.32967 -1.81836 9.47882 -1.72171 9.57548C-1.62505 9.67213 -1.47232 9.68406 -1.3697 9.58144C-1.30765 9.51939 -1.29811 9.4478 -1.30884 9.37262L-1.09048 9.35711C-1.07378 9.49076 -1.11554 9.62082 -1.23725 9.74253ZM-0.640377 9.14566C-0.832489 9.33777 -1.11648 9.33061 -1.29547 9.15162C-1.47445 8.97264 -1.48281 8.68745 -1.29069 8.49534C-1.09858 8.30323 -0.813397 8.31158 -0.634411 8.49057C-0.455424 8.66955 -0.448265 8.95354 -0.640377 9.14566ZM-1.13438 8.99054C-1.03773 9.08719 -0.889765 9.10151 -0.787146 8.99889C-0.684527 8.89627 -0.698846 8.74831 -0.795499 8.65165C-0.892151 8.555 -1.04131 8.53949 -1.14393 8.64211C-1.24654 8.74473 -1.23103 8.89388 -1.13438 8.99054ZM-0.254065 8.72832L-0.874551 8.10783L-0.71585 7.94913L-0.625163 8.03982C-0.662154 7.93839 -0.635902 7.84055 -0.540443 7.74509C-0.453336 7.65798 -0.337592 7.62576 -0.221847 7.66037C-0.255258 7.54343 -0.237359 7.442 -0.128774 7.33342C0.00486898 7.19978 0.206527 7.1962 0.362842 7.35251L0.742293 7.73196L0.581205 7.89305L0.241131 7.55298C0.133739 7.44558 0.0358932 7.45036 -0.0368945 7.52314C-0.112069 7.59832 -0.128774 7.68423 -0.00944996 7.80356L0.330624 8.14363L0.169536 8.30472L-0.170538 7.96464C-0.27793 7.85725 -0.378162 7.86441 -0.458109 7.94436C-0.526124 8.01237 -0.540443 8.11977 -0.433051 8.22716L-0.0929769 8.56723L-0.254065 8.72832Z" fill="white" fill-opacity="0.03"/>
stroke="none" fill="#4c545c" fillRule="evenodd"></path> <path d="M2.24275 6.26244C1.99455 6.51064 1.61391 6.50467 1.37526 6.26602C1.13542 6.02618 1.11871 5.65389 1.37645 5.39615C1.51248 5.26012 1.64851 5.20761 1.81318 5.22193L1.79767 5.44268C1.69505 5.4403 1.60675 5.47609 1.53157 5.55127C1.37049 5.71236 1.39554 5.94027 1.54828 6.093C1.70101 6.24574 1.92654 6.26841 2.0912 6.10374C2.17235 6.0226 2.20576 5.9343 2.20098 5.83168L2.42651 5.81378C2.43963 5.95339 2.38832 6.11687 2.24275 6.26244ZM2.86301 5.64218C2.69238 5.81281 2.41196 5.80446 2.23298 5.62547C2.05399 5.44649 2.04325 5.16369 2.21389 4.99305C2.32128 4.88566 2.42151 4.87373 2.52174 4.90714L2.4239 4.8093L2.58379 4.6494L3.20428 5.26989L3.04796 5.4262L2.94654 5.32478C2.98353 5.42859 2.97398 5.53121 2.86301 5.64218ZM2.39287 5.46319C2.48714 5.55746 2.64107 5.57297 2.74368 5.47035C2.84988 5.36415 2.83676 5.215 2.74011 5.11835C2.64345 5.02169 2.49191 5.00618 2.38571 5.11238C2.28309 5.215 2.29622 5.36654 2.39287 5.46319ZM3.29999 5.17418L2.42892 4.30311L2.59001 4.14202L3.46108 5.01309L3.29999 5.17418ZM3.65777 4.84741C3.59573 4.90946 3.50265 4.90708 3.44538 4.8498C3.38929 4.79372 3.38691 4.70065 3.44896 4.6386C3.51101 4.57655 3.60288 4.58013 3.65897 4.63621C3.71624 4.69349 3.71982 4.78537 3.65777 4.84741ZM4.11016 4.39503C3.93237 4.57282 3.6448 4.56924 3.46462 4.38906C3.28444 4.20888 3.27847 3.92608 3.467 3.73516C3.57917 3.62061 3.7152 3.57288 3.84049 3.59317L3.81782 3.81869C3.74622 3.80437 3.67105 3.82466 3.61616 3.87955C3.51354 3.98216 3.52905 4.13132 3.62571 4.22797C3.72236 4.32462 3.87509 4.33656 3.97771 4.23394C4.03976 4.17189 4.04931 4.1003 4.03857 4.02512L4.25693 4.00961C4.27364 4.14325 4.23187 4.27332 4.11016 4.39503ZM4.70704 3.79815C4.51492 3.99027 4.23093 3.98311 4.05194 3.80412C3.87296 3.62513 3.86461 3.33995 4.05672 3.14784C4.24883 2.95572 4.53401 2.96408 4.713 3.14306C4.89199 3.32205 4.89915 3.60604 4.70704 3.79815ZM4.21303 3.64303C4.30969 3.73968 4.45765 3.754 4.56027 3.65138C4.66289 3.54877 4.64857 3.4008 4.55191 3.30415C4.45526 3.2075 4.30611 3.19199 4.20349 3.2946C4.10087 3.39722 4.11638 3.54638 4.21303 3.64303ZM5.09335 3.38082L4.47286 2.76033L4.63156 2.60163L4.72225 2.69232C4.68526 2.59089 4.71151 2.49304 4.80697 2.39758C4.89408 2.31048 5.00982 2.27826 5.12556 2.31286C5.09215 2.19593 5.11005 2.0945 5.21864 1.98592C5.35228 1.85227 5.55394 1.84869 5.71025 2.00501L6.08971 2.38446L5.92862 2.54555L5.58854 2.20547C5.48115 2.09808 5.38331 2.10285 5.31052 2.17564C5.23534 2.25082 5.21864 2.33673 5.33796 2.45605L5.67804 2.79613L5.51695 2.95722L5.17687 2.61714C5.06948 2.50975 4.96925 2.51691 4.8893 2.59686C4.82129 2.66487 4.80697 2.77226 4.91436 2.87965L5.25444 3.21973L5.09335 3.38082Z" fill="white" fill-opacity="0.03"/>
<path id="path3" <path d="M7.59028 0.914953C7.34209 1.16315 6.96144 1.15718 6.72279 0.918533C6.48295 0.678691 6.46625 0.306399 6.72399 0.0486588C6.86002 -0.0873708 6.99605 -0.139873 7.16071 -0.125555L7.1452 0.0951953C7.04258 0.0928088 6.95428 0.128606 6.87911 0.20378C6.71802 0.364868 6.74308 0.592778 6.89581 0.745513C7.04855 0.898248 7.27407 0.920919 7.43874 0.756252C7.51988 0.675111 7.55329 0.586811 7.54852 0.484192L7.77404 0.466294C7.78717 0.605903 7.73586 0.769377 7.59028 0.914953ZM8.21054 0.294691C8.03991 0.465324 7.7595 0.456972 7.58051 0.277985C7.40152 0.0989988 7.39079 -0.1838 7.56142 -0.354433C7.66881 -0.461825 7.76904 -0.473758 7.86928 -0.440347L7.77143 -0.538193L7.93132 -0.698087L8.55181 -0.0776011L8.3955 0.0787137L8.29407 -0.0227119C8.33106 0.0811002 8.32151 0.183719 8.21054 0.294691ZM7.74041 0.115704C7.83467 0.20997 7.9886 0.225483 8.09122 0.122864C8.19742 0.0166651 8.18429 -0.13249 8.08764 -0.229143C7.99099 -0.325796 7.83944 -0.341308 7.73325 -0.235109C7.63063 -0.13249 7.64375 0.0190516 7.74041 0.115704ZM8.64752 -0.173312L7.77645 -1.04438L7.93754 -1.20547L8.80861 -0.3344L8.64752 -0.173312ZM9.00531 -0.500074C8.94326 -0.438026 8.85019 -0.440412 8.79291 -0.497688C8.73683 -0.55377 8.73444 -0.646843 8.79649 -0.708892C8.85854 -0.77094 8.95042 -0.767361 9.0065 -0.711278C9.06378 -0.654003 9.06736 -0.562123 9.00531 -0.500074ZM9.4577 -0.952462C9.2799 -0.774669 8.99233 -0.778249 8.81215 -0.958429C8.63197 -1.13861 8.62601 -1.42141 8.81454 -1.61233C8.9267 -1.72688 9.06273 -1.77461 9.18802 -1.75432L9.16535 -1.5288C9.09376 -1.54312 9.01858 -1.52283 8.96369 -1.46794C8.86107 -1.36532 8.87659 -1.21617 8.97324 -1.11952C9.06989 -1.02286 9.22263 -1.01093 9.32525 -1.11355C9.38729 -1.1756 9.39684 -1.24719 9.3861 -1.32237L9.60447 -1.33788C9.62117 -1.20424 9.57941 -1.07417 9.4577 -0.952462ZM10.0546 -1.54934C9.86246 -1.35722 9.57847 -1.36438 9.39948 -1.54337C9.22049 -1.72236 9.21214 -2.00754 9.40425 -2.19965C9.59636 -2.39176 9.88155 -2.38341 10.0605 -2.20443C10.2395 -2.02544 10.2467 -1.74145 10.0546 -1.54934ZM9.56057 -1.70446C9.65722 -1.6078 9.80518 -1.59349 9.9078 -1.6961C10.0104 -1.79872 9.9961 -1.94669 9.89945 -2.04334C9.8028 -2.13999 9.65364 -2.1555 9.55102 -2.05288C9.4484 -1.95026 9.46391 -1.80111 9.56057 -1.70446ZM10.4409 -1.96667L9.8204 -2.58716L9.9791 -2.74586L10.0698 -2.65517C10.0328 -2.7566 10.059 -2.85444 10.1545 -2.9499C10.2416 -3.03701 10.3574 -3.06923 10.4731 -3.03462C10.4397 -3.15156 10.4576 -3.25299 10.5662 -3.36157C10.6998 -3.49522 10.9015 -3.4988 11.0578 -3.34248L11.4372 -2.96303L11.2762 -2.80194L10.9361 -3.14202C10.8287 -3.24941 10.7308 -3.24464 10.6581 -3.17185C10.5829 -3.09667 10.5662 -3.01076 10.6855 -2.89144L11.0256 -2.55136L10.8645 -2.39027L10.5244 -2.73035C10.417 -2.83774 10.3168 -2.83058 10.2368 -2.75063C10.1688 -2.68262 10.1545 -2.57523 10.2619 -2.46783L10.602 -2.12776L10.4409 -1.96667Z" fill="white" fill-opacity="0.03"/>
d="M102.200 140.195 C 101.980 140.273,100.958 140.450,99.928 140.589 C 98.567 140.772,97.645 141.217,96.550 142.220 C 95.721 142.979,94.926 143.600,94.781 143.600 C 94.367 143.600,92.000 145.965,92.000 146.379 C 92.000 146.583,91.445 147.347,90.767 148.075 C 88.746 150.246,88.800 148.835,88.804 199.526 C 88.809 252.440,88.728 250.126,90.652 252.283 C 91.396 253.117,92.094 254.070,92.202 254.400 C 92.310 254.730,93.037 255.434,93.818 255.964 C 94.598 256.495,95.663 257.435,96.185 258.055 C 98.009 260.223,96.040 260.154,160.200 260.300 C 229.256 260.458,232.125 260.355,233.563 257.670 C 233.798 257.231,234.628 256.477,235.407 255.995 C 236.187 255.514,237.187 254.410,237.629 253.543 C 238.071 252.676,238.800 251.600,239.248 251.152 C 240.750 249.650,240.829 246.814,240.713 198.600 C 240.592 148.280,240.721 151.291,238.574 148.710 C 238.076 148.110,237.556 147.110,237.419 146.487 C 237.282 145.862,236.684 145.061,236.085 144.699 C 235.488 144.338,234.235 143.333,233.299 142.466 C 232.363 141.600,231.013 140.751,230.299 140.581 C 229.052 140.284,103.020 139.904,102.200 140.195 M230.466 142.277 C 231.052 142.539,231.641 143.098,231.774 143.518 C 231.907 143.938,232.893 144.759,233.964 145.342 C 235.591 146.227,235.956 146.640,236.183 147.850 C 236.332 148.647,236.610 149.591,236.799 149.949 C 238.967 154.051,238.801 149.852,238.787 200.426 C 238.776 240.392,238.696 246.704,238.187 247.376 C 237.864 247.804,237.594 248.434,237.586 248.776 C 237.579 249.119,237.225 250.120,236.800 251.000 C 236.375 251.880,236.021 252.921,236.014 253.314 C 236.005 253.774,235.357 254.304,234.197 254.801 C 233.149 255.250,232.208 255.983,231.949 256.552 C 231.099 258.418,231.741 258.400,164.273 258.400 C 94.832 258.400,98.373 258.498,97.169 256.550 C 96.710 255.808,96.107 255.200,95.829 255.200 C 95.054 255.200,93.751 253.916,93.401 252.808 C 93.229 252.262,92.571 251.334,91.940 250.744 C 90.014 248.945,89.999 248.545,90.010 199.645 C 90.020 151.390,90.024 151.267,91.919 149.613 C 92.560 149.054,93.221 148.147,93.389 147.598 C 93.802 146.248,94.776 145.200,95.616 145.200 C 95.997 145.200,96.914 144.583,97.654 143.830 C 98.394 143.076,99.630 142.280,100.400 142.062 C 102.567 141.447,229.079 141.657,230.466 142.277 " <path d="M-1.69048 13.0242C-1.93868 13.2724 -2.31932 13.2664 -2.55797 13.0277C-2.79781 12.7879 -2.81452 12.4156 -2.55678 12.1579C-2.42075 12.0218 -2.28472 11.9693 -2.12005 11.9837L-2.13556 12.2044C-2.23818 12.202 -2.32648 12.2378 -2.40165 12.313C-2.56274 12.4741 -2.53768 12.702 -2.38495 12.8547C-2.23221 13.0075 -2.00669 13.0301 -1.84202 12.8655C-1.76088 12.7843 -1.72747 12.696 -1.73224 12.5934L-1.50672 12.5755C-1.4936 12.7151 -1.54491 12.8786 -1.69048 13.0242ZM-1.07022 12.4039C-1.24085 12.5745 -1.52126 12.5662 -1.70025 12.3872C-1.87924 12.2082 -1.88998 11.9254 -1.71934 11.7548C-1.61195 11.6474 -1.51172 11.6354 -1.41149 11.6689L-1.50933 11.571L-1.34944 11.4111L-0.728951 12.0316L-0.885266 12.1879L-0.986691 12.0865C-0.949701 12.1903 -0.959247 12.2929 -1.07022 12.4039ZM-1.54036 12.2249C-1.44609 12.3192 -1.29216 12.3347 -1.18954 12.2321C-1.08334 12.1259 -1.09647 11.9767 -1.19312 11.8801C-1.28978 11.7834 -1.44132 11.7679 -1.54752 11.8741C-1.65013 11.9767 -1.63701 12.1283 -1.54036 12.2249ZM-0.63324 11.9359L-1.50431 11.0648L-1.34322 10.9037L-0.472152 11.7748L-0.63324 11.9359ZM-0.275454 11.6091C-0.337502 11.6712 -0.430575 11.6688 -0.487851 11.6115C-0.543933 11.5554 -0.54632 11.4624 -0.484271 11.4003C-0.422222 11.3383 -0.330343 11.3418 -0.27426 11.3979C-0.216985 11.4552 -0.213405 11.5471 -0.275454 11.6091ZM0.176935 11.1567C-0.000858635 11.3345 -0.28843 11.331 -0.46861 11.1508C-0.648789 10.9706 -0.654756 10.6878 -0.466223 10.4969C-0.354059 10.3823 -0.218029 10.3346 -0.0927383 10.3549L-0.11541 10.5804C-0.187005 10.5661 -0.262179 10.5864 -0.317068 10.6413C-0.419687 10.7439 -0.404175 10.893 -0.307522 10.9897C-0.210869 11.0863 -0.0581343 11.0983 0.0444846 10.9957C0.106533 10.9336 0.116079 10.862 0.10534 10.7868L0.323703 10.7713C0.340409 10.905 0.298645 11.035 0.176935 11.1567ZM0.773808 10.5599C0.581695 10.752 0.297704 10.7448 0.118717 10.5658C-0.0602691 10.3869 -0.0686218 10.1017 0.12349 9.90955C0.315602 9.71744 0.600787 9.7258 0.779774 9.90478C0.95876 10.0838 0.96592 10.3678 0.773808 10.5599ZM0.279805 10.4048C0.376458 10.5014 0.52442 10.5157 0.627039 10.4131C0.729658 10.3105 0.715339 10.1625 0.618686 10.0659C0.522033 9.96922 0.372878 9.9537 0.270259 10.0563C0.16764 10.1589 0.183152 10.3081 0.279805 10.4048ZM1.16012 10.1425L0.539634 9.52205L0.698335 9.36335L0.789021 9.45403C0.752031 9.35261 0.778282 9.25476 0.873742 9.1593C0.960848 9.0722 1.07659 9.03998 1.19234 9.07458C1.15893 8.95765 1.17683 8.85622 1.28541 8.74763C1.41905 8.61399 1.62071 8.61041 1.77703 8.76673L2.15648 9.14618L1.99539 9.30727L1.65532 8.96719C1.54792 8.8598 1.45008 8.86457 1.37729 8.93736C1.30212 9.01253 1.28541 9.09845 1.40473 9.21777L1.74481 9.55785L1.58372 9.71893L1.24365 9.37886C1.13625 9.27147 1.03602 9.27863 0.956075 9.35857C0.888061 9.42659 0.873742 9.53398 0.981133 9.64137L1.32121 9.98145L1.16012 10.1425Z" fill="white" fill-opacity="0.03"/>
stroke="none" fill="#949c9c" fillRule="evenodd"></path> <path d="M3.65693 7.67666C3.40874 7.92485 3.02809 7.91888 2.78944 7.68024C2.5496 7.44039 2.5329 7.0681 2.79064 6.81036C2.92667 6.67433 3.0627 6.62183 3.22736 6.63615L3.21185 6.8569C3.10923 6.85451 3.02093 6.89031 2.94576 6.96548C2.78467 7.12657 2.80973 7.35448 2.96246 7.50722C3.1152 7.65995 3.34072 7.68262 3.50539 7.51796C3.58653 7.43681 3.61994 7.34851 3.61517 7.2459L3.84069 7.228C3.85382 7.36761 3.80251 7.53108 3.65693 7.67666ZM4.27719 7.05639C4.10656 7.22703 3.82615 7.21868 3.64716 7.03969C3.46818 6.8607 3.45744 6.5779 3.62807 6.40727C3.73546 6.29988 3.83569 6.28795 3.93593 6.32136L3.83808 6.22351L3.99797 6.06362L4.61846 6.6841L4.46215 6.84042L4.36072 6.73899C4.39771 6.8428 4.38817 6.94542 4.27719 7.05639ZM3.80706 6.87741C3.90132 6.97167 4.05525 6.98719 4.15787 6.88457C4.26407 6.77837 4.25094 6.62921 4.15429 6.53256C4.05764 6.43591 3.9061 6.4204 3.7999 6.52659C3.69728 6.62921 3.7104 6.78076 3.80706 6.87741ZM4.71417 6.58839L3.8431 5.71732L4.00419 5.55624L4.87526 6.4273L4.71417 6.58839ZM5.07196 6.26163C5.00991 6.32368 4.91684 6.32129 4.85956 6.26402C4.80348 6.20793 4.80109 6.11486 4.86314 6.05281C4.92519 5.99076 5.01707 5.99434 5.07315 6.05043C5.13043 6.1077 5.13401 6.19958 5.07196 6.26163ZM5.52435 5.80924C5.34655 5.98703 5.05898 5.98345 4.8788 5.80327C4.69862 5.6231 4.69266 5.3403 4.88119 5.14938C4.99335 5.03483 5.12938 4.9871 5.25467 5.00738L5.232 5.2329C5.16041 5.21859 5.08523 5.23887 5.03034 5.29376C4.92773 5.39638 4.94324 5.54553 5.03989 5.64219C5.13654 5.73884 5.28928 5.75077 5.3919 5.64815C5.45395 5.5861 5.46349 5.51451 5.45275 5.43934L5.67112 5.42382C5.68782 5.55747 5.64606 5.68753 5.52435 5.80924ZM6.12122 5.21237C5.92911 5.40448 5.64512 5.39732 5.46613 5.21833C5.28714 5.03935 5.27879 4.75416 5.4709 4.56205C5.66301 4.36994 5.9482 4.37829 6.12719 4.55728C6.30617 4.73626 6.31333 5.02026 6.12122 5.21237ZM5.62722 5.05725C5.72387 5.1539 5.87183 5.16822 5.97445 5.0656C6.07707 4.96298 6.06275 4.81502 5.9661 4.71837C5.86945 4.62171 5.72029 4.6062 5.61767 4.70882C5.51505 4.81144 5.53056 4.96059 5.62722 5.05725ZM6.50753 4.79503L5.88705 4.17455L6.04575 4.01584L6.13643 4.10653C6.09944 4.0051 6.12569 3.90726 6.22115 3.8118C6.30826 3.72469 6.424 3.69248 6.53975 3.72708C6.50634 3.61014 6.52424 3.50872 6.63282 3.40013C6.76647 3.26649 6.96812 3.26291 7.12444 3.41922L7.50389 3.79867L7.3428 3.95976L7.00273 3.61969C6.89534 3.5123 6.79749 3.51707 6.7247 3.58986C6.64953 3.66503 6.63282 3.75094 6.75215 3.87027L7.09222 4.21034L6.93113 4.37143L6.59106 4.03136C6.48367 3.92396 6.38343 3.93112 6.30349 4.01107C6.23547 4.07909 6.22115 4.18648 6.32855 4.29387L6.66862 4.63394L6.50753 4.79503Z" fill="white" fill-opacity="0.03"/>
<path id="path4" <path d="M9.00447 2.32917C8.75627 2.57736 8.37563 2.5714 8.13698 2.33275C7.89714 2.09291 7.88043 1.72061 8.13817 1.46287C8.2742 1.32684 8.41023 1.27434 8.5749 1.28866L8.55939 1.50941C8.45677 1.50702 8.36847 1.54282 8.29329 1.618C8.1322 1.77908 8.15726 2.00699 8.31 2.15973C8.46273 2.31246 8.68826 2.33513 8.85292 2.17047C8.93406 2.08933 8.96747 2.00103 8.9627 1.89841L9.18822 1.88051C9.20135 2.02012 9.15004 2.18359 9.00447 2.32917ZM9.62473 1.70891C9.45409 1.87954 9.17368 1.87119 8.9947 1.6922C8.81571 1.51321 8.80497 1.23042 8.9756 1.05978C9.083 0.95239 9.18323 0.940457 9.28346 0.973868L9.18561 0.876022L9.34551 0.716128L9.966 1.33661L9.80968 1.49293L9.70825 1.3915C9.74525 1.49532 9.7357 1.59793 9.62473 1.70891ZM9.15459 1.52992C9.24886 1.62419 9.40278 1.6397 9.5054 1.53708C9.6116 1.43088 9.59848 1.28172 9.50182 1.18507C9.40517 1.08842 9.25363 1.07291 9.14743 1.17911C9.04481 1.28172 9.05794 1.43327 9.15459 1.52992ZM10.0617 1.2409L9.19064 0.369836L9.35173 0.208748L10.2228 1.07982L10.0617 1.2409ZM10.4195 0.914141C10.3574 0.976189 10.2644 0.973803 10.2071 0.916527C10.151 0.860445 10.1486 0.767372 10.2107 0.705323C10.2727 0.643275 10.3646 0.646854 10.4207 0.702937C10.478 0.760213 10.4815 0.852092 10.4195 0.914141ZM10.8719 0.461753C10.6941 0.639546 10.4065 0.635966 10.2263 0.455786C10.0462 0.275607 10.0402 -0.00719167 10.2287 -0.198111C10.3409 -0.312662 10.4769 -0.360392 10.6022 -0.340106L10.5795 -0.114584C10.5079 -0.128902 10.4328 -0.108617 10.3779 -0.0537282C10.2753 0.0488907 10.2908 0.198046 10.3874 0.294699C10.4841 0.391351 10.6368 0.403284 10.7394 0.300665C10.8015 0.238616 10.811 0.167022 10.8003 0.0918475L11.0186 0.0763353C11.0354 0.209978 10.9936 0.340042 10.8719 0.461753ZM11.4688 -0.13512C11.2766 0.0569917 10.9927 0.0498323 10.8137 -0.129154C10.6347 -0.308141 10.6263 -0.593326 10.8184 -0.785438C11.0105 -0.97755 11.2957 -0.969197 11.4747 -0.790211C11.6537 -0.611224 11.6609 -0.327232 11.4688 -0.13512ZM10.9748 -0.290242C11.0714 -0.193589 11.2194 -0.17927 11.322 -0.281889C11.4246 -0.384508 11.4103 -0.53247 11.3136 -0.629123C11.217 -0.725775 11.0678 -0.741288 10.9652 -0.638669C10.8626 -0.53605 10.8781 -0.386895 10.9748 -0.290242ZM11.8551 -0.552457L11.2346 -1.17294L11.3933 -1.33164L11.484 -1.24096C11.447 -1.34238 11.4732 -1.44023 11.5687 -1.53569C11.6558 -1.6228 11.7715 -1.65501 11.8873 -1.62041C11.8539 -1.73735 11.8718 -1.83877 11.9804 -1.94736C12.114 -2.081 12.3157 -2.08458 12.472 -1.92827L12.8514 -1.54881L12.6903 -1.38773L12.3503 -1.7278C12.2429 -1.83519 12.145 -1.83042 12.0722 -1.75763C11.9971 -1.68246 11.9804 -1.59654 12.0997 -1.47722L12.4398 -1.13715L12.2787 -0.976058L11.9386 -1.31613C11.8312 -1.42352 11.731 -1.41636 11.651 -1.33642C11.583 -1.2684 11.5687 -1.16101 11.6761 -1.05362L12.0162 -0.713545L11.8551 -0.552457Z" fill="white" fill-opacity="0.03"/>
d="M35.200 0.984 C 35.200 1.947,35.121 1.971,31.700 2.084 L 28.200 2.200 28.077 3.900 L 27.954 5.600 25.403 5.600 C 21.914 5.600,20.903 6.043,20.590 7.712 C 20.367 8.902,20.142 9.103,18.669 9.430 C 17.102 9.777,16.988 9.898,16.800 11.400 C 16.605 12.956,16.554 13.003,14.922 13.122 C 13.260 13.243,13.243 13.260,13.122 14.922 C 13.003 16.554,12.956 16.605,11.400 16.800 C 9.898 16.988,9.777 17.102,9.430 18.669 C 9.103 20.142,8.902 20.367,7.712 20.590 C 6.043 20.903,5.600 21.914,5.600 25.403 L 5.600 27.954 3.900 28.077 L 2.200 28.200 2.084 31.700 C 1.971 35.121,1.947 35.200,0.984 35.200 L 0.000 35.200 0.000 200.000 L 0.000 364.800 0.984 364.800 C 1.947 364.800,1.971 364.879,2.084 368.300 L 2.200 371.800 3.900 372.177 L 5.600 372.554 5.600 374.851 C 5.600 378.083,6.072 379.102,7.712 379.410 C 8.902 379.633,9.103 379.858,9.430 381.331 C 9.777 382.898,9.898 383.012,11.400 383.200 C 12.953 383.394,13.004 383.449,13.121 385.059 C 13.247 386.786,13.757 387.181,15.876 387.195 C 16.598 387.199,16.773 387.463,16.876 388.700 C 16.992 390.104,17.107 390.224,18.669 390.570 C 20.142 390.897,20.367 391.098,20.590 392.288 C 20.903 393.957,21.914 394.400,25.403 394.400 L 27.954 394.400 28.077 396.100 L 28.200 397.800 31.700 397.916 C 35.121 398.029,35.200 398.053,35.200 399.016 L 35.200 400.000 200.000 400.000 L 364.800 400.000 364.800 399.016 C 364.800 398.053,364.879 398.029,368.300 397.916 L 371.800 397.800 372.177 396.100 L 372.554 394.400 375.103 394.400 C 378.233 394.400,379.094 393.974,379.414 392.265 C 379.633 391.101,379.865 390.896,381.331 390.570 C 382.893 390.224,383.008 390.104,383.124 388.700 C 383.241 387.288,383.327 387.200,384.596 387.200 C 386.308 387.200,387.200 386.308,387.200 384.596 C 387.200 383.327,387.288 383.241,388.700 383.124 C 390.104 383.008,390.224 382.893,390.570 381.331 C 390.896 379.865,391.101 379.633,392.265 379.414 C 393.974 379.094,394.400 378.233,394.400 375.103 L 394.400 372.554 396.100 372.177 L 397.800 371.800 397.916 368.300 C 398.029 364.879,398.053 364.800,399.016 364.800 L 400.000 364.800 400.000 200.000 L 400.000 35.200 399.016 35.200 C 398.053 35.200,398.029 35.121,397.916 31.700 L 397.800 28.200 396.100 28.077 L 394.400 27.954 394.400 25.403 C 394.400 21.914,393.957 20.903,392.288 20.590 C 391.098 20.367,390.897 20.142,390.570 18.669 C 390.224 17.107,390.104 16.992,388.700 16.876 C 387.463 16.773,387.199 16.598,387.195 15.876 C 387.181 13.757,386.786 13.247,385.059 13.121 C 383.452 13.004,383.396 12.953,383.275 11.480 C 383.121 9.617,382.265 9.200,378.597 9.200 L 376.046 9.200 375.923 7.500 C 375.802 5.821,375.779 5.798,374.173 5.681 C 372.616 5.566,372.529 5.488,372.173 3.881 L 371.800 2.200 368.300 2.084 C 364.879 1.971,364.800 1.947,364.800 0.984 L 364.800 0.000 200.000 0.000 L 35.200 0.000 35.200 0.984 M224.918 137.663 C 225.394 137.918,225.998 138.341,226.260 138.603 C 226.522 138.865,227.786 139.194,229.068 139.333 C 233.008 139.763,234.411 140.311,234.859 141.598 C 235.110 142.318,235.696 142.895,236.441 143.154 C 237.232 143.430,237.852 144.075,238.312 145.101 C 238.690 145.944,239.630 147.197,240.400 147.884 L 241.800 149.134 241.800 200.335 L 241.800 251.536 240.830 252.568 C 240.297 253.135,239.622 253.600,239.330 253.600 C 239.039 253.600,238.800 253.876,238.800 254.214 C 238.800 255.226,237.635 256.688,236.432 257.187 C 235.812 257.444,235.107 258.087,234.866 258.616 C 234.281 259.898,232.411 260.620,228.925 260.910 C 227.174 261.056,225.616 261.433,224.942 261.875 C 223.251 262.983,102.535 263.008,101.311 261.901 C 100.887 261.516,99.743 261.044,98.770 260.851 C 96.289 260.360,94.801 259.708,94.795 259.110 C 94.792 258.829,94.178 258.204,93.430 257.719 C 92.682 257.235,91.559 256.159,90.935 255.328 C 90.311 254.498,89.350 253.425,88.800 252.944 L 87.800 252.069 87.693 201.219 C 87.579 147.532,87.556 148.251,89.467 147.000 C 90.140 146.560,90.984 145.525,91.344 144.700 C 91.703 143.875,92.181 143.200,92.406 143.200 C 92.630 143.200,93.434 142.562,94.191 141.782 C 95.594 140.337,98.679 139.200,101.196 139.200 C 101.832 139.200,102.475 139.002,102.624 138.760 C 103.575 137.222,103.193 137.232,164.726 137.216 C 208.933 137.204,224.273 137.318,224.918 137.663 M308.162 152.107 C 309.021 152.598,310.281 153.692,310.962 154.537 L 312.200 156.074 312.322 197.737 C 312.469 247.711,312.714 243.696,309.338 246.578 L 306.736 248.800 303.981 248.800 C 301.366 248.800,301.156 248.729,299.827 247.400 C 299.057 246.630,298.233 246.000,297.997 246.000 C 297.174 246.000,292.400 244.329,292.400 244.041 C 292.400 243.256,290.693 242.085,289.201 241.847 C 287.095 241.510,284.400 240.158,284.400 239.438 C 284.400 239.096,283.242 238.578,281.300 238.052 C 278.976 237.422,277.950 236.919,277.200 236.040 C 276.610 235.349,275.626 234.760,274.800 234.604 C 272.827 234.231,270.324 233.017,269.504 232.034 C 269.121 231.575,268.457 231.200,268.028 231.200 C 267.598 231.200,267.148 231.040,267.027 230.844 C 266.906 230.649,266.340 230.371,265.769 230.228 C 263.915 229.763,262.801 228.21Line truncated <path d="M-0.276174 14.4384C-0.524369 14.6866 -0.905013 14.6806 -1.14366 14.442C-1.3835 14.2021 -1.40021 13.8298 -1.14247 13.5721C-1.00644 13.4361 -0.870409 13.3835 -0.705742 13.3979L-0.721254 13.6186C-0.823873 13.6162 -0.912173 13.652 -0.987347 13.7272C-1.14843 13.8883 -1.12338 14.1162 -0.970642 14.2689C-0.817907 14.4217 -0.592384 14.4443 -0.427716 14.2797C-0.346576 14.1985 -0.313165 14.1102 -0.317938 14.0076L-0.0924149 13.9897C-0.0792892 14.1293 -0.130599 14.2928 -0.276174 14.4384ZM0.344088 13.8181C0.173454 13.9887 -0.106958 13.9804 -0.285944 13.8014C-0.46493 13.6224 -0.47567 13.3396 -0.305036 13.169C-0.197644 13.0616 -0.0974116 13.0497 0.00282075 13.0831L-0.0950252 12.9852L0.0648694 12.8253L0.685356 13.4458L0.529041 13.6021L0.427615 13.5007C0.464606 13.6045 0.45506 13.7071 0.344088 13.8181ZM-0.126049 13.6391C-0.0317833 13.7334 0.122145 13.7489 0.224764 13.6463C0.330962 13.5401 0.317837 13.3909 0.221184 13.2943C0.124531 13.1976 -0.0270103 13.1821 -0.133209 13.2883C-0.235828 13.3909 -0.222702 13.5425 -0.126049 13.6391ZM0.781067 13.3501L-0.0900005 12.479L0.0710873 12.318L0.942154 13.189L0.781067 13.3501ZM1.13885 13.0233C1.0768 13.0854 0.983731 13.083 0.926456 13.0257C0.870373 12.9697 0.867987 12.8766 0.930036 12.8145C0.992084 12.7525 1.08396 12.7561 1.14005 12.8121C1.19732 12.8694 1.2009 12.9613 1.13885 13.0233ZM1.59124 12.571C1.41345 12.7488 1.12588 12.7452 0.945697 12.565C0.765517 12.3848 0.759551 12.102 0.948083 11.9111C1.06025 11.7965 1.19628 11.7488 1.32157 11.7691L1.2989 11.9946C1.2273 11.9803 1.15213 12.0006 1.09724 12.0555C0.99462 12.1581 1.01013 12.3073 1.10678 12.4039C1.20344 12.5006 1.35617 12.5125 1.45879 12.4099C1.52084 12.3478 1.53039 12.2762 1.51965 12.2011L1.73801 12.1855C1.75472 12.3192 1.71295 12.4492 1.59124 12.571ZM2.18811 11.9741C1.996 12.1662 1.71201 12.159 1.53302 11.9801C1.35404 11.8011 1.34568 11.5159 1.5378 11.3238C1.72991 11.1317 2.01509 11.14 2.19408 11.319C2.37307 11.498 2.38023 11.782 2.18811 11.9741ZM1.69411 11.819C1.79076 11.9156 1.93873 11.9299 2.04135 11.8273C2.14396 11.7247 2.12965 11.5767 2.03299 11.4801C1.93634 11.3834 1.78718 11.3679 1.68457 11.4705C1.58195 11.5732 1.59746 11.7223 1.69411 11.819ZM2.57443 11.5568L1.95394 10.9363L2.11264 10.7776L2.20333 10.8682C2.16634 10.7668 2.19259 10.669 2.28805 10.5735C2.37516 10.4864 2.4909 10.4542 2.60664 10.4888C2.57323 10.3719 2.59113 10.2704 2.69972 10.1618C2.83336 10.0282 3.03502 10.0246 3.19133 10.1809L3.57078 10.5604L3.4097 10.7215L3.06962 10.3814C2.96223 10.274 2.86438 10.2788 2.7916 10.3516C2.71642 10.4267 2.69972 10.5127 2.81904 10.632L3.15912 10.9721L2.99803 11.1331L2.65795 10.7931C2.55056 10.6857 2.45033 10.6928 2.37038 10.7728C2.30237 10.8408 2.28805 10.9482 2.39544 11.0556L2.73551 11.3957L2.57443 11.5568Z" fill="white" fill-opacity="0.03"/>
stroke="none" fill="#141c24" fillRule="evenodd"></path> <path d="M5.07124 9.09087C4.82304 9.33907 4.4424 9.3331 4.20375 9.09445C3.96391 8.85461 3.9472 8.48232 4.20494 8.22458C4.34097 8.08855 4.477 8.03605 4.64167 8.05036L4.62616 8.27111C4.52354 8.26873 4.43524 8.30452 4.36007 8.3797C4.19898 8.54079 4.22404 8.7687 4.37677 8.92143C4.52951 9.07417 4.75503 9.09684 4.9197 8.93217C5.00084 8.85103 5.03425 8.76273 5.02947 8.66011L5.255 8.64221C5.26812 8.78182 5.21681 8.9453 5.07124 9.09087ZM5.6915 8.47061C5.52087 8.64124 5.24045 8.63289 5.06147 8.4539C4.88248 8.27492 4.87174 7.99212 5.04238 7.82149C5.14977 7.71409 5.25 7.70216 5.35023 7.73557L5.25239 7.63773L5.41228 7.47783L6.03277 8.09832L5.87645 8.25463L5.77503 8.15321C5.81202 8.25702 5.80247 8.35964 5.6915 8.47061ZM5.22136 8.29162C5.31563 8.38589 5.46956 8.4014 5.57218 8.29878C5.67837 8.19258 5.66525 8.04343 5.5686 7.94678C5.47194 7.85012 5.3204 7.83461 5.2142 7.94081C5.11158 8.04343 5.12471 8.19497 5.22136 8.29162ZM6.12848 8.00261L5.25741 7.13154L5.4185 6.97045L6.28957 7.84152L6.12848 8.00261ZM6.48627 7.67584C6.42422 7.73789 6.33114 7.73551 6.27387 7.67823C6.21779 7.62215 6.2154 7.52908 6.27745 7.46703C6.3395 7.40498 6.43138 7.40856 6.48746 7.46464C6.54473 7.52192 6.54831 7.6138 6.48627 7.67584ZM6.93865 7.22346C6.76086 7.40125 6.47329 7.39767 6.29311 7.21749C6.11293 7.03731 6.10696 6.75451 6.2955 6.56359C6.40766 6.44904 6.54369 6.40131 6.66898 6.4216L6.64631 6.64712C6.57471 6.6328 6.49954 6.65309 6.44465 6.70798C6.34203 6.81059 6.35754 6.95975 6.4542 7.0564C6.55085 7.15305 6.70358 7.16499 6.8062 7.06237C6.86825 7.00032 6.8778 6.92873 6.86706 6.85355L7.08542 6.83804C7.10213 6.97168 7.06036 7.10175 6.93865 7.22346ZM7.53553 6.62658C7.34341 6.8187 7.05942 6.81154 6.88044 6.63255C6.70145 6.45356 6.6931 6.16838 6.88521 5.97627C7.07732 5.78415 7.36251 5.79251 7.54149 5.97149C7.72048 6.15048 7.72764 6.43447 7.53553 6.62658ZM7.04152 6.47146C7.13818 6.56811 7.28614 6.58243 7.38876 6.47981C7.49138 6.3772 7.47706 6.22923 7.3804 6.13258C7.28375 6.03593 7.1346 6.02042 7.03198 6.12303C6.92936 6.22565 6.94487 6.37481 7.04152 6.47146ZM7.92184 6.20925L7.30135 5.58876L7.46005 5.43006L7.55074 5.52075C7.51375 5.41932 7.54 5.32147 7.63546 5.22601C7.72257 5.13891 7.83831 5.10669 7.95406 5.14129C7.92065 5.02436 7.93854 4.92293 8.04713 4.81435C8.18077 4.6807 8.38243 4.67712 8.53875 4.83344L8.9182 5.21289L8.75711 5.37398L8.41703 5.0339C8.30964 4.92651 8.2118 4.93128 8.13901 5.00407C8.06383 5.07925 8.04713 5.16516 8.16645 5.28448L8.50653 5.62456L8.34544 5.78565L8.00537 5.44557C7.89797 5.33818 7.79774 5.34534 7.71779 5.42529C7.64978 5.4933 7.63546 5.60069 7.74285 5.70808L8.08293 6.04816L7.92184 6.20925Z" fill="white" fill-opacity="0.03"/>
<path d="M10.4188 3.74338C10.1706 3.99158 9.78993 3.98561 9.55128 3.74696C9.31144 3.50712 9.29474 3.13483 9.55248 2.87709C9.68851 2.74106 9.82454 2.68856 9.9892 2.70288L9.97369 2.92363C9.87107 2.92124 9.78277 2.95704 9.7076 3.03221C9.54651 3.1933 9.57157 3.42121 9.7243 3.57394C9.87704 3.72668 10.1026 3.74935 10.2672 3.58468C10.3484 3.50354 10.3818 3.41524 10.377 3.31262L10.6025 3.29472C10.6157 3.43433 10.5643 3.59781 10.4188 3.74338ZM11.039 3.12312C10.8684 3.29375 10.588 3.2854 10.409 3.10642C10.23 2.92743 10.2193 2.64463 10.3899 2.474C10.4973 2.3666 10.5975 2.35467 10.6978 2.38808L10.5999 2.29024L10.7598 2.13034L11.3803 2.75083L11.224 2.90714L11.1226 2.80572C11.1596 2.90953 11.15 3.01215 11.039 3.12312ZM10.5689 2.94413C10.6632 3.0384 10.8171 3.05391 10.9197 2.95129C11.0259 2.8451 11.0128 2.69594 10.9161 2.59929C10.8195 2.50263 10.6679 2.48712 10.5617 2.59332C10.4591 2.69594 10.4722 2.84748 10.5689 2.94413ZM11.476 2.65512L10.6049 1.78405L10.766 1.62296L11.6371 2.49403L11.476 2.65512ZM11.8338 2.32836C11.7718 2.3904 11.6787 2.38802 11.6214 2.33074C11.5653 2.27466 11.5629 2.18159 11.625 2.11954C11.687 2.05749 11.7789 2.06107 11.835 2.11715C11.8923 2.17443 11.8958 2.26631 11.8338 2.32836ZM12.2862 1.87597C12.1084 2.05376 11.8208 2.05018 11.6406 1.87C11.4605 1.68982 11.4545 1.40702 11.643 1.2161C11.7552 1.10155 11.8912 1.05382 12.0165 1.07411L11.9938 1.29963C11.9222 1.28531 11.8471 1.3056 11.7922 1.36049C11.6896 1.46311 11.7051 1.61226 11.8017 1.70891C11.8984 1.80557 12.0511 1.8175 12.1537 1.71488C12.2158 1.65283 12.2253 1.58124 12.2146 1.50606L12.433 1.49055C12.4497 1.62419 12.4079 1.75426 12.2862 1.87597ZM12.8831 1.27909C12.6909 1.47121 12.407 1.46405 12.228 1.28506C12.049 1.10607 12.0406 0.82089 12.2327 0.628777C12.4249 0.436665 12.71 0.445018 12.889 0.624005C13.068 0.802991 13.0752 1.08698 12.8831 1.27909ZM12.3891 1.12397C12.4857 1.22063 12.6337 1.23494 12.7363 1.13233C12.8389 1.02971 12.8246 0.881745 12.7279 0.785092C12.6313 0.68844 12.4821 0.672927 12.3795 0.775546C12.2769 0.878165 12.2924 1.02732 12.3891 1.12397ZM13.2694 0.861758L12.6489 0.241272L12.8076 0.0825706L12.8983 0.173257C12.8613 0.0718315 12.8875 -0.0260144 12.983 -0.121474C13.0701 -0.208581 13.1858 -0.240798 13.3016 -0.206194C13.2682 -0.323132 13.2861 -0.424557 13.3947 -0.533143C13.5283 -0.666786 13.73 -0.670366 13.8863 -0.514051L14.2657 -0.1346L14.1046 0.0264883L13.7646 -0.313586C13.6572 -0.420978 13.5593 -0.416205 13.4865 -0.343417C13.4114 -0.268243 13.3947 -0.182329 13.514 -0.063005L13.8541 0.277069L13.693 0.438157L13.3529 0.0980828C13.2455 -0.00930905 13.1453 -0.00214962 13.0653 0.0777976C12.9973 0.145812 12.983 0.253204 13.0904 0.360596L13.4305 0.70067L13.2694 0.861758Z" fill="white" fill-opacity="0.03"/>
<path d="M1.13801 15.8526C0.889816 16.1008 0.509171 16.0948 0.270523 15.8562C0.030681 15.6163 0.0139756 15.244 0.271716 14.9863C0.407746 14.8503 0.543775 14.7978 0.708443 14.8121L0.692931 15.0328C0.590312 15.0304 0.502012 15.0662 0.426838 15.1414C0.26575 15.3025 0.290808 15.5304 0.443543 15.6831C0.596278 15.8359 0.821801 15.8586 0.986468 15.6939C1.06761 15.6127 1.10102 15.5244 1.09625 15.4218L1.32177 15.4039C1.3349 15.5435 1.28359 15.707 1.13801 15.8526ZM1.75827 15.2323C1.58764 15.403 1.30723 15.3946 1.12824 15.2156C0.949254 15.0366 0.938515 14.7538 1.10915 14.5832C1.21654 14.4758 1.31677 14.4639 1.41701 14.4973L1.31916 14.3994L1.47905 14.2395L2.09954 14.86L1.94323 15.0164L1.8418 14.9149C1.87879 15.0187 1.86924 15.1214 1.75827 15.2323ZM1.28814 15.0533C1.3824 15.1476 1.53633 15.1631 1.63895 15.0605C1.74515 14.9543 1.73202 14.8051 1.63537 14.7085C1.53872 14.6118 1.38717 14.5963 1.28098 14.7025C1.17836 14.8051 1.19148 14.9567 1.28814 15.0533ZM2.19525 14.7643L1.32418 13.8933L1.48527 13.7322L2.35634 14.6032L2.19525 14.7643ZM2.55304 14.4376C2.49099 14.4996 2.39792 14.4972 2.34064 14.4399C2.28456 14.3839 2.28217 14.2908 2.34422 14.2287C2.40627 14.1667 2.49815 14.1703 2.55423 14.2264C2.61151 14.2836 2.61509 14.3755 2.55304 14.4376ZM3.00543 13.9852C2.82763 14.163 2.54006 14.1594 2.35988 13.9792C2.1797 13.799 2.17374 13.5162 2.36227 13.3253C2.47443 13.2108 2.61046 13.163 2.73575 13.1833L2.71308 13.4088C2.64149 13.3945 2.56631 13.4148 2.51142 13.4697C2.4088 13.5723 2.42432 13.7215 2.52097 13.8181C2.61762 13.9148 2.77036 13.9267 2.87298 13.8241C2.93502 13.762 2.94457 13.6904 2.93383 13.6153L3.15219 13.5998C3.1689 13.7334 3.12714 13.8635 3.00543 13.9852ZM3.6023 13.3883C3.41019 13.5804 3.12619 13.5733 2.94721 13.3943C2.76822 13.2153 2.75987 12.9301 2.95198 12.738C3.14409 12.5459 3.42928 12.5542 3.60826 12.7332C3.78725 12.9122 3.79441 13.1962 3.6023 13.3883ZM3.1083 13.2332C3.20495 13.3298 3.35291 13.3442 3.45553 13.2415C3.55815 13.1389 3.54383 12.991 3.44718 12.8943C3.35052 12.7976 3.20137 12.7821 3.09875 12.8848C2.99613 12.9874 3.01164 13.1365 3.1083 13.2332ZM3.98861 12.971L3.36812 12.3505L3.52683 12.1918L3.61751 12.2825C3.58052 12.181 3.60677 12.0832 3.70223 11.9877C3.78934 11.9006 3.90508 11.8684 4.02083 11.903C3.98742 11.7861 4.00532 11.6846 4.1139 11.5761C4.24754 11.4424 4.4492 11.4388 4.60552 11.5952L4.98497 11.9746L4.82388 12.1357L4.48381 11.7956C4.37641 11.6882 4.27857 11.693 4.20578 11.7658C4.13061 11.841 4.1139 11.9269 4.23323 12.0462L4.5733 12.3863L4.41221 12.5474L4.07214 12.2073C3.96475 12.0999 3.86451 12.1071 3.78457 12.187C3.71655 12.255 3.70223 12.3624 3.80962 12.4698L4.1497 12.8099L3.98861 12.971Z" fill="white" fill-opacity="0.03"/>
<path d="M6.48542 10.5051C6.23723 10.7533 5.85658 10.7473 5.61793 10.5087C5.37809 10.2688 5.36139 9.89653 5.61913 9.63879C5.75516 9.50276 5.89119 9.45026 6.05585 9.46458L6.04034 9.68533C5.93772 9.68294 5.84942 9.71874 5.77425 9.79391C5.61316 9.955 5.63822 10.1829 5.79096 10.3356C5.94369 10.4884 6.16921 10.5111 6.33388 10.3464C6.41502 10.2652 6.44843 10.1769 6.44366 10.0743L6.66918 10.0564C6.68231 10.196 6.631 10.3595 6.48542 10.5051ZM7.10568 9.88482C6.93505 10.0555 6.65464 10.0471 6.47565 9.86812C6.29667 9.68913 6.28593 9.40633 6.45656 9.2357C6.56395 9.12831 6.66419 9.11638 6.76442 9.14979L6.66657 9.05194L6.82647 8.89205L7.44695 9.51253L7.29064 9.66885L7.18921 9.56742C7.2262 9.67123 7.21666 9.77385 7.10568 9.88482ZM6.63555 9.70584C6.72981 9.8001 6.88374 9.81562 6.98636 9.713C7.09256 9.6068 7.07943 9.45764 6.98278 9.36099C6.88613 9.26434 6.73459 9.24883 6.62839 9.35502C6.52577 9.45764 6.53889 9.60919 6.63555 9.70584ZM7.54266 9.41682L6.6716 8.54575L6.83268 8.38467L7.70375 9.25573L7.54266 9.41682ZM7.90045 9.09006C7.8384 9.15211 7.74533 9.14972 7.68805 9.09245C7.63197 9.03636 7.62958 8.94329 7.69163 8.88124C7.75368 8.81919 7.84556 8.82277 7.90164 8.87886C7.95892 8.93613 7.9625 9.02801 7.90045 9.09006ZM8.35284 8.63767C8.17504 8.81546 7.88747 8.81188 7.70729 8.63171C7.52711 8.45153 7.52115 8.16873 7.70968 7.97781C7.82184 7.86326 7.95787 7.81553 8.08317 7.83581L8.06049 8.06134C7.9889 8.04702 7.91372 8.0673 7.85884 8.12219C7.75622 8.22481 7.77173 8.37396 7.86838 8.47062C7.96503 8.56727 8.11777 8.5792 8.22039 8.47658C8.28244 8.41453 8.29198 8.34294 8.28124 8.26777L8.49961 8.25225C8.51631 8.3859 8.47455 8.51596 8.35284 8.63767ZM8.94971 8.0408C8.7576 8.23291 8.47361 8.22575 8.29462 8.04676C8.11563 7.86778 8.10728 7.58259 8.29939 7.39048C8.49151 7.19837 8.77669 7.20672 8.95568 7.38571C9.13466 7.56469 9.14182 7.84869 8.94971 8.0408ZM8.45571 7.88568C8.55236 7.98233 8.70032 7.99665 8.80294 7.89403C8.90556 7.79141 8.89124 7.64345 8.79459 7.5468C8.69794 7.45014 8.54878 7.43463 8.44616 7.53725C8.34354 7.63987 8.35906 7.78902 8.45571 7.88568ZM9.33602 7.62346L8.71554 7.00298L8.87424 6.84427L8.96492 6.93496C8.92793 6.83353 8.95419 6.73569 9.04964 6.64023C9.13675 6.55312 9.2525 6.52091 9.36824 6.55551C9.33483 6.43857 9.35273 6.33715 9.46131 6.22856C9.59496 6.09492 9.79661 6.09134 9.95293 6.24765L10.3324 6.6271L10.1713 6.78819L9.83122 6.44812C9.72383 6.34073 9.62598 6.3455 9.55319 6.41829C9.47802 6.49346 9.46131 6.57937 9.58064 6.6987L9.92071 7.03877L9.75962 7.19986L9.41955 6.85979C9.31216 6.75239 9.21193 6.75955 9.13198 6.8395C9.06396 6.90752 9.04964 7.01491 9.15704 7.1223L9.49711 7.46237L9.33602 7.62346Z" fill="white" fill-opacity="0.03"/>
<path d="M11.833 5.1576C11.5848 5.40579 11.2041 5.39983 10.9655 5.16118C10.7256 4.92134 10.7089 4.54904 10.9667 4.2913C11.1027 4.15527 11.2387 4.10277 11.4034 4.11709L11.3879 4.33784C11.2853 4.33545 11.197 4.37125 11.1218 4.44643C10.9607 4.60751 10.9858 4.83542 11.1385 4.98816C11.2912 5.14089 11.5167 5.16356 11.6814 4.9989C11.7626 4.91776 11.796 4.82946 11.7912 4.72684L12.0167 4.70894C12.0298 4.84855 11.9785 5.01202 11.833 5.1576ZM12.4532 4.53734C12.2826 4.70797 12.0022 4.69962 11.8232 4.52063C11.6442 4.34164 11.6335 4.05885 11.8041 3.88821C11.9115 3.78082 12.0117 3.76889 12.112 3.8023L12.0141 3.70445L12.174 3.54456L12.7945 4.16504L12.6382 4.32136L12.5367 4.21993C12.5737 4.32375 12.5642 4.42636 12.4532 4.53734ZM11.9831 4.35835C12.0773 4.45262 12.2313 4.46813 12.3339 4.36551C12.4401 4.25931 12.427 4.11015 12.3303 4.0135C12.2337 3.91685 12.0821 3.90134 11.9759 4.00754C11.8733 4.11015 11.8864 4.2617 11.9831 4.35835ZM12.8902 4.06933L12.0191 3.19827L12.1802 3.03718L13.0513 3.90825L12.8902 4.06933ZM13.248 3.74257C13.1859 3.80462 13.0929 3.80223 13.0356 3.74496C12.9795 3.68888 12.9771 3.5958 13.0392 3.53375C13.1012 3.4717 13.1931 3.47528 13.2492 3.53137C13.3065 3.58864 13.31 3.68052 13.248 3.74257ZM13.7004 3.29018C13.5226 3.46798 13.235 3.4644 13.0548 3.28422C12.8746 3.10404 12.8687 2.82124 13.0572 2.63032C13.1694 2.51577 13.3054 2.46804 13.4307 2.48832L13.408 2.71385C13.3364 2.69953 13.2613 2.71981 13.2064 2.7747C13.1038 2.87732 13.1193 3.02648 13.2159 3.12313C13.3126 3.21978 13.4653 3.23171 13.5679 3.1291C13.63 3.06705 13.6395 2.99545 13.6288 2.92028L13.8471 2.90477C13.8638 3.03841 13.8221 3.16847 13.7004 3.29018ZM14.2972 2.69331C14.1051 2.88542 13.8211 2.87826 13.6422 2.69928C13.4632 2.52029 13.4548 2.2351 13.6469 2.04299C13.839 1.85088 14.1242 1.85923 14.3032 2.03822C14.4822 2.21721 14.4894 2.5012 14.2972 2.69331ZM13.8032 2.53819C13.8999 2.63484 14.0479 2.64916 14.1505 2.54654C14.2531 2.44392 14.2388 2.29596 14.1421 2.19931C14.0455 2.10265 13.8963 2.08714 13.7937 2.18976C13.6911 2.29238 13.7066 2.44154 13.8032 2.53819ZM14.6836 2.27597L14.0631 1.65549L14.2218 1.49679L14.3125 1.58747C14.2755 1.48605 14.3017 1.3882 14.3972 1.29274C14.4843 1.20563 14.6 1.17342 14.7158 1.20802C14.6824 1.09108 14.7003 0.989658 14.8088 0.881072C14.9425 0.747429 15.1441 0.74385 15.3005 0.900164L15.6799 1.27962L15.5188 1.4407L15.1788 1.10063C15.0714 0.993237 14.9735 0.99801 14.9007 1.0708C14.8256 1.14597 14.8088 1.23189 14.9282 1.35121L15.2682 1.69128L15.1072 1.85237L14.7671 1.5123C14.6597 1.40491 14.5595 1.41207 14.4795 1.49201C14.4115 1.56003 14.3972 1.66742 14.5046 1.77481L14.8446 2.11489L14.6836 2.27597Z" fill="white" fill-opacity="0.03"/>
<path d="M17.1805 -0.189905C16.9323 0.0582892 16.5517 0.052323 16.313 -0.186326C16.0732 -0.426167 16.0565 -0.798459 16.3142 -1.0562C16.4502 -1.19223 16.5863 -1.24473 16.7509 -1.23041L16.7354 -1.00966C16.6328 -1.01205 16.5445 -0.976252 16.4693 -0.901078C16.3082 -0.73999 16.3333 -0.512081 16.486 -0.359346C16.6388 -0.206611 16.8643 -0.183939 17.0289 -0.348607C17.1101 -0.429747 17.1435 -0.518047 17.1387 -0.620666L17.3643 -0.638565C17.3774 -0.498955 17.3261 -0.335481 17.1805 -0.189905ZM17.8008 -0.810168C17.6301 -0.639534 17.3497 -0.647887 17.1707 -0.826873C16.9917 -1.00586 16.981 -1.28866 17.1516 -1.45929C17.259 -1.56668 17.3593 -1.57862 17.4595 -1.54521L17.3616 -1.64305L17.5215 -1.80295L18.142 -1.18246L17.9857 -1.02614L17.8843 -1.12757C17.9213 -1.02376 17.9117 -0.921139 17.8008 -0.810168ZM17.3306 -0.989154C17.4249 -0.894888 17.5788 -0.879376 17.6814 -0.981995C17.7876 -1.08819 17.7745 -1.23735 17.6778 -1.334C17.5812 -1.43065 17.4297 -1.44617 17.3235 -1.33997C17.2208 -1.23735 17.234 -1.08581 17.3306 -0.989154ZM18.2377 -1.27817L17.3667 -2.14924L17.5278 -2.31033L18.3988 -1.43926L18.2377 -1.27817ZM18.5955 -1.60493C18.5335 -1.54288 18.4404 -1.54527 18.3831 -1.60255C18.327 -1.65863 18.3247 -1.7517 18.3867 -1.81375C18.4487 -1.8758 18.5406 -1.87222 18.5967 -1.81614C18.654 -1.75886 18.6576 -1.66698 18.5955 -1.60493ZM19.0479 -2.05732C18.8701 -1.87953 18.5825 -1.88311 18.4024 -2.06329C18.2222 -2.24347 18.2162 -2.52627 18.4047 -2.71718C18.5169 -2.83174 18.6529 -2.87946 18.7782 -2.85918L18.7556 -2.63366C18.684 -2.64798 18.6088 -2.62769 18.5539 -2.5728C18.4513 -2.47018 18.4668 -2.32103 18.5634 -2.22437C18.6601 -2.12772 18.8128 -2.11579 18.9155 -2.21841C18.9775 -2.28046 18.9871 -2.35205 18.9763 -2.42723L19.1947 -2.44274C19.2114 -2.30909 19.1696 -2.17903 19.0479 -2.05732ZM19.6448 -2.65419C19.4527 -2.46208 19.1687 -2.46924 18.9897 -2.64823C18.8107 -2.82721 18.8023 -3.1124 18.9945 -3.30451C19.1866 -3.49662 19.4718 -3.48827 19.6507 -3.30928C19.8297 -3.1303 19.8369 -2.84631 19.6448 -2.65419ZM19.1508 -2.80932C19.2474 -2.71266 19.3954 -2.69834 19.498 -2.80096C19.6006 -2.90358 19.5863 -3.05154 19.4897 -3.1482C19.393 -3.24485 19.2438 -3.26036 19.1412 -3.15774C19.0386 -3.05512 19.0541 -2.90597 19.1508 -2.80932ZM20.0311 -3.07153L19.4106 -3.69202L19.5693 -3.85072L19.66 -3.76003C19.623 -3.86146 19.6493 -3.9593 19.7447 -4.05476C19.8318 -4.14187 19.9476 -4.17409 20.0633 -4.13948C20.0299 -4.25642 20.0478 -4.35785 20.1564 -4.46643C20.29 -4.60007 20.4917 -4.60365 20.648 -4.44734L21.0274 -4.06789L20.8664 -3.9068L20.5263 -4.24687C20.4189 -4.35427 20.321 -4.34949 20.2483 -4.27671C20.1731 -4.20153 20.1564 -4.11562 20.2757 -3.99629L20.6158 -3.65622L20.4547 -3.49513L20.1146 -3.83521C20.0072 -3.9426 19.907 -3.93544 19.827 -3.85549C19.759 -3.78748 19.7447 -3.68008 19.8521 -3.57269L20.1922 -3.23262L20.0311 -3.07153Z" fill="white" fill-opacity="0.03"/>
<path d="M-2.79534 22.6143C-3.04353 22.8625 -3.42418 22.8565 -3.66283 22.6179C-3.90267 22.378 -3.91937 22.0057 -3.66163 21.748C-3.5256 21.612 -3.38957 21.5595 -3.22491 21.5738L-3.24042 21.7945C-3.34304 21.7921 -3.43134 21.8279 -3.50651 21.9031C-3.6676 22.0642 -3.64254 22.2921 -3.48981 22.4449C-3.33707 22.5976 -3.11155 22.6203 -2.94688 22.4556C-2.86574 22.3745 -2.83233 22.2862 -2.8371 22.1835L-2.61158 22.1656C-2.59845 22.3052 -2.64976 22.4687 -2.79534 22.6143ZM-2.17508 21.994C-2.34571 22.1647 -2.62612 22.1563 -2.80511 21.9773C-2.9841 21.7983 -2.99483 21.5155 -2.8242 21.3449C-2.71681 21.2375 -2.61658 21.2256 -2.51634 21.259L-2.61419 21.1611L-2.4543 21.0013L-1.83381 21.6217L-1.99012 21.7781L-2.09155 21.6766C-2.05456 21.7804 -2.06411 21.8831 -2.17508 21.994ZM-2.64521 21.815C-2.55095 21.9093 -2.39702 21.9248 -2.2944 21.8222C-2.1882 21.716 -2.20133 21.5669 -2.29798 21.4702C-2.39463 21.3735 -2.54618 21.358 -2.65237 21.4642C-2.75499 21.5669 -2.74187 21.7184 -2.64521 21.815ZM-1.7381 21.526L-2.60917 20.655L-2.44808 20.4939L-1.57701 21.3649L-1.7381 21.526ZM-1.38031 21.1993C-1.44236 21.2613 -1.53543 21.2589 -1.59271 21.2017C-1.64879 21.1456 -1.65118 21.0525 -1.58913 20.9904C-1.52708 20.9284 -1.4352 20.932 -1.37912 20.9881C-1.32184 21.0453 -1.31826 21.1372 -1.38031 21.1993ZM-0.927924 20.7469C-1.10572 20.9247 -1.39329 20.9211 -1.57347 20.7409C-1.75365 20.5607 -1.75961 20.2779 -1.57108 20.087C-1.45892 19.9725 -1.32289 19.9247 -1.1976 19.945L-1.22027 20.1705C-1.29186 20.1562 -1.36704 20.1765 -1.42193 20.2314C-1.52455 20.334 -1.50903 20.4832 -1.41238 20.5798C-1.31573 20.6765 -1.16299 20.6884 -1.06037 20.5858C-0.998325 20.5237 -0.988779 20.4521 -0.999518 20.377L-0.781155 20.3615C-0.76445 20.4951 -0.806213 20.6252 -0.927924 20.7469ZM-0.331051 20.15C-0.523163 20.3421 -0.807155 20.335 -0.986141 20.156C-1.16513 19.977 -1.17348 19.6918 -0.981368 19.4997C-0.789256 19.3076 -0.504071 19.3159 -0.325085 19.4949C-0.146098 19.6739 -0.138939 19.9579 -0.331051 20.15ZM-0.825053 19.9949C-0.728401 20.0915 -0.580439 20.1059 -0.47782 20.0032C-0.375201 19.9006 -0.38952 19.7527 -0.486172 19.656C-0.582825 19.5594 -0.73198 19.5438 -0.834599 19.6465C-0.937218 19.7491 -0.921706 19.8982 -0.825053 19.9949ZM0.0552615 19.7327L-0.565225 19.1122L-0.406523 18.9535L-0.315837 19.0442C-0.352828 18.9427 -0.326576 18.8449 -0.231117 18.7494C-0.14401 18.6623 -0.0282655 18.6301 0.087479 18.6647C0.0540682 18.5478 0.0719669 18.4464 0.180552 18.3378C0.314195 18.2041 0.515853 18.2005 0.672168 18.3569L1.05162 18.7363L0.890531 18.8974L0.550457 18.5573C0.443065 18.4499 0.345219 18.4547 0.272432 18.5275C0.197257 18.6027 0.180552 18.6886 0.299876 18.8079L0.63995 19.148L0.478863 19.3091L0.138788 18.969C0.0313966 18.8616 -0.0688358 18.8688 -0.148783 18.9487C-0.216798 19.0167 -0.231117 19.1241 -0.123725 19.2315L0.216349 19.5716L0.0552615 19.7327Z" fill="white" fill-opacity="0.03"/>
<path d="M2.55219 17.2668C2.304 17.515 1.92336 17.509 1.68471 17.2704C1.44487 17.0305 1.42816 16.6583 1.6859 16.4005C1.82193 16.2645 1.95796 16.212 2.12263 16.2263L2.10712 16.447C2.0045 16.4447 1.9162 16.4805 1.84102 16.5556C1.67993 16.7167 1.70499 16.9446 1.85773 17.0974C2.01046 17.2501 2.23599 17.2728 2.40065 17.1081C2.48179 17.027 2.5152 16.9387 2.51043 16.836L2.73595 16.8181C2.74908 16.9578 2.69777 17.1212 2.55219 17.2668ZM3.17246 16.6465C3.00182 16.8172 2.72141 16.8088 2.54243 16.6298C2.36344 16.4509 2.3527 16.1681 2.52333 15.9974C2.63073 15.89 2.73096 15.8781 2.83119 15.9115L2.73334 15.8137L2.89324 15.6538L3.51372 16.2743L3.35741 16.4306L3.25598 16.3291C3.29297 16.433 3.28343 16.5356 3.17246 16.6465ZM2.70232 16.4676C2.79659 16.5618 2.95051 16.5773 3.05313 16.4747C3.15933 16.3685 3.14621 16.2194 3.04955 16.1227C2.9529 16.0261 2.80136 16.0105 2.69516 16.1167C2.59254 16.2194 2.60567 16.3709 2.70232 16.4676ZM3.60944 16.1785L2.73837 15.3075L2.89946 15.1464L3.77052 16.0175L3.60944 16.1785ZM3.96722 15.8518C3.90517 15.9138 3.8121 15.9114 3.75482 15.8542C3.69874 15.7981 3.69636 15.705 3.7584 15.643C3.82045 15.5809 3.91233 15.5845 3.96842 15.6406C4.02569 15.6978 4.02927 15.7897 3.96722 15.8518ZM4.41961 15.3994C4.24182 15.5772 3.95425 15.5736 3.77407 15.3934C3.59389 15.2132 3.58792 14.9304 3.77645 14.7395C3.88862 14.625 4.02465 14.5772 4.14994 14.5975L4.12727 14.8231C4.05567 14.8087 3.9805 14.829 3.92561 14.8839C3.82299 14.9865 3.8385 15.1357 3.93515 15.2323C4.03181 15.329 4.18454 15.3409 4.28716 15.2383C4.34921 15.1763 4.35875 15.1047 4.34802 15.0295L4.56638 15.014C4.58308 15.1476 4.54132 15.2777 4.41961 15.3994ZM5.01648 14.8025C4.82437 14.9946 4.54038 14.9875 4.36139 14.8085C4.18241 14.6295 4.17405 14.3443 4.36617 14.1522C4.55828 13.9601 4.84346 13.9684 5.02245 14.1474C5.20144 14.3264 5.2086 14.6104 5.01648 14.8025ZM4.52248 14.6474C4.61913 14.744 4.7671 14.7584 4.86971 14.6557C4.97233 14.5531 4.95801 14.4052 4.86136 14.3085C4.76471 14.2119 4.61555 14.1963 4.51293 14.299C4.41032 14.4016 4.42583 14.5507 4.52248 14.6474ZM5.4028 14.3852L4.78231 13.7647L4.94101 13.606L5.0317 13.6967C4.99471 13.5953 5.02096 13.4974 5.11642 13.4019C5.20352 13.3148 5.31927 13.2826 5.43501 13.3172C5.4016 13.2003 5.4195 13.0989 5.52809 12.9903C5.66173 12.8566 5.86339 12.8531 6.0197 13.0094L6.39915 13.3888L6.23807 13.5499L5.89799 13.2098C5.7906 13.1024 5.69275 13.1072 5.61997 13.18C5.54479 13.2552 5.52809 13.3411 5.64741 13.4604L5.98748 13.8005L5.8264 13.9616L5.48632 13.6215C5.37893 13.5141 5.2787 13.5213 5.19875 13.6012C5.13074 13.6692 5.11642 13.7766 5.22381 13.884L5.56388 14.2241L5.4028 14.3852Z" fill="white" fill-opacity="0.03"/>
<path d="M7.89961 11.9193C7.65141 12.1675 7.27077 12.1615 7.03212 11.9229C6.79228 11.683 6.77557 11.3107 7.03331 11.053C7.16934 10.917 7.30537 10.8645 7.47004 10.8788L7.45453 11.0995C7.35191 11.0972 7.26361 11.133 7.18843 11.2081C7.02735 11.3692 7.0524 11.5971 7.20514 11.7499C7.35787 11.9026 7.5834 11.9253 7.74807 11.7606C7.82921 11.6795 7.86262 11.5912 7.85784 11.4885L8.08337 11.4706C8.09649 11.6103 8.04518 11.7737 7.89961 11.9193ZM8.51987 11.299C8.34924 11.4697 8.06882 11.4613 7.88984 11.2823C7.71085 11.1033 7.70011 10.8205 7.87075 10.6499C7.97814 10.5425 8.07837 10.5306 8.1786 10.564L8.08076 10.4662L8.24065 10.3063L8.86114 10.9267L8.70482 11.0831L8.6034 10.9816C8.64039 11.0854 8.63084 11.1881 8.51987 11.299ZM8.04973 11.1201C8.144 11.2143 8.29793 11.2298 8.40055 11.1272C8.50674 11.021 8.49362 10.8719 8.39697 10.7752C8.30031 10.6786 8.14877 10.663 8.04257 10.7692C7.93995 10.8719 7.95308 11.0234 8.04973 11.1201ZM8.95685 10.831L8.08578 9.95997L8.24687 9.79888L9.11794 10.6699L8.95685 10.831ZM9.31463 10.5043C9.25259 10.5663 9.15951 10.5639 9.10224 10.5067C9.04615 10.4506 9.04377 10.3575 9.10582 10.2955C9.16787 10.2334 9.25975 10.237 9.31583 10.2931C9.3731 10.3503 9.37668 10.4422 9.31463 10.5043ZM9.76702 10.0519C9.58923 10.2297 9.30166 10.2261 9.12148 10.0459C8.9413 9.86574 8.93533 9.58294 9.12386 9.39202C9.23603 9.27747 9.37206 9.22974 9.49735 9.25003L9.47468 9.47555C9.40308 9.46123 9.32791 9.48152 9.27302 9.53641C9.1704 9.63902 9.18591 9.78818 9.28257 9.88483C9.37922 9.98149 9.53195 9.99342 9.63457 9.8908C9.69662 9.82875 9.70617 9.75716 9.69543 9.68198L9.91379 9.66647C9.9305 9.80011 9.88873 9.93018 9.76702 10.0519ZM10.3639 9.45501C10.1718 9.64713 9.88779 9.63997 9.70881 9.46098C9.52982 9.28199 9.52147 8.99681 9.71358 8.8047C9.90569 8.61258 10.1909 8.62094 10.3699 8.79992C10.5488 8.97891 10.556 9.2629 10.3639 9.45501ZM9.86989 9.29989C9.96655 9.39654 10.1145 9.41086 10.2171 9.30824C10.3197 9.20563 10.3054 9.05766 10.2088 8.96101C10.1121 8.86436 9.96297 8.84885 9.86035 8.95146C9.75773 9.05408 9.77324 9.20324 9.86989 9.29989ZM10.7502 9.03768L10.1297 8.41719L10.2884 8.25849L10.3791 8.34918C10.3421 8.24775 10.3684 8.1499 10.4638 8.05444C10.5509 7.96734 10.6667 7.93512 10.7824 7.96972C10.749 7.85279 10.7669 7.75136 10.8755 7.64278C11.0091 7.50913 11.2108 7.50555 11.3671 7.66187L11.7466 8.04132L11.5855 8.20241L11.2454 7.86233C11.138 7.75494 11.0402 7.75971 10.9674 7.8325C10.8922 7.90768 10.8755 7.99359 10.9948 8.11291L11.3349 8.45299L11.1738 8.61408L10.8337 8.274C10.7263 8.16661 10.6261 8.17377 10.5462 8.25372C10.4781 8.32173 10.4638 8.42912 10.5712 8.53651L10.9113 8.87659L10.7502 9.03768Z" fill="white" fill-opacity="0.03"/>
<path d="M13.2471 6.57181C12.9989 6.82001 12.6183 6.81404 12.3797 6.57539C12.1398 6.33555 12.1231 5.96326 12.3808 5.70552C12.5169 5.56949 12.6529 5.51699 12.8176 5.53131L12.8021 5.75206C12.6994 5.74967 12.6111 5.78547 12.536 5.86064C12.3749 6.02173 12.3999 6.24964 12.5527 6.40237C12.7054 6.55511 12.9309 6.57778 13.0956 6.41311C13.1767 6.33197 13.2102 6.24367 13.2054 6.14105L13.4309 6.12315C13.444 6.26276 13.3927 6.42624 13.2471 6.57181ZM13.8674 5.95155C13.6968 6.12218 13.4164 6.11383 13.2374 5.93485C13.0584 5.75586 13.0476 5.47306 13.2183 5.30243C13.3257 5.19504 13.4259 5.1831 13.5261 5.21651L13.4283 5.11867L13.5882 4.95877L14.2087 5.57926L14.0524 5.73557L13.9509 5.63415C13.9879 5.73796 13.9784 5.84058 13.8674 5.95155ZM13.3973 5.77256C13.4915 5.86683 13.6455 5.88234 13.7481 5.77972C13.8543 5.67353 13.8412 5.52437 13.7445 5.42772C13.6478 5.33106 13.4963 5.31555 13.3901 5.42175C13.2875 5.52437 13.3006 5.67591 13.3973 5.77256ZM14.3044 5.48355L13.4333 4.61248L13.5944 4.45139L14.4655 5.32246L14.3044 5.48355ZM14.6622 5.15679C14.6001 5.21883 14.507 5.21645 14.4498 5.15917C14.3937 5.10309 14.3913 5.01002 14.4534 4.94797C14.5154 4.88592 14.6073 4.8895 14.6634 4.94558C14.7206 5.00286 14.7242 5.09474 14.6622 5.15679ZM15.1146 4.7044C14.9368 4.88219 14.6492 4.87861 14.469 4.69843C14.2888 4.51825 14.2829 4.23545 14.4714 4.04453C14.5836 3.92998 14.7196 3.88225 14.8449 3.90254L14.8222 4.12806C14.7506 4.11374 14.6754 4.13403 14.6206 4.18892C14.5179 4.29154 14.5334 4.44069 14.6301 4.53734C14.7268 4.634 14.8795 4.64593 14.9821 4.54331C15.0442 4.48126 15.0537 4.40967 15.043 4.33449L15.2613 4.31898C15.278 4.45262 15.2363 4.58269 15.1146 4.7044ZM15.7114 4.10752C15.5193 4.29964 15.2353 4.29248 15.0563 4.11349C14.8774 3.9345 14.869 3.64932 15.0611 3.45721C15.2532 3.2651 15.5384 3.27345 15.7174 3.45243C15.8964 3.63142 15.9035 3.91541 15.7114 4.10752ZM15.2174 3.9524C15.3141 4.04906 15.462 4.06337 15.5647 3.96076C15.6673 3.85814 15.653 3.71018 15.5563 3.61352C15.4597 3.51687 15.3105 3.50136 15.2079 3.60398C15.1053 3.7066 15.1208 3.85575 15.2174 3.9524ZM16.0977 3.69019L15.4773 3.0697L15.636 2.911L15.7266 3.00169C15.6897 2.90026 15.7159 2.80242 15.8114 2.70696C15.8985 2.61985 16.0142 2.58763 16.13 2.62224C16.0965 2.5053 16.1144 2.40387 16.223 2.29529C16.3567 2.16164 16.5583 2.15806 16.7146 2.31438L17.0941 2.69383L16.933 2.85492L16.5929 2.51484C16.4855 2.40745 16.3877 2.41223 16.3149 2.48501C16.2397 2.56019 16.223 2.6461 16.3424 2.76543L16.6824 3.1055L16.5213 3.26659L16.1813 2.92651C16.0739 2.81912 15.9736 2.82628 15.8937 2.90623C15.8257 2.97424 15.8114 3.08163 15.9188 3.18903L16.2588 3.5291L16.0977 3.69019Z" fill="white" fill-opacity="0.03"/>
<path d="M18.5947 1.22431C18.3465 1.4725 17.9658 1.46654 17.7272 1.22789C17.4873 0.988048 17.4706 0.615756 17.7284 0.358016C17.8644 0.221986 18.0004 0.169483 18.1651 0.183802L18.1496 0.404552C18.047 0.402166 17.9587 0.437963 17.8835 0.513137C17.7224 0.674225 17.7475 0.902134 17.9002 1.05487C18.0529 1.2076 18.2785 1.23028 18.4431 1.06561C18.5243 0.984468 18.5577 0.896168 18.5529 0.793549L18.7784 0.77565C18.7916 0.91526 18.7403 1.07873 18.5947 1.22431ZM19.2149 0.604047C19.0443 0.774681 18.7639 0.766328 18.5849 0.587342C18.4059 0.408355 18.3952 0.125557 18.5658 -0.0450767C18.6732 -0.152469 18.7734 -0.164401 18.8737 -0.13099L18.7758 -0.228836L18.9357 -0.388731L19.5562 0.231756L19.3999 0.38807L19.2985 0.286645C19.3355 0.390457 19.3259 0.493076 19.2149 0.604047ZM18.7448 0.425061C18.8391 0.519327 18.993 0.534839 19.0956 0.43222C19.2018 0.326022 19.1887 0.176866 19.092 0.0802137C18.9954 -0.0164389 18.8438 -0.031951 18.7376 0.0742475C18.635 0.176866 18.6481 0.328408 18.7448 0.425061ZM19.6519 0.136044L18.7808 -0.735023L18.9419 -0.89611L19.813 -0.0250433L19.6519 0.136044ZM20.0097 -0.190718C19.9477 -0.128669 19.8546 -0.131055 19.7973 -0.188331C19.7412 -0.244413 19.7388 -0.337486 19.8009 -0.399535C19.8629 -0.461584 19.9548 -0.458004 20.0109 -0.401922C20.0682 -0.344646 20.0718 -0.252766 20.0097 -0.190718ZM20.4621 -0.643106C20.2843 -0.465313 19.9967 -0.468892 19.8165 -0.649072C19.6364 -0.829252 19.6304 -1.11205 19.8189 -1.30297C19.9311 -1.41752 20.0671 -1.46525 20.1924 -1.44496L20.1697 -1.21944C20.0982 -1.23376 20.023 -1.21348 19.9681 -1.15859C19.8655 -1.05597 19.881 -0.906812 19.9776 -0.81016C20.0743 -0.713507 20.227 -0.701575 20.3296 -0.804193C20.3917 -0.866242 20.4012 -0.937837 20.3905 -1.01301L20.6089 -1.02852C20.6256 -0.89488 20.5838 -0.764816 20.4621 -0.643106ZM21.059 -1.23998C20.8669 -1.04787 20.5829 -1.05503 20.4039 -1.23401C20.2249 -1.413 20.2165 -1.69818 20.4086 -1.8903C20.6008 -2.08241 20.8859 -2.07406 21.0649 -1.89507C21.2439 -1.71608 21.2511 -1.43209 21.059 -1.23998ZM20.565 -1.3951C20.6616 -1.29845 20.8096 -1.28413 20.9122 -1.38675C21.0148 -1.48937 21.0005 -1.63733 20.9038 -1.73398C20.8072 -1.83063 20.658 -1.84615 20.5554 -1.74353C20.4528 -1.64091 20.4683 -1.49175 20.565 -1.3951ZM21.4453 -1.65732L20.8248 -2.2778L20.9835 -2.4365L21.0742 -2.34582C21.0372 -2.44724 21.0634 -2.54509 21.1589 -2.64055C21.246 -2.72765 21.3617 -2.75987 21.4775 -2.72527C21.4441 -2.84221 21.462 -2.94363 21.5706 -3.05222C21.7042 -3.18586 21.9059 -3.18944 22.0622 -3.03312L22.4416 -2.65367L22.2805 -2.49259L21.9405 -2.83266C21.8331 -2.94005 21.7352 -2.93528 21.6624 -2.86249C21.5873 -2.78732 21.5706 -2.7014 21.6899 -2.58208L22.03 -2.242L21.8689 -2.08092L21.5288 -2.42099C21.4214 -2.52838 21.3212 -2.52122 21.2412 -2.44128C21.1732 -2.37326 21.1589 -2.26587 21.2663 -2.15848L21.6064 -1.8184L21.4453 -1.65732Z" fill="white" fill-opacity="0.03"/>
<path d="M-1.38115 24.0285C-1.62935 24.2767 -2.00999 24.2707 -2.24864 24.0321C-2.48848 23.7922 -2.50519 23.4199 -2.24745 23.1622C-2.11142 23.0262 -1.97539 22.9737 -1.81072 22.988L-1.82623 23.2087C-1.92885 23.2063 -2.01715 23.2421 -2.09233 23.3173C-2.25342 23.4784 -2.22836 23.7063 -2.07562 23.8591C-1.92289 24.0118 -1.69736 24.0345 -1.5327 23.8698C-1.45156 23.7887 -1.41815 23.7004 -1.42292 23.5977L-1.1974 23.5798C-1.18427 23.7194 -1.23558 23.8829 -1.38115 24.0285ZM-0.760892 23.4082C-0.931526 23.5789 -1.21194 23.5705 -1.39092 23.3915C-1.56991 23.2125 -1.58065 22.9297 -1.41002 22.7591C-1.30262 22.6517 -1.20239 22.6398 -1.10216 22.6732L-1.20001 22.5753L-1.04011 22.4155L-0.419625 23.0359L-0.57594 23.1923L-0.677365 23.0908C-0.640375 23.1946 -0.649921 23.2973 -0.760892 23.4082ZM-1.23103 23.2292C-1.13676 23.3235 -0.982835 23.339 -0.880217 23.2364C-0.774018 23.1302 -0.787144 22.9811 -0.883796 22.8844C-0.980449 22.7877 -1.13199 22.7722 -1.23819 22.8784C-1.34081 22.9811 -1.32768 23.1326 -1.23103 23.2292ZM-0.323914 22.9402L-1.19498 22.0692L-1.03389 21.9081L-0.162826 22.7791L-0.323914 22.9402ZM0.0338726 22.6135C-0.0281761 22.6755 -0.121249 22.6731 -0.178525 22.6159C-0.234607 22.5598 -0.236994 22.4667 -0.174945 22.4046C-0.112896 22.3426 -0.0210166 22.3462 0.0350658 22.4023C0.0923414 22.4595 0.0959212 22.5514 0.0338726 22.6135ZM0.486261 22.1611C0.308468 22.3389 0.020896 22.3353 -0.159284 22.1551C-0.339463 21.9749 -0.345429 21.6921 -0.156897 21.5012C-0.0447323 21.3867 0.0912974 21.3389 0.216588 21.3592L0.193916 21.5847C0.122322 21.5704 0.0471474 21.5907 -0.00774179 21.6456C-0.110361 21.7482 -0.0948485 21.8974 0.00180413 21.994C0.0984568 22.0907 0.251192 22.1026 0.353811 22C0.415859 21.9379 0.425405 21.8663 0.414666 21.7912L0.63303 21.7757C0.649735 21.9093 0.607971 22.0394 0.486261 22.1611ZM1.08313 21.5642C0.891022 21.7563 0.60703 21.7492 0.428043 21.5702C0.249057 21.3912 0.240704 21.106 0.432816 20.9139C0.624929 20.7218 0.910114 20.7301 1.0891 20.9091C1.26809 21.0881 1.27525 21.3721 1.08313 21.5642ZM0.589131 21.4091C0.685784 21.5057 0.833746 21.5201 0.936365 21.4174C1.03898 21.3148 1.02466 21.1669 0.928012 21.0702C0.83136 20.9736 0.682204 20.958 0.579585 21.0607C0.476966 21.1633 0.492479 21.3124 0.589131 21.4091ZM1.46945 21.1469L0.84896 20.5264L1.00766 20.3677L1.09835 20.4584C1.06136 20.3569 1.08761 20.2591 1.18307 20.1636C1.27017 20.0765 1.38592 20.0443 1.50166 20.0789C1.46825 19.962 1.48615 19.8606 1.59474 19.752C1.72838 19.6183 1.93004 19.6147 2.08635 19.7711L2.4658 20.1505L2.30472 20.3116L1.96464 19.9715C1.85725 19.8641 1.7594 19.8689 1.68662 19.9417C1.61144 20.0169 1.59474 20.1028 1.71406 20.2221L2.05413 20.5622L1.89305 20.7233L1.55297 20.3832C1.44558 20.2758 1.34535 20.283 1.2654 20.3629C1.19739 20.4309 1.18307 20.5383 1.29046 20.6457L1.63053 20.9858L1.46945 21.1469Z" fill="white" fill-opacity="0.03"/>
<path d="M3.96638 18.681C3.71818 18.9292 3.33754 18.9232 3.09889 18.6846C2.85905 18.4447 2.84234 18.0725 3.10009 17.8147C3.23611 17.6787 3.37214 17.6262 3.53681 17.6405L3.5213 17.8612C3.41868 17.8589 3.33038 17.8947 3.25521 17.9698C3.09412 18.1309 3.11918 18.3588 3.27191 18.5116C3.42465 18.6643 3.65017 18.687 3.81484 18.5223C3.89598 18.4412 3.92939 18.3529 3.92462 18.2502L4.15014 18.2323C4.16326 18.372 4.11196 18.5354 3.96638 18.681ZM4.58664 18.0607C4.41601 18.2314 4.1356 18.223 3.95661 18.044C3.77762 17.8651 3.76688 17.5823 3.93752 17.4116C4.04491 17.3042 4.14514 17.2923 4.24537 17.3257L4.14753 17.2279L4.30742 17.068L4.92791 17.6885L4.77159 17.8448L4.67017 17.7433C4.70716 17.8472 4.69761 17.9498 4.58664 18.0607ZM4.1165 17.8818C4.21077 17.976 4.3647 17.9915 4.46732 17.8889C4.57352 17.7827 4.56039 17.6336 4.46374 17.5369C4.36709 17.4403 4.21554 17.4247 4.10934 17.5309C4.00673 17.6336 4.01985 17.7851 4.1165 17.8818ZM5.02362 17.5927L4.15255 16.7217L4.31364 16.5606L5.18471 17.4317L5.02362 17.5927ZM5.38141 17.266C5.31936 17.328 5.22629 17.3256 5.16901 17.2684C5.11293 17.2123 5.11054 17.1192 5.17259 17.0572C5.23464 16.9951 5.32652 16.9987 5.3826 17.0548C5.43988 17.112 5.44346 17.2039 5.38141 17.266ZM5.83379 16.8136C5.656 16.9914 5.36843 16.9878 5.18825 16.8076C5.00807 16.6274 5.0021 16.3446 5.19064 16.1537C5.3028 16.0392 5.43883 15.9914 5.56412 16.0117L5.54145 16.2373C5.46986 16.2229 5.39468 16.2432 5.33979 16.2981C5.23717 16.4007 5.25269 16.5499 5.34934 16.6465C5.44599 16.7432 5.59873 16.7551 5.70134 16.6525C5.76339 16.5905 5.77294 16.5189 5.7622 16.4437L5.98056 16.4282C5.99727 16.5618 5.95551 16.6919 5.83379 16.8136ZM6.43067 16.2167C6.23856 16.4088 5.95456 16.4017 5.77558 16.2227C5.59659 16.0437 5.58824 15.7585 5.78035 15.5664C5.97246 15.3743 6.25765 15.3826 6.43663 15.5616C6.61562 15.7406 6.62278 16.0246 6.43067 16.2167ZM5.93667 16.0616C6.03332 16.1582 6.18128 16.1726 6.2839 16.0699C6.38652 15.9673 6.3722 15.8194 6.27555 15.7227C6.17889 15.6261 6.02974 15.6105 5.92712 15.7132C5.8245 15.8158 5.84001 15.9649 5.93667 16.0616ZM6.81698 15.7994L6.19649 15.1789L6.3552 15.0202L6.44588 15.1109C6.40889 15.0095 6.43514 14.9116 6.5306 14.8161C6.61771 14.729 6.73345 14.6968 6.8492 14.7314C6.81579 14.6145 6.83369 14.5131 6.94227 14.4045C7.07591 14.2708 7.27757 14.2673 7.43389 14.4236L7.81334 14.803L7.65225 14.9641L7.31218 14.624C7.20478 14.5166 7.10694 14.5214 7.03415 14.5942C6.95898 14.6694 6.94227 14.7553 7.06159 14.8746L7.40167 15.2147L7.24058 15.3758L6.90051 15.0357C6.79312 14.9283 6.69288 14.9355 6.61294 15.0154C6.54492 15.0834 6.5306 15.1908 6.63799 15.2982L6.97807 15.6383L6.81698 15.7994Z" fill="white" fill-opacity="0.03"/>
<path d="M9.31379 13.3335C9.0656 13.5817 8.68495 13.5757 8.4463 13.3371C8.20646 13.0972 8.18976 12.7249 8.4475 12.4672C8.58353 12.3312 8.71956 12.2787 8.88422 12.293L8.86871 12.5137C8.76609 12.5114 8.67779 12.5472 8.60262 12.6223C8.44153 12.7834 8.46659 13.0113 8.61932 13.1641C8.77206 13.3168 8.99758 13.3395 9.16225 13.1748C9.24339 13.0937 9.2768 13.0054 9.27203 12.9027L9.49755 12.8848C9.51068 13.0245 9.45937 13.1879 9.31379 13.3335ZM9.93405 12.7132C9.76342 12.8839 9.48301 12.8755 9.30402 12.6965C9.12504 12.5175 9.1143 12.2347 9.28493 12.0641C9.39232 11.9567 9.49255 11.9448 9.59279 11.9782L9.49494 11.8804L9.65484 11.7205L10.2753 12.3409L10.119 12.4973L10.0176 12.3958C10.0546 12.4996 10.045 12.6023 9.93405 12.7132ZM9.46392 12.5343C9.55818 12.6285 9.71211 12.644 9.81473 12.5414C9.92093 12.4352 9.9078 12.2861 9.81115 12.1894C9.7145 12.0928 9.56296 12.0772 9.45676 12.1834C9.35414 12.2861 9.36726 12.4376 9.46392 12.5343ZM10.371 12.2452L9.49997 11.3742L9.66105 11.2131L10.5321 12.0841L10.371 12.2452ZM10.7288 11.9185C10.6668 11.9805 10.5737 11.9781 10.5164 11.9209C10.4603 11.8648 10.458 11.7717 10.52 11.7097C10.582 11.6476 10.6739 11.6512 10.73 11.7073C10.7873 11.7645 10.7909 11.8564 10.7288 11.9185ZM11.1812 11.4661C11.0034 11.6439 10.7158 11.6403 10.5357 11.4601C10.3555 11.2799 10.3495 10.9971 10.538 10.8062C10.6502 10.6917 10.7862 10.6439 10.9115 10.6642L10.8889 10.8897C10.8173 10.8754 10.7421 10.8957 10.6872 10.9506C10.5846 11.0532 10.6001 11.2024 10.6968 11.299C10.7934 11.3957 10.9461 11.4076 11.0488 11.305C11.1108 11.2429 11.1204 11.1714 11.1096 11.0962L11.328 11.0807C11.3447 11.2143 11.3029 11.3444 11.1812 11.4661ZM11.7781 10.8692C11.586 11.0613 11.302 11.0542 11.123 10.8752C10.944 10.6962 10.9357 10.411 11.1278 10.2189C11.3199 10.0268 11.6051 10.0351 11.784 10.2141C11.963 10.3931 11.9702 10.6771 11.7781 10.8692ZM11.2841 10.7141C11.3807 10.8107 11.5287 10.8251 11.6313 10.7224C11.7339 10.6198 11.7196 10.4719 11.623 10.3752C11.5263 10.2786 11.3772 10.263 11.2745 10.3657C11.1719 10.4683 11.1874 10.6174 11.2841 10.7141ZM12.1644 10.4519L11.5439 9.83139L11.7026 9.67269L11.7933 9.76338C11.7563 9.66195 11.7826 9.5641 11.878 9.46864C11.9651 9.38154 12.0809 9.34932 12.1966 9.38392C12.1632 9.26699 12.1811 9.16556 12.2897 9.05698C12.4233 8.92333 12.625 8.91975 12.7813 9.07607L13.1608 9.45552L12.9997 9.61661L12.6596 9.27653C12.5522 9.16914 12.4544 9.17391 12.3816 9.2467C12.3064 9.32188 12.2897 9.40779 12.409 9.52711L12.7491 9.86719L12.588 10.0283L12.2479 9.6882C12.1405 9.58081 12.0403 9.58797 11.9603 9.66792C11.8923 9.73593 11.878 9.84332 11.9854 9.95071L12.3255 10.2908L12.1644 10.4519Z" fill="white" fill-opacity="0.03"/>
<path d="M14.6613 7.98601C14.4131 8.23421 14.0325 8.22824 13.7938 7.98959C13.554 7.74975 13.5373 7.37746 13.795 7.11972C13.9311 6.98369 14.0671 6.93119 14.2318 6.94551L14.2162 7.16626C14.1136 7.16387 14.0253 7.19967 13.9502 7.27484C13.7891 7.43593 13.8141 7.66384 13.9669 7.81657C14.1196 7.96931 14.3451 7.99198 14.5098 7.82731C14.5909 7.74617 14.6243 7.65787 14.6196 7.55525L14.8451 7.53735C14.8582 7.67696 14.8069 7.84044 14.6613 7.98601ZM15.2816 7.36575C15.111 7.53638 14.8305 7.52803 14.6516 7.34905C14.4726 7.17006 14.4618 6.88726 14.6325 6.71663C14.7399 6.60923 14.8401 6.5973 14.9403 6.63071L14.8425 6.53287L15.0024 6.37297L15.6229 6.99346L15.4665 7.14977L15.3651 7.04835C15.4021 7.15216 15.3926 7.25478 15.2816 7.36575ZM14.8115 7.18676C14.9057 7.28103 15.0596 7.29654 15.1623 7.19392C15.2685 7.08773 15.2553 6.93857 15.1587 6.84192C15.062 6.74526 14.9105 6.72975 14.8043 6.83595C14.7017 6.93857 14.7148 7.09011 14.8115 7.18676ZM15.7186 6.89775L14.8475 6.02668L15.0086 5.86559L15.8797 6.73666L15.7186 6.89775ZM16.0764 6.57099C16.0143 6.63303 15.9212 6.63065 15.864 6.57337C15.8079 6.51729 15.8055 6.42422 15.8675 6.36217C15.9296 6.30012 16.0215 6.3037 16.0775 6.35978C16.1348 6.41706 16.1384 6.50894 16.0764 6.57099ZM16.5287 6.1186C16.3509 6.29639 16.0634 6.29281 15.8832 6.11263C15.703 5.93245 15.6971 5.64965 15.8856 5.45873C15.9977 5.34418 16.1338 5.29645 16.2591 5.31674L16.2364 5.54226C16.1648 5.52794 16.0896 5.54823 16.0347 5.60312C15.9321 5.70574 15.9476 5.85489 16.0443 5.95154C16.1409 6.0482 16.2937 6.06013 16.3963 5.95751C16.4583 5.89546 16.4679 5.82387 16.4571 5.74869L16.6755 5.73318C16.6922 5.86682 16.6505 5.99689 16.5287 6.1186ZM17.1256 5.52172C16.9335 5.71384 16.6495 5.70668 16.4705 5.52769C16.2915 5.3487 16.2832 5.06352 16.4753 4.87141C16.6674 4.6793 16.9526 4.68765 17.1316 4.86663C17.3106 5.04562 17.3177 5.32961 17.1256 5.52172ZM16.6316 5.3666C16.7283 5.46326 16.8762 5.47757 16.9788 5.37496C17.0815 5.27234 17.0671 5.12437 16.9705 5.02772C16.8738 4.93107 16.7247 4.91556 16.6221 5.01818C16.5194 5.1208 16.535 5.26995 16.6316 5.3666ZM17.5119 5.10439L16.8914 4.4839L17.0501 4.3252L17.1408 4.41589C17.1038 4.31446 17.1301 4.21662 17.2255 4.12116C17.3127 4.03405 17.4284 4.00183 17.5441 4.03644C17.5107 3.9195 17.5286 3.81807 17.6372 3.70949C17.7709 3.57584 17.9725 3.57226 18.1288 3.72858L18.5083 4.10803L18.3472 4.26912L18.0071 3.92904C17.8997 3.82165 17.8019 3.82643 17.7291 3.89921C17.6539 3.97439 17.6372 4.0603 17.7565 4.17963L18.0966 4.5197L17.9355 4.68079L17.5955 4.34071C17.4881 4.23332 17.3878 4.24048 17.3079 4.32043C17.2399 4.38844 17.2255 4.49583 17.3329 4.60323L17.673 4.9433L17.5119 5.10439Z" fill="white" fill-opacity="0.03"/>
<path d="M20.0089 2.63851C19.7607 2.8867 19.38 2.88074 19.1414 2.64209C18.9015 2.40225 18.8848 2.02996 19.1426 1.77222C19.2786 1.63619 19.4146 1.58368 19.5793 1.598L19.5638 1.81875C19.4612 1.81637 19.3729 1.85216 19.2977 1.92734C19.1366 2.08842 19.1617 2.31633 19.3144 2.46907C19.4671 2.6218 19.6927 2.64448 19.8573 2.47981C19.9385 2.39867 19.9719 2.31037 19.9671 2.20775L20.1926 2.18985C20.2057 2.32946 20.1544 2.49293 20.0089 2.63851ZM20.6291 2.01825C20.4585 2.18888 20.1781 2.18053 19.9991 2.00154C19.8201 1.82256 19.8094 1.53976 19.98 1.36912C20.0874 1.26173 20.1876 1.2498 20.2879 1.28321L20.19 1.18536L20.3499 1.02547L20.9704 1.64596L20.8141 1.80227L20.7126 1.70084C20.7496 1.80466 20.7401 1.90728 20.6291 2.01825ZM20.159 1.83926C20.2533 1.93353 20.4072 1.94904 20.5098 1.84642C20.616 1.74022 20.6029 1.59107 20.5062 1.49441C20.4096 1.39776 20.258 1.38225 20.1518 1.48845C20.0492 1.59107 20.0623 1.74261 20.159 1.83926ZM21.0661 1.55024L20.195 0.679177L20.3561 0.518089L21.2272 1.38916L21.0661 1.55024ZM21.4239 1.22348C21.3618 1.28553 21.2688 1.28314 21.2115 1.22587C21.1554 1.16979 21.153 1.07671 21.2151 1.01466C21.2771 0.952616 21.369 0.956196 21.4251 1.01228C21.4824 1.06955 21.4859 1.16143 21.4239 1.22348ZM21.8763 0.771094C21.6985 0.948887 21.4109 0.945308 21.2307 0.765128C21.0506 0.584948 21.0446 0.30215 21.2331 0.111231C21.3453 -0.00332041 21.4813 -0.0510501 21.6066 -0.030765L21.5839 0.194758C21.5123 0.180439 21.4372 0.200724 21.3823 0.255613C21.2797 0.358232 21.2952 0.507387 21.3918 0.60404C21.4885 0.700693 21.6412 0.712625 21.7438 0.610006C21.8059 0.547958 21.8154 0.476363 21.8047 0.401189L22.023 0.385677C22.0397 0.51932 21.998 0.649383 21.8763 0.771094ZM22.4731 0.174221C22.281 0.366333 21.997 0.359174 21.8181 0.180187C21.6391 0.00120091 21.6307 -0.283984 21.8228 -0.476096C22.0149 -0.668208 22.3001 -0.659856 22.4791 -0.480869C22.6581 -0.301883 22.6653 -0.017891 22.4731 0.174221ZM21.9791 0.0190996C22.0758 0.115752 22.2238 0.130071 22.3264 0.0274522C22.429 -0.0751666 22.4147 -0.223129 22.318 -0.319781C22.2214 -0.416434 22.0722 -0.431946 21.9696 -0.329327C21.867 -0.226708 21.8825 -0.0775531 21.9791 0.0190996ZM22.8595 -0.243116L22.239 -0.863602L22.3977 -1.0223L22.4884 -0.931617C22.4514 -1.03304 22.4776 -1.13089 22.5731 -1.22635C22.6602 -1.31345 22.7759 -1.34567 22.8917 -1.31107C22.8583 -1.42801 22.8762 -1.52943 22.9848 -1.63802C23.1184 -1.77166 23.3201 -1.77524 23.4764 -1.61892L23.8558 -1.23947L23.6947 -1.07839L23.3547 -1.41846C23.2473 -1.52585 23.1494 -1.52108 23.0766 -1.44829C23.0015 -1.37312 22.9848 -1.2872 23.1041 -1.16788L23.4441 -0.827804L23.2831 -0.666717L22.943 -1.00679C22.8356 -1.11418 22.7354 -1.10702 22.6554 -1.02708C22.5874 -0.959061 22.5731 -0.851669 22.6805 -0.744277L23.0205 -0.404203L22.8595 -0.243116Z" fill="white" fill-opacity="0.03"/>
<path d="M0.0331519 25.4427C-0.215043 25.6909 -0.595687 25.6849 -0.834336 25.4463C-1.07418 25.2064 -1.09088 24.8342 -0.833142 24.5764C-0.697113 24.4404 -0.561083 24.3879 -0.396416 24.4022L-0.411928 24.623C-0.514547 24.6206 -0.602846 24.6564 -0.678021 24.7315C-0.839109 24.8926 -0.81405 25.1205 -0.661315 25.2733C-0.50858 25.426 -0.283057 25.4487 -0.11839 25.284C-0.0372494 25.2029 -0.00383864 25.1146 -0.0086116 25.0119L0.216911 24.994C0.230037 25.1337 0.178727 25.2971 0.0331519 25.4427ZM0.653414 24.8224C0.482781 24.9931 0.202369 24.9847 0.0233822 24.8057C-0.155604 24.6268 -0.166343 24.344 0.00429029 24.1733C0.111682 24.0659 0.211915 24.054 0.312147 24.0874L0.214301 23.9896L0.374196 23.8297L0.994682 24.4502L0.838367 24.6065L0.736941 24.505C0.773932 24.6089 0.764386 24.7115 0.653414 24.8224ZM0.183277 24.6435C0.277543 24.7377 0.431471 24.7532 0.53409 24.6506C0.640289 24.5444 0.627163 24.3953 0.53051 24.2986C0.433858 24.202 0.282316 24.1864 0.176117 24.2926C0.0734984 24.3953 0.086624 24.5468 0.183277 24.6435ZM1.09039 24.3544L0.219326 23.4834L0.380413 23.3223L1.25148 24.1934L1.09039 24.3544ZM1.44818 24.0277C1.38613 24.0897 1.29306 24.0873 1.23578 24.0301C1.1797 23.974 1.17731 23.8809 1.23936 23.8189C1.30141 23.7568 1.39329 23.7604 1.44937 23.8165C1.50665 23.8738 1.51023 23.9656 1.44818 24.0277ZM1.90057 23.5753C1.72277 23.7531 1.4352 23.7495 1.25502 23.5693C1.07484 23.3891 1.06888 23.1063 1.25741 22.9154C1.36957 22.8009 1.5056 22.7531 1.63089 22.7734L1.60822 22.999C1.53663 22.9846 1.46145 23.0049 1.40656 23.0598C1.30395 23.1624 1.31946 23.3116 1.41611 23.4082C1.51276 23.5049 1.6655 23.5168 1.76812 23.4142C1.83017 23.3522 1.83971 23.2806 1.82897 23.2054L2.04734 23.1899C2.06404 23.3235 2.02228 23.4536 1.90057 23.5753ZM2.49744 22.9784C2.30533 23.1705 2.02134 23.1634 1.84235 22.9844C1.66336 22.8054 1.65501 22.5202 1.84712 22.3281C2.03924 22.136 2.32442 22.1443 2.50341 22.3233C2.68239 22.5023 2.68955 22.7863 2.49744 22.9784ZM2.00344 22.8233C2.10009 22.92 2.24805 22.9343 2.35067 22.8317C2.45329 22.729 2.43897 22.5811 2.34232 22.4844C2.24567 22.3878 2.09651 22.3723 1.99389 22.4749C1.89127 22.5775 1.90679 22.7266 2.00344 22.8233ZM2.88375 22.5611L2.26327 21.9406L2.42197 21.7819L2.51265 21.8726C2.47566 21.7712 2.50192 21.6733 2.59737 21.5779C2.68448 21.4907 2.80023 21.4585 2.91597 21.4931C2.88256 21.3762 2.90046 21.2748 3.00904 21.1662C3.14269 21.0325 3.34434 21.029 3.50066 21.1853L3.88011 21.5647L3.71902 21.7258L3.37895 21.3857C3.27156 21.2783 3.17371 21.2831 3.10092 21.3559C3.02575 21.4311 3.00904 21.517 3.12837 21.6363L3.46844 21.9764L3.30735 22.1375L2.96728 21.7974C2.85989 21.69 2.75966 21.6972 2.67971 21.7771C2.61169 21.8451 2.59737 21.9525 2.70477 22.0599L3.04484 22.4L2.88375 22.5611Z" fill="white" fill-opacity="0.03"/>
<path d="M5.38069 20.0952C5.13249 20.3434 4.75185 20.3374 4.5132 20.0988C4.27336 19.859 4.25665 19.4867 4.51439 19.2289C4.65042 19.0929 4.78645 19.0404 4.95112 19.0547L4.93561 19.2755C4.83299 19.2731 4.74469 19.3089 4.66951 19.384C4.50843 19.5451 4.53348 19.773 4.68622 19.9258C4.83895 20.0785 5.06448 20.1012 5.22914 19.9365C5.31028 19.8554 5.3437 19.7671 5.33892 19.6645L5.56445 19.6466C5.57757 19.7862 5.52626 19.9496 5.38069 20.0952ZM6.00095 19.475C5.83031 19.6456 5.5499 19.6372 5.37092 19.4583C5.19193 19.2793 5.18119 18.9965 5.35182 18.8258C5.45922 18.7184 5.55945 18.7065 5.65968 18.7399L5.56184 18.6421L5.72173 18.4822L6.34222 19.1027L6.1859 19.259L6.08448 19.1576C6.12147 19.2614 6.11192 19.364 6.00095 19.475ZM5.53081 19.296C5.62508 19.3902 5.77901 19.4057 5.88162 19.3031C5.98782 19.1969 5.9747 19.0478 5.87804 18.9511C5.78139 18.8545 5.62985 18.839 5.52365 18.9452C5.42103 19.0478 5.43416 19.1993 5.53081 19.296ZM6.43793 19.007L5.56686 18.1359L5.72795 17.9748L6.59901 18.8459L6.43793 19.007ZM6.79571 18.6802C6.73366 18.7422 6.64059 18.7399 6.58332 18.6826C6.52723 18.6265 6.52485 18.5334 6.5869 18.4714C6.64894 18.4093 6.74082 18.4129 6.79691 18.469C6.85418 18.5263 6.85776 18.6181 6.79571 18.6802ZM7.2481 18.2278C7.07031 18.4056 6.78274 18.402 6.60256 18.2218C6.42238 18.0417 6.41641 17.7589 6.60494 17.5679C6.71711 17.4534 6.85314 17.4057 6.97843 17.4259L6.95576 17.6515C6.88416 17.6371 6.80899 17.6574 6.7541 17.7123C6.65148 17.8149 6.66699 17.9641 6.76364 18.0608C6.8603 18.1574 7.01303 18.1693 7.11565 18.0667C7.1777 18.0047 7.18725 17.9331 7.17651 17.8579L7.39487 17.8424C7.41158 17.976 7.36981 18.1061 7.2481 18.2278ZM7.84497 17.6309C7.65286 17.823 7.36887 17.8159 7.18988 17.6369C7.0109 17.4579 7.00255 17.1727 7.19466 16.9806C7.38677 16.7885 7.67195 16.7969 7.85094 16.9758C8.02993 17.1548 8.03709 17.4388 7.84497 17.6309ZM7.35097 17.4758C7.44762 17.5725 7.59559 17.5868 7.69821 17.4842C7.80082 17.3815 7.78651 17.2336 7.68985 17.1369C7.5932 17.0403 7.44405 17.0248 7.34143 17.1274C7.23881 17.23 7.25432 17.3792 7.35097 17.4758ZM8.23129 17.2136L7.6108 16.5931L7.7695 16.4344L7.86019 16.5251C7.8232 16.4237 7.84945 16.3258 7.94491 16.2304C8.03202 16.1433 8.14776 16.111 8.2635 16.1456C8.23009 16.0287 8.24799 15.9273 8.35658 15.8187C8.49022 15.6851 8.69188 15.6815 8.84819 15.8378L9.22764 16.2172L9.06656 16.3783L8.72648 16.0383C8.61909 15.9309 8.52124 15.9356 8.44846 16.0084C8.37328 16.0836 8.35658 16.1695 8.4759 16.2888L8.81598 16.6289L8.65489 16.79L8.31481 16.4499C8.20742 16.3425 8.10719 16.3497 8.02724 16.4296C7.95923 16.4976 7.94491 16.605 8.0523 16.7124L8.39237 17.0525L8.23129 17.2136Z" fill="white" fill-opacity="0.03"/>
<path d="M10.7281 14.7477C10.4799 14.9959 10.0993 14.9899 9.86061 14.7513C9.62077 14.5115 9.60406 14.1392 9.8618 13.8814C9.99783 13.7454 10.1339 13.6929 10.2985 13.7072L10.283 13.928C10.1804 13.9256 10.0921 13.9614 10.0169 14.0365C9.85584 14.1976 9.8809 14.4255 10.0336 14.5783C10.1864 14.731 10.4119 14.7537 10.5766 14.589C10.6577 14.5079 10.6911 14.4196 10.6863 14.317L10.9119 14.2991C10.925 14.4387 10.8737 14.6021 10.7281 14.7477ZM11.3484 14.1275C11.1777 14.2981 10.8973 14.2897 10.7183 14.1107C10.5393 13.9318 10.5286 13.649 10.6992 13.4783C10.8066 13.3709 10.9069 13.359 11.0071 13.3924L10.9092 13.2946L11.0691 13.1347L11.6896 13.7552L11.5333 13.9115L11.4319 13.8101C11.4689 13.9139 11.4593 14.0165 11.3484 14.1275ZM10.8782 13.9485C10.9725 14.0427 11.1264 14.0582 11.229 13.9556C11.3352 13.8494 11.3221 13.7003 11.2255 13.6036C11.1288 13.507 10.9773 13.4915 10.8711 13.5977C10.7684 13.7003 10.7816 13.8518 10.8782 13.9485ZM11.7853 13.6595L10.9143 12.7884L11.0754 12.6273L11.9464 13.4984L11.7853 13.6595ZM12.1431 13.3327C12.0811 13.3947 11.988 13.3924 11.9307 13.3351C11.8746 13.279 11.8723 13.1859 11.9343 13.1239C11.9964 13.0618 12.0882 13.0654 12.1443 13.1215C12.2016 13.1788 12.2052 13.2706 12.1431 13.3327ZM12.5955 12.8803C12.4177 13.0581 12.1301 13.0545 11.95 12.8743C11.7698 12.6942 11.7638 12.4114 11.9524 12.2204C12.0645 12.1059 12.2006 12.0582 12.3258 12.0784L12.3032 12.304C12.2316 12.2896 12.1564 12.3099 12.1015 12.3648C11.9989 12.4674 12.0144 12.6166 12.1111 12.7132C12.2077 12.8099 12.3604 12.8218 12.4631 12.7192C12.5251 12.6572 12.5347 12.5856 12.5239 12.5104L12.7423 12.4949C12.759 12.6285 12.7172 12.7586 12.5955 12.8803ZM13.1924 12.2834C13.0003 12.4755 12.7163 12.4684 12.5373 12.2894C12.3583 12.1104 12.35 11.8252 12.5421 11.6331C12.7342 11.441 13.0194 11.4494 13.1984 11.6283C13.3773 11.8073 13.3845 12.0913 13.1924 12.2834ZM12.6984 12.1283C12.795 12.225 12.943 12.2393 13.0456 12.1367C13.1482 12.034 13.1339 11.8861 13.0373 11.7894C12.9406 11.6928 12.7915 11.6773 12.6888 11.7799C12.5862 11.8825 12.6017 12.0317 12.6984 12.1283ZM13.5787 11.8661L12.9582 11.2456L13.1169 11.0869L13.2076 11.1776C13.1706 11.0762 13.1969 10.9783 13.2923 10.8829C13.3794 10.7958 13.4952 10.7635 13.6109 10.7981C13.5775 10.6812 13.5954 10.5798 13.704 10.4712C13.8376 10.3375 14.0393 10.334 14.1956 10.4903L14.5751 10.8697L14.414 11.0308L14.0739 10.6907C13.9665 10.5834 13.8687 10.5881 13.7959 10.6609C13.7207 10.7361 13.704 10.822 13.8233 10.9413L14.1634 11.2814L14.0023 11.4425L13.6622 11.1024C13.5548 10.995 13.4546 11.0022 13.3747 11.0821C13.3066 11.1501 13.2923 11.2575 13.3997 11.3649L13.7398 11.705L13.5787 11.8661Z" fill="white" fill-opacity="0.03"/>
<path d="M16.0756 9.40023C15.8274 9.64842 15.4468 9.64246 15.2081 9.40381C14.9683 9.16397 14.9516 8.79167 15.2093 8.53393C15.3454 8.3979 15.4814 8.3454 15.6461 8.35972L15.6306 8.58047C15.5279 8.57808 15.4396 8.61388 15.3645 8.68906C15.2034 8.85014 15.2284 9.07805 15.3812 9.23079C15.5339 9.38352 15.7594 9.40619 15.9241 9.24153C16.0052 9.16039 16.0386 9.07209 16.0339 8.96947L16.2594 8.95157C16.2725 9.09118 16.2212 9.25465 16.0756 9.40023ZM16.6959 8.77997C16.5253 8.9506 16.2448 8.94225 16.0659 8.76326C15.8869 8.58427 15.8761 8.30148 16.0468 8.13084C16.1542 8.02345 16.2544 8.01152 16.3546 8.04493L16.2568 7.94708L16.4167 7.78719L17.0372 8.40767L16.8808 8.56399L16.7794 8.46256C16.8164 8.56638 16.8069 8.66899 16.6959 8.77997ZM16.2258 8.60098C16.32 8.69525 16.474 8.71076 16.5766 8.60814C16.6828 8.50194 16.6696 8.35278 16.573 8.25613C16.4763 8.15948 16.3248 8.14397 16.2186 8.25017C16.116 8.35278 16.1291 8.50433 16.2258 8.60098ZM17.1329 8.31196L16.2618 7.4409L16.4229 7.27981L17.294 8.15088L17.1329 8.31196ZM17.4907 7.9852C17.4286 8.04725 17.3355 8.04486 17.2783 7.98759C17.2222 7.93151 17.2198 7.83843 17.2818 7.77638C17.3439 7.71433 17.4358 7.71791 17.4919 7.774C17.5491 7.83127 17.5527 7.92315 17.4907 7.9852ZM17.943 7.53281C17.7653 7.71061 17.4777 7.70703 17.2975 7.52685C17.1173 7.34667 17.1114 7.06387 17.2999 6.87295C17.4121 6.7584 17.5481 6.71067 17.6734 6.73095L17.6507 6.95648C17.5791 6.94216 17.5039 6.96244 17.449 7.01733C17.3464 7.11995 17.3619 7.26911 17.4586 7.36576C17.5552 7.46241 17.708 7.47434 17.8106 7.37173C17.8726 7.30968 17.8822 7.23808 17.8715 7.16291L18.0898 7.1474C18.1065 7.28104 18.0648 7.4111 17.943 7.53281ZM18.5399 6.93594C18.3478 7.12805 18.0638 7.12089 17.8848 6.94191C17.7058 6.76292 17.6975 6.47773 17.8896 6.28562C18.0817 6.09351 18.3669 6.10186 18.5459 6.28085C18.7249 6.45984 18.732 6.74383 18.5399 6.93594ZM18.0459 6.78082C18.1426 6.87747 18.2905 6.89179 18.3932 6.78917C18.4958 6.68655 18.4815 6.53859 18.3848 6.44194C18.2881 6.34528 18.139 6.32977 18.0364 6.43239C17.9338 6.53501 17.9493 6.68417 18.0459 6.78082ZM18.9262 6.5186L18.3057 5.89812L18.4644 5.73942L18.5551 5.8301C18.5181 5.72868 18.5444 5.63083 18.6399 5.53537C18.727 5.44826 18.8427 5.41605 18.9585 5.45065C18.925 5.33371 18.9429 5.23229 19.0515 5.1237C19.1852 4.99006 19.3868 4.98648 19.5431 5.14279L19.9226 5.52225L19.7615 5.68333L19.4214 5.34326C19.314 5.23587 19.2162 5.24064 19.1434 5.31343C19.0682 5.3886 19.0515 5.47452 19.1708 5.59384L19.5109 5.93391L19.3498 6.095L19.0098 5.75493C18.9024 5.64754 18.8021 5.6547 18.7222 5.73464C18.6542 5.80266 18.6399 5.91005 18.7472 6.01744L19.0873 6.35752L18.9262 6.5186Z" fill="white" fill-opacity="0.03"/>
<path d="M21.4232 4.05272C21.175 4.30092 20.7943 4.29495 20.5557 4.0563C20.3158 3.81646 20.2991 3.44417 20.5569 3.18643C20.6929 3.0504 20.8289 2.9979 20.9936 3.01222L20.9781 3.23297C20.8755 3.23058 20.7872 3.26638 20.712 3.34155C20.5509 3.50264 20.576 3.73055 20.7287 3.88328C20.8814 4.03602 21.107 4.05869 21.2716 3.89402C21.3528 3.81288 21.3862 3.72458 21.3814 3.62196L21.6069 3.60407C21.6201 3.74367 21.5687 3.90715 21.4232 4.05272ZM22.0434 3.43246C21.8728 3.6031 21.5924 3.59474 21.4134 3.41576C21.2344 3.23677 21.2237 2.95397 21.3943 2.78334C21.5017 2.67595 21.6019 2.66401 21.7022 2.69742L21.6043 2.59958L21.7642 2.43968L22.3847 3.06017L22.2284 3.21649L22.127 3.11506C22.1639 3.21887 22.1544 3.32149 22.0434 3.43246ZM21.5733 3.25348C21.6676 3.34774 21.8215 3.36325 21.9241 3.26064C22.0303 3.15444 22.0172 3.00528 21.9205 2.90863C21.8239 2.81198 21.6723 2.79646 21.5661 2.90266C21.4635 3.00528 21.4766 3.15682 21.5733 3.25348ZM22.4804 2.96446L21.6093 2.09339L21.7704 1.9323L22.6415 2.80337L22.4804 2.96446ZM22.8382 2.6377C22.7761 2.69975 22.6831 2.69736 22.6258 2.64008C22.5697 2.584 22.5673 2.49093 22.6294 2.42888C22.6914 2.36683 22.7833 2.37041 22.8394 2.42649C22.8967 2.48377 22.9002 2.57565 22.8382 2.6377ZM23.2906 2.18531C23.1128 2.3631 22.8252 2.35952 22.645 2.17934C22.4649 1.99916 22.4589 1.71636 22.6474 1.52545C22.7596 1.41089 22.8956 1.36317 23.0209 1.38345L22.9982 1.60897C22.9266 1.59465 22.8515 1.61494 22.7966 1.66983C22.694 1.77245 22.7095 1.9216 22.8061 2.01826C22.9028 2.11491 23.0555 2.12684 23.1581 2.02422C23.2202 1.96217 23.2297 1.89058 23.219 1.8154L23.4374 1.79989C23.4541 1.93354 23.4123 2.0636 23.2906 2.18531ZM23.8875 1.58844C23.6953 1.78055 23.4114 1.77339 23.2324 1.5944C23.0534 1.41542 23.045 1.13023 23.2371 0.938119C23.4292 0.746007 23.7144 0.75436 23.8934 0.933346C24.0724 1.11233 24.0796 1.39632 23.8875 1.58844ZM23.3935 1.43331C23.4901 1.52997 23.6381 1.54429 23.7407 1.44167C23.8433 1.33905 23.829 1.19109 23.7323 1.09443C23.6357 0.997781 23.4865 0.982269 23.3839 1.08489C23.2813 1.18751 23.2968 1.33666 23.3935 1.43331ZM24.2738 1.1711L23.6533 0.550613L23.812 0.391912L23.9027 0.482599C23.8657 0.381173 23.8919 0.283327 23.9874 0.187868C24.0745 0.100761 24.1902 0.0685433 24.306 0.103147C24.2726 -0.0137904 24.2905 -0.115216 24.3991 -0.223801C24.5327 -0.357444 24.7344 -0.361024 24.8907 -0.204709L25.2701 0.174742L25.109 0.33583L24.769 -0.0042445C24.6616 -0.111636 24.5637 -0.106863 24.4909 -0.0340756C24.4158 0.0410987 24.3991 0.127012 24.5184 0.246336L24.8585 0.586411L24.6974 0.747498L24.3573 0.407424C24.2499 0.300032 24.1497 0.307192 24.0697 0.387139C24.0017 0.455154 23.9874 0.562546 24.0948 0.669938L24.4349 1.01001L24.2738 1.1711Z" fill="white" fill-opacity="0.03"/>
<path d="M1.44734 26.8569C1.19914 27.1051 0.818498 27.0992 0.579849 26.8605C0.340007 26.6207 0.323302 26.2484 0.581042 25.9906C0.717072 25.8546 0.853102 25.8021 1.01777 25.8164L1.00226 26.0372C0.899638 26.0348 0.811338 26.0706 0.736164 26.1458C0.575076 26.3068 0.600134 26.5347 0.752869 26.6875C0.905604 26.8402 1.13113 26.8629 1.29579 26.6982C1.37694 26.6171 1.41035 26.5288 1.40557 26.4262L1.6311 26.4083C1.64422 26.5479 1.59291 26.7113 1.44734 26.8569ZM2.0676 26.2367C1.89697 26.4073 1.61655 26.3989 1.43757 26.22C1.25858 26.041 1.24784 25.7582 1.41847 25.5875C1.52587 25.4801 1.6261 25.4682 1.72633 25.5016L1.62849 25.4038L1.78838 25.2439L2.40887 25.8644L2.25255 26.0207L2.15113 25.9193C2.18812 26.0231 2.17857 26.1257 2.0676 26.2367ZM1.59746 26.0577C1.69173 26.1519 1.84566 26.1675 1.94827 26.0648C2.05447 25.9586 2.04135 25.8095 1.94469 25.7128C1.84804 25.6162 1.6965 25.6007 1.5903 25.7069C1.48768 25.8095 1.50081 25.961 1.59746 26.0577ZM2.50458 25.7687L1.63351 24.8976L1.7946 24.7365L2.66567 25.6076L2.50458 25.7687ZM2.86236 25.4419C2.80032 25.5039 2.70724 25.5016 2.64997 25.4443C2.59388 25.3882 2.5915 25.2951 2.65355 25.2331C2.71559 25.171 2.80747 25.1746 2.86356 25.2307C2.92083 25.288 2.92441 25.3798 2.86236 25.4419ZM3.31475 24.9895C3.13696 25.1673 2.84939 25.1637 2.66921 24.9835C2.48903 24.8034 2.48306 24.5206 2.67159 24.3296C2.78376 24.2151 2.91979 24.1674 3.04508 24.1876L3.02241 24.4132C2.95081 24.3989 2.87564 24.4191 2.82075 24.474C2.71813 24.5766 2.73364 24.7258 2.8303 24.8225C2.92695 24.9191 3.07968 24.931 3.1823 24.8284C3.24435 24.7664 3.2539 24.6948 3.24316 24.6196L3.46152 24.6041C3.47823 24.7377 3.43646 24.8678 3.31475 24.9895ZM3.91162 24.3926C3.71951 24.5847 3.43552 24.5776 3.25653 24.3986C3.07755 24.2196 3.0692 23.9344 3.26131 23.7423C3.45342 23.5502 3.7386 23.5586 3.91759 23.7375C4.09658 23.9165 4.10374 24.2005 3.91162 24.3926ZM3.41762 24.2375C3.51428 24.3342 3.66224 24.3485 3.76486 24.2459C3.86747 24.1432 3.85316 23.9953 3.7565 23.8986C3.65985 23.802 3.5107 23.7865 3.40808 23.8891C3.30546 23.9917 3.32097 24.1409 3.41762 24.2375ZM4.29794 23.9753L3.67745 23.3548L3.83615 23.1961L3.92684 23.2868C3.88985 23.1854 3.9161 23.0875 4.01156 22.9921C4.09867 22.905 4.21441 22.8727 4.33015 22.9073C4.29674 22.7904 4.31464 22.689 4.42323 22.5804C4.55687 22.4468 4.75853 22.4432 4.91484 22.5995L5.29429 22.9789L5.13321 23.14L4.79313 22.8C4.68574 22.6926 4.5879 22.6973 4.51511 22.7701C4.43993 22.8453 4.42323 22.9312 4.54255 23.0505L4.88263 23.3906L4.72154 23.5517L4.38146 23.2116C4.27407 23.1042 4.17384 23.1114 4.09389 23.1913C4.02588 23.2594 4.01156 23.3667 4.11895 23.4741L4.45903 23.8142L4.29794 23.9753Z" fill="white" fill-opacity="0.03"/>
<path d="M6.79487 21.5094C6.54668 21.7576 6.16603 21.7517 5.92738 21.513C5.68754 21.2732 5.67084 20.9009 5.92858 20.6431C6.06461 20.5071 6.20064 20.4546 6.3653 20.4689L6.34979 20.6897C6.24717 20.6873 6.15887 20.7231 6.0837 20.7983C5.92261 20.9594 5.94767 21.1873 6.1004 21.34C6.25314 21.4927 6.47866 21.5154 6.64333 21.3507C6.72447 21.2696 6.75788 21.1813 6.75311 21.0787L6.97863 21.0608C6.99176 21.2004 6.94045 21.3639 6.79487 21.5094ZM7.41513 20.8892C7.2445 21.0598 6.96409 21.0515 6.7851 20.8725C6.60611 20.6935 6.59538 20.4107 6.76601 20.24C6.8734 20.1327 6.97363 20.1207 7.07387 20.1541L6.97602 20.0563L7.13591 19.8964L7.7564 20.5169L7.60009 20.6732L7.49866 20.5718C7.53565 20.6756 7.5261 20.7782 7.41513 20.8892ZM6.945 20.7102C7.03926 20.8045 7.19319 20.82 7.29581 20.7173C7.40201 20.6111 7.38888 20.462 7.29223 20.3653C7.19558 20.2687 7.04403 20.2532 6.93784 20.3594C6.83522 20.462 6.84834 20.6135 6.945 20.7102ZM7.85211 20.4212L6.98104 19.5501L7.14213 19.389L8.0132 20.2601L7.85211 20.4212ZM8.2099 20.0944C8.14785 20.1565 8.05478 20.1541 7.9975 20.0968C7.94142 20.0407 7.93903 19.9476 8.00108 19.8856C8.06313 19.8235 8.15501 19.8271 8.21109 19.8832C8.26837 19.9405 8.27195 20.0324 8.2099 20.0944ZM8.66229 19.642C8.48449 19.8198 8.19692 19.8162 8.01674 19.6361C7.83656 19.4559 7.8306 19.1731 8.01913 18.9822C8.13129 18.8676 8.26732 18.8199 8.39261 18.8402L8.36994 19.0657C8.29835 19.0514 8.22317 19.0716 8.16828 19.1265C8.06566 19.2292 8.08118 19.3783 8.17783 19.475C8.27448 19.5716 8.42722 19.5836 8.52984 19.4809C8.59188 19.4189 8.60143 19.3473 8.59069 19.2721L8.80905 19.2566C8.82576 19.3902 8.784 19.5203 8.66229 19.642ZM9.25916 19.0451C9.06705 19.2373 8.78306 19.2301 8.60407 19.0511C8.42508 18.8721 8.41673 18.5869 8.60884 18.3948C8.80095 18.2027 9.08614 18.2111 9.26513 18.3901C9.44411 18.569 9.45127 18.853 9.25916 19.0451ZM8.76516 18.89C8.86181 18.9867 9.00977 19.001 9.11239 18.8984C9.21501 18.7958 9.20069 18.6478 9.10404 18.5511C9.00738 18.4545 8.85823 18.439 8.75561 18.5416C8.65299 18.6442 8.6685 18.7934 8.76516 18.89ZM9.64547 18.6278L9.02499 18.0073L9.18369 17.8486L9.27437 17.9393C9.23738 17.8379 9.26363 17.74 9.35909 17.6446C9.4462 17.5575 9.56194 17.5253 9.67769 17.5599C9.64428 17.4429 9.66218 17.3415 9.77076 17.2329C9.90441 17.0993 10.1061 17.0957 10.2624 17.252L10.6418 17.6315L10.4807 17.7925L10.1407 17.4525C10.0333 17.3451 9.93543 17.3498 9.86264 17.4226C9.78747 17.4978 9.77076 17.5837 9.89009 17.703L10.2302 18.0431L10.0691 18.2042L9.729 17.8641C9.62161 17.7567 9.52137 17.7639 9.44143 17.8438C9.37341 17.9119 9.35909 18.0193 9.46649 18.1266L9.80656 18.4667L9.64547 18.6278Z" fill="white" fill-opacity="0.03"/>
<path d="M12.1423 16.1619C11.8941 16.4101 11.5134 16.4042 11.2748 16.1655C11.035 15.9257 11.0182 15.5534 11.276 15.2956C11.412 15.1596 11.548 15.1071 11.7127 15.1214L11.6972 15.3422C11.5946 15.3398 11.5063 15.3756 11.4311 15.4508C11.27 15.6118 11.2951 15.8398 11.4478 15.9925C11.6006 16.1452 11.8261 16.1679 11.9907 16.0032C12.0719 15.9221 12.1053 15.8338 12.1005 15.7312L12.326 15.7133C12.3392 15.8529 12.2879 16.0164 12.1423 16.1619ZM12.7625 15.5417C12.5919 15.7123 12.3115 15.704 12.1325 15.525C11.9535 15.346 11.9428 15.0632 12.1134 14.8925C12.2208 14.7852 12.321 14.7732 12.4213 14.8066L12.3234 14.7088L12.4833 14.5489L13.1038 15.1694L12.9475 15.3257L12.8461 15.2243C12.8831 15.3281 12.8735 15.4307 12.7625 15.5417ZM12.2924 15.3627C12.3867 15.4569 12.5406 15.4725 12.6432 15.3698C12.7494 15.2636 12.7363 15.1145 12.6396 15.0178C12.543 14.9212 12.3914 14.9057 12.2852 15.0119C12.1826 15.1145 12.1958 15.266 12.2924 15.3627ZM13.1995 15.0737L12.3285 14.2026L12.4895 14.0415L13.3606 14.9126L13.1995 15.0737ZM13.5573 14.7469C13.4953 14.809 13.4022 14.8066 13.3449 14.7493C13.2888 14.6932 13.2864 14.6001 13.3485 14.5381C13.4105 14.476 13.5024 14.4796 13.5585 14.5357C13.6158 14.593 13.6194 14.6849 13.5573 14.7469ZM14.0097 14.2945C13.8319 14.4723 13.5443 14.4687 13.3642 14.2886C13.184 14.1084 13.178 13.8256 13.3665 13.6347C13.4787 13.5201 13.6147 13.4724 13.74 13.4927L13.7174 13.7182C13.6458 13.7039 13.5706 13.7241 13.5157 13.779C13.4131 13.8817 13.4286 14.0308 13.5252 14.1275C13.6219 14.2241 13.7746 14.236 13.8772 14.1334C13.9393 14.0714 13.9488 13.9998 13.9381 13.9246L14.1565 13.9091C14.1732 14.0427 14.1314 14.1728 14.0097 14.2945ZM14.6066 13.6976C14.4145 13.8898 14.1305 13.8826 13.9515 13.7036C13.7725 13.5246 13.7641 13.2394 13.9563 13.0473C14.1484 12.8552 14.4336 12.8636 14.6125 13.0426C14.7915 13.2215 14.7987 13.5055 14.6066 13.6976ZM14.1126 13.5425C14.2092 13.6392 14.3572 13.6535 14.4598 13.5509C14.5624 13.4483 14.5481 13.3003 14.4514 13.2036C14.3548 13.107 14.2056 13.0915 14.103 13.1941C14.0004 13.2967 14.0159 13.4459 14.1126 13.5425ZM14.9929 13.2803L14.3724 12.6598L14.5311 12.5011L14.6218 12.5918C14.5848 12.4904 14.611 12.3925 14.7065 12.2971C14.7936 12.21 14.9094 12.1778 15.0251 12.2124C14.9917 12.0954 15.0096 11.994 15.1182 11.8854C15.2518 11.7518 15.4535 11.7482 15.6098 11.9045L15.9892 12.2839L15.8282 12.445L15.4881 12.105C15.3807 11.9976 15.2828 12.0023 15.2101 12.0751C15.1349 12.1503 15.1182 12.2362 15.2375 12.3555L15.5776 12.6956L15.4165 12.8567L15.0764 12.5166C14.969 12.4092 14.8688 12.4164 14.7888 12.4963C14.7208 12.5644 14.7065 12.6718 14.8139 12.7791L15.154 13.1192L14.9929 13.2803Z" fill="white" fill-opacity="0.03"/>
<path d="M17.4898 10.8144C17.2416 11.0626 16.861 11.0567 16.6223 10.818C16.3825 10.5782 16.3658 10.2059 16.6235 9.94815C16.7596 9.81212 16.8956 9.75962 17.0602 9.77394L17.0447 9.99469C16.9421 9.9923 16.8538 10.0281 16.7786 10.1033C16.6176 10.2644 16.6426 10.4923 16.7953 10.645C16.9481 10.7977 17.1736 10.8204 17.3383 10.6557C17.4194 10.5746 17.4528 10.4863 17.4481 10.3837L17.6736 10.3658C17.6867 10.5054 17.6354 10.6689 17.4898 10.8144ZM18.1101 10.1942C17.9394 10.3648 17.659 10.3565 17.48 10.1775C17.3011 9.99849 17.2903 9.71569 17.461 9.54506C17.5683 9.43767 17.6686 9.42573 17.7688 9.45914L17.671 9.3613L17.8309 9.2014L18.4513 9.82189L18.295 9.9782L18.1936 9.87678C18.2306 9.98059 18.2211 10.0832 18.1101 10.1942ZM17.6399 10.0152C17.7342 10.1095 17.8881 10.125 17.9908 10.0224C18.097 9.91616 18.0838 9.767 17.9872 9.67035C17.8905 9.57369 17.739 9.55818 17.6328 9.66438C17.5302 9.767 17.5433 9.91854 17.6399 10.0152ZM18.5471 9.72618L17.676 8.85511L17.8371 8.69402L18.7081 9.56509L18.5471 9.72618ZM18.9048 9.39942C18.8428 9.46146 18.7497 9.45908 18.6924 9.4018C18.6364 9.34572 18.634 9.25265 18.696 9.1906C18.7581 9.12855 18.85 9.13213 18.906 9.18821C18.9633 9.24549 18.9669 9.33737 18.9048 9.39942ZM19.3572 8.94703C19.1794 9.12482 18.8919 9.12124 18.7117 8.94106C18.5315 8.76088 18.5255 8.47808 18.7141 8.28716C18.8262 8.17261 18.9623 8.12488 19.0876 8.14517L19.0649 8.37069C18.9933 8.35637 18.9181 8.37666 18.8632 8.43155C18.7606 8.53417 18.7761 8.68332 18.8728 8.77997C18.9694 8.87663 19.1222 8.88856 19.2248 8.78594C19.2868 8.72389 19.2964 8.6523 19.2856 8.57712L19.504 8.56161C19.5207 8.69525 19.4789 8.82532 19.3572 8.94703ZM19.9541 8.35015C19.762 8.54227 19.478 8.53511 19.299 8.35612C19.12 8.17713 19.1117 7.89195 19.3038 7.69984C19.4959 7.50773 19.7811 7.51608 19.9601 7.69506C20.1391 7.87405 20.1462 8.15804 19.9541 8.35015ZM19.4601 8.19503C19.5568 8.29169 19.7047 8.306 19.8073 8.20339C19.91 8.10077 19.8956 7.95281 19.799 7.85615C19.7023 7.7595 19.5532 7.74399 19.4506 7.84661C19.3479 7.94923 19.3635 8.09838 19.4601 8.19503ZM20.3404 7.93282L19.7199 7.31233L19.8786 7.15363L19.9693 7.24432C19.9323 7.14289 19.9586 7.04505 20.054 6.94959C20.1411 6.86248 20.2569 6.83026 20.3726 6.86487C20.3392 6.74793 20.3571 6.6465 20.4657 6.53792C20.5994 6.40427 20.801 6.40069 20.9573 6.55701L21.3368 6.93646L21.1757 7.09755L20.8356 6.75747C20.7282 6.65008 20.6304 6.65486 20.5576 6.72764C20.4824 6.80282 20.4657 6.88873 20.585 7.00806L20.9251 7.34813L20.764 7.50922L20.4239 7.16914C20.3166 7.06175 20.2163 7.06891 20.1364 7.14886C20.0684 7.21687 20.054 7.32426 20.1614 7.43166L20.5015 7.77173L20.3404 7.93282Z" fill="white" fill-opacity="0.03"/>
<path d="M22.8374 5.46694C22.5892 5.71513 22.2085 5.70917 21.9699 5.47052C21.73 5.23068 21.7133 4.85839 21.9711 4.60065C22.1071 4.46462 22.2431 4.41211 22.4078 4.42643L22.3923 4.64718C22.2897 4.6448 22.2014 4.68059 22.1262 4.75577C21.9651 4.91685 21.9901 5.14476 22.1429 5.2975C22.2956 5.45023 22.5211 5.47291 22.6858 5.30824C22.7669 5.2271 22.8004 5.1388 22.7956 5.03618L23.0211 5.01828C23.0342 5.15789 22.9829 5.32136 22.8374 5.46694ZM23.4576 4.84668C23.287 5.01731 23.0066 5.00896 22.8276 4.82997C22.6486 4.65099 22.6379 4.36819 22.8085 4.19755C22.9159 4.09016 23.0161 4.07823 23.1163 4.11164L23.0185 4.01379L23.1784 3.8539L23.7989 4.47439L23.6426 4.6307L23.5411 4.52927C23.5781 4.63309 23.5686 4.73571 23.4576 4.84668ZM22.9875 4.66769C23.0817 4.76196 23.2357 4.77747 23.3383 4.67485C23.4445 4.56865 23.4314 4.4195 23.3347 4.32284C23.2381 4.22619 23.0865 4.21068 22.9803 4.31688C22.8777 4.4195 22.8908 4.57104 22.9875 4.66769ZM23.8946 4.37867L23.0235 3.50761L23.1846 3.34652L24.0557 4.21759L23.8946 4.37867ZM24.2524 4.05191C24.1903 4.11396 24.0973 4.11157 24.04 4.0543C23.9839 3.99822 23.9815 3.90514 24.0436 3.84309C24.1056 3.78105 24.1975 3.78463 24.2536 3.84071C24.3108 3.89798 24.3144 3.98986 24.2524 4.05191ZM24.7048 3.59952C24.527 3.77732 24.2394 3.77374 24.0592 3.59356C23.879 3.41338 23.8731 3.13058 24.0616 2.93966C24.1738 2.82511 24.3098 2.77738 24.4351 2.79767L24.4124 3.02319C24.3408 3.00887 24.2657 3.02915 24.2108 3.08404C24.1081 3.18666 24.1237 3.33582 24.2203 3.43247C24.317 3.52912 24.4697 3.54106 24.5723 3.43844C24.6344 3.37639 24.6439 3.30479 24.6332 3.22962L24.8515 3.21411C24.8682 3.34775 24.8265 3.47781 24.7048 3.59952ZM25.3016 3.00265C25.1095 3.19476 24.8255 3.1876 24.6465 3.00862C24.4676 2.82963 24.4592 2.54445 24.6513 2.35233C24.8434 2.16022 25.1286 2.16857 25.3076 2.34756C25.4866 2.52655 25.4938 2.81054 25.3016 3.00265ZM24.8076 2.84753C24.9043 2.94418 25.0523 2.9585 25.1549 2.85588C25.2575 2.75326 25.2432 2.6053 25.1465 2.50865C25.0499 2.412 24.9007 2.39648 24.7981 2.4991C24.6955 2.60172 24.711 2.75088 24.8076 2.84753ZM25.688 2.58531L25.0675 1.96483L25.2262 1.80613L25.3169 1.89681C25.2799 1.79539 25.3061 1.69754 25.4016 1.60208C25.4887 1.51498 25.6044 1.48276 25.7202 1.51736C25.6868 1.40042 25.7047 1.299 25.8132 1.19041C25.9469 1.05677 26.1485 1.05319 26.3049 1.20951L26.6843 1.58896L26.5232 1.75004L26.1831 1.40997C26.0758 1.30258 25.9779 1.30735 25.9051 1.38014C25.8299 1.45531 25.8132 1.54123 25.9326 1.66055L26.2726 2.00063L26.1116 2.16171L25.7715 1.82164C25.6641 1.71425 25.5639 1.72141 25.4839 1.80135C25.4159 1.86937 25.4016 1.97676 25.509 2.08415L25.849 2.42423L25.688 2.58531Z" fill="white" fill-opacity="0.03"/>
<path d="M2.86152 28.2711C2.61333 28.5193 2.23268 28.5134 1.99403 28.2747C1.75419 28.0349 1.73749 27.6626 1.99523 27.4048C2.13126 27.2688 2.26729 27.2163 2.43195 27.2306L2.41644 27.4514C2.31382 27.449 2.22552 27.4848 2.15035 27.56C1.98926 27.7211 2.01432 27.949 2.16705 28.1017C2.31979 28.2544 2.54531 28.2771 2.70998 28.1124C2.79112 28.0313 2.82453 27.943 2.81976 27.8404L3.04528 27.8225C3.05841 27.9621 3.0071 28.1256 2.86152 28.2711ZM3.48178 27.6509C3.31115 27.8215 3.03074 27.8132 2.85175 27.6342C2.67276 27.4552 2.66203 27.1724 2.83266 27.0018C2.94005 26.8944 3.04028 26.8824 3.14052 26.9158L3.04267 26.818L3.20256 26.6581L3.82305 27.2786L3.66674 27.4349L3.56531 27.3335C3.6023 27.4373 3.59276 27.5399 3.48178 27.6509ZM3.01165 27.4719C3.10591 27.5662 3.25984 27.5817 3.36246 27.479C3.46866 27.3729 3.45553 27.2237 3.35888 27.127C3.26223 27.0304 3.11068 27.0149 3.00449 27.1211C2.90187 27.2237 2.91499 27.3752 3.01165 27.4719ZM3.91876 27.1829L3.04769 26.3118L3.20878 26.1507L4.07985 27.0218L3.91876 27.1829ZM4.27655 26.8561C4.2145 26.9182 4.12143 26.9158 4.06415 26.8585C4.00807 26.8024 4.00568 26.7093 4.06773 26.6473C4.12978 26.5852 4.22166 26.5888 4.27774 26.6449C4.33502 26.7022 4.3386 26.7941 4.27655 26.8561ZM4.72894 26.4037C4.55114 26.5815 4.26357 26.5779 4.08339 26.3978C3.90321 26.2176 3.89725 25.9348 4.08578 25.7439C4.19794 25.6293 4.33397 25.5816 4.45926 25.6019L4.43659 25.8274C4.365 25.8131 4.28982 25.8334 4.23493 25.8882C4.13232 25.9909 4.14783 26.14 4.24448 26.2367C4.34113 26.3333 4.49387 26.3453 4.59649 26.2426C4.65854 26.1806 4.66808 26.109 4.65734 26.0338L4.87571 26.0183C4.89241 26.1519 4.85065 26.282 4.72894 26.4037ZM5.32581 25.8069C5.1337 25.999 4.84971 25.9918 4.67072 25.8128C4.49173 25.6338 4.48338 25.3486 4.67549 25.1565C4.8676 24.9644 5.15279 24.9728 5.33178 25.1518C5.51076 25.3307 5.51792 25.6147 5.32581 25.8069ZM4.83181 25.6517C4.92846 25.7484 5.07642 25.7627 5.17904 25.6601C5.28166 25.5575 5.26734 25.4095 5.17069 25.3128C5.07404 25.2162 4.92488 25.2007 4.82226 25.3033C4.71964 25.4059 4.73515 25.5551 4.83181 25.6517ZM5.71212 25.3895L5.09164 24.769L5.25034 24.6103L5.34102 24.701C5.30403 24.5996 5.33028 24.5017 5.42574 24.4063C5.51285 24.3192 5.62859 24.287 5.74434 24.3216C5.71093 24.2046 5.72883 24.1032 5.83741 23.9946C5.97106 23.861 6.17271 23.8574 6.32903 24.0137L6.70848 24.3932L6.54739 24.5542L6.20732 24.2142C6.09993 24.1068 6.00208 24.1116 5.92929 24.1843C5.85412 24.2595 5.83741 24.3454 5.95674 24.4648L6.29681 24.8048L6.13572 24.9659L5.79565 24.6258C5.68826 24.5184 5.58802 24.5256 5.50808 24.6056C5.44006 24.6736 5.42574 24.781 5.53314 24.8884L5.87321 25.2284L5.71212 25.3895Z" fill="white" fill-opacity="0.03"/>
<path d="M8.20906 22.9237C7.96086 23.1718 7.58022 23.1659 7.34157 22.9272C7.10173 22.6874 7.08502 22.3151 7.34276 22.0574C7.47879 21.9213 7.61482 21.8688 7.77949 21.8831L7.76398 22.1039C7.66136 22.1015 7.57306 22.1373 7.49788 22.2125C7.33679 22.3736 7.36185 22.6015 7.51459 22.7542C7.66732 22.9069 7.89285 22.9296 8.05751 22.7649C8.13865 22.6838 8.17206 22.5955 8.16729 22.4929L8.39281 22.475C8.40594 22.6146 8.35463 22.7781 8.20906 22.9237ZM8.82932 22.3034C8.65868 22.474 8.37827 22.4657 8.19929 22.2867C8.0203 22.1077 8.00956 21.8249 8.18019 21.6543C8.28759 21.5469 8.38782 21.5349 8.48805 21.5684L8.3902 21.4705L8.5501 21.3106L9.17059 21.9311L9.01427 22.0874L8.91284 21.986C8.94984 22.0898 8.94029 22.1924 8.82932 22.3034ZM8.35918 22.1244C8.45345 22.2187 8.60737 22.2342 8.70999 22.1316C8.81619 22.0254 8.80307 21.8762 8.70641 21.7796C8.60976 21.6829 8.45822 21.6674 8.35202 21.7736C8.2494 21.8762 8.26253 22.0277 8.35918 22.1244ZM9.2663 21.8354L8.39523 20.9643L8.55632 20.8032L9.42738 21.6743L9.2663 21.8354ZM9.62408 21.5086C9.56203 21.5707 9.46896 21.5683 9.41169 21.511C9.3556 21.4549 9.35322 21.3619 9.41527 21.2998C9.47731 21.2378 9.56919 21.2413 9.62528 21.2974C9.68255 21.3547 9.68613 21.4466 9.62408 21.5086ZM10.0765 21.0562C9.89868 21.234 9.61111 21.2304 9.43093 21.0503C9.25075 20.8701 9.24478 20.5873 9.43331 20.3964C9.54548 20.2818 9.68151 20.2341 9.8068 20.2544L9.78413 20.4799C9.71253 20.4656 9.63736 20.4859 9.58247 20.5408C9.47985 20.6434 9.49536 20.7925 9.59201 20.8892C9.68867 20.9858 9.8414 20.9978 9.94402 20.8951C10.0061 20.8331 10.0156 20.7615 10.0049 20.6863L10.2232 20.6708C10.2399 20.8045 10.1982 20.9345 10.0765 21.0562ZM10.6733 20.4594C10.4812 20.6515 10.1972 20.6443 10.0183 20.4653C9.83927 20.2863 9.83091 20.0012 10.023 19.809C10.2151 19.6169 10.5003 19.6253 10.6793 19.8043C10.8583 19.9833 10.8655 20.2672 10.6733 20.4594ZM10.1793 20.3042C10.276 20.4009 10.424 20.4152 10.5266 20.3126C10.6292 20.21 10.6149 20.062 10.5182 19.9654C10.4216 19.8687 10.2724 19.8532 10.1698 19.9558C10.0672 20.0584 10.0827 20.2076 10.1793 20.3042ZM11.0597 20.042L10.4392 19.4215L10.5979 19.2628L10.6886 19.3535C10.6516 19.2521 10.6778 19.1543 10.7733 19.0588C10.8604 18.9717 10.9761 18.9395 11.0919 18.9741C11.0585 18.8571 11.0764 18.7557 11.1849 18.6471C11.3186 18.5135 11.5202 18.5099 11.6766 18.6662L12.056 19.0457L11.8949 19.2068L11.5549 18.8667C11.4475 18.7593 11.3496 18.7641 11.2768 18.8369C11.2017 18.912 11.1849 18.9979 11.3043 19.1173L11.6443 19.4573L11.4833 19.6184L11.1432 19.2784C11.0358 19.171 10.9356 19.1781 10.8556 19.2581C10.7876 19.3261 10.7733 19.4335 10.8807 19.5409L11.2207 19.8809L11.0597 20.042Z" fill="white" fill-opacity="0.03"/>
<path d="M13.5565 17.5761C13.3083 17.8243 12.9276 17.8184 12.689 17.5797C12.4491 17.3399 12.4324 16.9676 12.6902 16.7099C12.8262 16.5738 12.9622 16.5213 13.1269 16.5356L13.1114 16.7564C13.0088 16.754 12.9205 16.7898 12.8453 16.865C12.6842 17.0261 12.7093 17.254 12.862 17.4067C13.0147 17.5594 13.2403 17.5821 13.4049 17.4174C13.4861 17.3363 13.5195 17.248 13.5147 17.1454L13.7402 17.1275C13.7534 17.2671 13.702 17.4306 13.5565 17.5761ZM14.1767 16.9559C14.0061 17.1265 13.7257 17.1182 13.5467 16.9392C13.3677 16.7602 13.357 16.4774 13.5276 16.3068C13.635 16.1994 13.7352 16.1874 13.8355 16.2208L13.7376 16.123L13.8975 15.9631L14.518 16.5836L14.3617 16.7399L14.2603 16.6385C14.2972 16.7423 14.2877 16.8449 14.1767 16.9559ZM13.7066 16.7769C13.8009 16.8712 13.9548 16.8867 14.0574 16.7841C14.1636 16.6779 14.1505 16.5287 14.0538 16.4321C13.9572 16.3354 13.8056 16.3199 13.6994 16.4261C13.5968 16.5287 13.6099 16.6802 13.7066 16.7769ZM14.6137 16.4879L13.7426 15.6168L13.9037 15.4557L14.7748 16.3268L14.6137 16.4879ZM14.9715 16.1611C14.9094 16.2232 14.8164 16.2208 14.7591 16.1635C14.703 16.1074 14.7006 16.0144 14.7627 15.9523C14.8247 15.8903 14.9166 15.8938 14.9727 15.9499C15.03 16.0072 15.0335 16.0991 14.9715 16.1611ZM15.4239 15.7087C15.2461 15.8865 14.9585 15.8829 14.7783 15.7028C14.5982 15.5226 14.5922 15.2398 14.7807 15.0489C14.8929 14.9343 15.0289 14.8866 15.1542 14.9069L15.1315 15.1324C15.0599 15.1181 14.9848 15.1384 14.9299 15.1933C14.8273 15.2959 14.8428 15.445 14.9394 15.5417C15.0361 15.6383 15.1888 15.6503 15.2914 15.5476C15.3535 15.4856 15.363 15.414 15.3523 15.3388L15.5707 15.3233C15.5874 15.457 15.5456 15.587 15.4239 15.7087ZM16.0208 15.1119C15.8286 15.304 15.5447 15.2968 15.3657 15.1178C15.1867 14.9388 15.1783 14.6537 15.3704 14.4615C15.5626 14.2694 15.8477 14.2778 16.0267 14.4568C16.2057 14.6358 16.2129 14.9197 16.0208 15.1119ZM15.5268 14.9567C15.6234 15.0534 15.7714 15.0677 15.874 14.9651C15.9766 14.8625 15.9623 14.7145 15.8656 14.6179C15.769 14.5212 15.6198 14.5057 15.5172 14.6083C15.4146 14.7109 15.4301 14.8601 15.5268 14.9567ZM16.4071 14.6945L15.7866 14.074L15.9453 13.9153L16.036 14.006C15.999 13.9046 16.0252 13.8067 16.1207 13.7113C16.2078 13.6242 16.3235 13.592 16.4393 13.6266C16.4059 13.5096 16.4238 13.4082 16.5324 13.2996C16.666 13.166 16.8677 13.1624 17.024 13.3187L17.4034 13.6982L17.2423 13.8593L16.9023 13.5192C16.7949 13.4118 16.697 13.4166 16.6242 13.4893C16.5491 13.5645 16.5324 13.6504 16.6517 13.7698L16.9918 14.1098L16.8307 14.2709L16.4906 13.9308C16.3832 13.8235 16.283 13.8306 16.203 13.9106C16.135 13.9786 16.1207 14.086 16.2281 14.1934L16.5682 14.5334L16.4071 14.6945Z" fill="white" fill-opacity="0.03"/>
<path d="M18.904 12.2287C18.6558 12.4769 18.2752 12.4709 18.0365 12.2322C17.7967 11.9924 17.78 11.6201 18.0377 11.3624C18.1737 11.2263 18.3098 11.1738 18.4744 11.1882L18.4589 11.4089C18.3563 11.4065 18.268 11.4423 18.1928 11.5175C18.0317 11.6786 18.0568 11.9065 18.2095 12.0592C18.3623 12.212 18.5878 12.2346 18.7525 12.07C18.8336 11.9888 18.867 11.9005 18.8622 11.7979L19.0878 11.78C19.1009 11.9196 19.0496 12.0831 18.904 12.2287ZM19.5243 11.6084C19.3536 11.779 19.0732 11.7707 18.8942 11.5917C18.7152 11.4127 18.7045 11.1299 18.8751 10.9593C18.9825 10.8519 19.0828 10.8399 19.183 10.8734L19.0852 10.7755L19.245 10.6156L19.8655 11.2361L19.7092 11.3924L19.6078 11.291C19.6448 11.3948 19.6352 11.4974 19.5243 11.6084ZM19.0541 11.4294C19.1484 11.5237 19.3023 11.5392 19.4049 11.4366C19.5111 11.3304 19.498 11.1812 19.4014 11.0846C19.3047 10.9879 19.1532 10.9724 19.047 11.0786C18.9443 11.1812 18.9575 11.3328 19.0541 11.4294ZM19.9612 11.1404L19.0902 10.2693L19.2513 10.1082L20.1223 10.9793L19.9612 11.1404ZM20.319 10.8136C20.257 10.8757 20.1639 10.8733 20.1066 10.816C20.0505 10.7599 20.0482 10.6669 20.1102 10.6048C20.1723 10.5428 20.2641 10.5463 20.3202 10.6024C20.3775 10.6597 20.3811 10.7516 20.319 10.8136ZM20.7714 10.3612C20.5936 10.539 20.3061 10.5355 20.1259 10.3553C19.9457 10.1751 19.9397 9.8923 20.1283 9.70138C20.2404 9.58683 20.3765 9.5391 20.5017 9.55938L20.4791 9.78491C20.4075 9.77059 20.3323 9.79087 20.2774 9.84576C20.1748 9.94838 20.1903 10.0975 20.287 10.1942C20.3836 10.2908 20.5363 10.3028 20.639 10.2002C20.701 10.1381 20.7106 10.0665 20.6998 9.99134L20.9182 9.97583C20.9349 10.1095 20.8931 10.2395 20.7714 10.3612ZM21.3683 9.76437C21.1762 9.95648 20.8922 9.94932 20.7132 9.77034C20.5342 9.59135 20.5259 9.30616 20.718 9.11405C20.9101 8.92194 21.1953 8.93029 21.3743 9.10928C21.5532 9.28827 21.5604 9.57226 21.3683 9.76437ZM20.8743 9.60925C20.9709 9.7059 21.1189 9.72022 21.2215 9.6176C21.3241 9.51498 21.3098 9.36702 21.2132 9.27037C21.1165 9.17371 20.9674 9.1582 20.8647 9.26082C20.7621 9.36344 20.7776 9.5126 20.8743 9.60925ZM21.7546 9.34703L21.1341 8.72655L21.2928 8.56785L21.3835 8.65853C21.3465 8.55711 21.3728 8.45926 21.4682 8.3638C21.5553 8.27669 21.6711 8.24448 21.7868 8.27908C21.7534 8.16214 21.7713 8.06072 21.8799 7.95213C22.0135 7.81849 22.2152 7.81491 22.3715 7.97122L22.751 8.35068L22.5899 8.51176L22.2498 8.17169C22.1424 8.0643 22.0446 8.06907 21.9718 8.14186C21.8966 8.21703 21.8799 8.30295 21.9992 8.42227L22.3393 8.76234L22.1782 8.92343L21.8381 8.58336C21.7307 8.47597 21.6305 8.48313 21.5506 8.56307C21.4825 8.63109 21.4682 8.73848 21.5756 8.84587L21.9157 9.18595L21.7546 9.34703Z" fill="white" fill-opacity="0.03"/>
<path d="M24.2515 6.88115C24.0033 7.12935 23.6227 7.12338 23.384 6.88473C23.1442 6.64489 23.1275 6.2726 23.3852 6.01486C23.5213 5.87883 23.6573 5.82633 23.822 5.84065L23.8065 6.0614C23.7038 6.05901 23.6155 6.09481 23.5404 6.16998C23.3793 6.33107 23.4043 6.55898 23.5571 6.71171C23.7098 6.86445 23.9353 6.88712 24.1 6.72245C24.1811 6.64131 24.2145 6.55301 24.2098 6.45039L24.4353 6.4325C24.4484 6.5721 24.3971 6.73558 24.2515 6.88115ZM24.8718 6.26089C24.7012 6.43153 24.4208 6.42317 24.2418 6.24419C24.0628 6.0652 24.052 5.7824 24.2227 5.61177C24.3301 5.50438 24.4303 5.49244 24.5305 5.52585L24.4327 5.42801L24.5926 5.26811L25.2131 5.8886L25.0568 6.04492L24.9553 5.94349C24.9923 6.0473 24.9828 6.14992 24.8718 6.26089ZM24.4017 6.08191C24.4959 6.17617 24.6499 6.19168 24.7525 6.08907C24.8587 5.98287 24.8455 5.83371 24.7489 5.73706C24.6522 5.64041 24.5007 5.62489 24.3945 5.73109C24.2919 5.83371 24.305 5.98525 24.4017 6.08191ZM25.3088 5.79289L24.4377 4.92182L24.5988 4.76073L25.4699 5.6318L25.3088 5.79289ZM25.6666 5.46613C25.6045 5.52818 25.5114 5.52579 25.4542 5.46851C25.3981 5.41243 25.3957 5.31936 25.4577 5.25731C25.5198 5.19526 25.6117 5.19884 25.6678 5.25492C25.725 5.3122 25.7286 5.40408 25.6666 5.46613ZM26.119 5.01374C25.9412 5.19153 25.6536 5.18795 25.4734 5.00777C25.2932 4.82759 25.2873 4.5448 25.4758 4.35388C25.588 4.23932 25.724 4.1916 25.8493 4.21188L25.8266 4.4374C25.755 4.42308 25.6798 4.44337 25.6249 4.49826C25.5223 4.60088 25.5378 4.75003 25.6345 4.84669C25.7311 4.94334 25.8839 4.95527 25.9865 4.85265C26.0485 4.7906 26.0581 4.71901 26.0474 4.64383L26.2657 4.62832C26.2824 4.76197 26.2407 4.89203 26.119 5.01374ZM26.7158 4.41687C26.5237 4.60898 26.2397 4.60182 26.0607 4.42283C25.8817 4.24385 25.8734 3.95866 26.0655 3.76655C26.2576 3.57444 26.5428 3.58279 26.7218 3.76178C26.9008 3.94076 26.9079 4.22475 26.7158 4.41687ZM26.2218 4.26174C26.3185 4.3584 26.4664 4.37272 26.5691 4.2701C26.6717 4.16748 26.6574 4.01952 26.5607 3.92286C26.464 3.82621 26.3149 3.8107 26.2123 3.91332C26.1097 4.01594 26.1252 4.16509 26.2218 4.26174ZM27.1021 3.99953L26.4817 3.37904L26.6404 3.22034L26.731 3.31103C26.694 3.2096 26.7203 3.11176 26.8158 3.0163C26.9029 2.92919 27.0186 2.89697 27.1344 2.93158C27.1009 2.81464 27.1188 2.71321 27.2274 2.60463C27.3611 2.47099 27.5627 2.46741 27.719 2.62372L28.0985 3.00317L27.9374 3.16426L27.5973 2.82419C27.4899 2.71679 27.3921 2.72157 27.3193 2.79435C27.2441 2.86953 27.2274 2.95544 27.3468 3.07477L27.6868 3.41484L27.5257 3.57593L27.1857 3.23585C27.0783 3.12846 26.978 3.13562 26.8981 3.21557C26.8301 3.28358 26.8158 3.39098 26.9232 3.49837L27.2632 3.83844L27.1021 3.99953Z" fill="white" fill-opacity="0.03"/>
<path d="M9.62324 24.3379C9.37505 24.5861 8.9944 24.5801 8.75575 24.3414C8.51591 24.1016 8.49921 23.7293 8.75695 23.4716C8.89298 23.3355 9.029 23.283 9.19367 23.2974L9.17816 23.5181C9.07554 23.5157 8.98724 23.5515 8.91207 23.6267C8.75098 23.7878 8.77604 24.0157 8.92877 24.1684C9.08151 24.3212 9.30703 24.3438 9.4717 24.1792C9.55284 24.098 9.58625 24.0097 9.58148 23.9071L9.807 23.8892C9.82012 24.0288 9.76882 24.1923 9.62324 24.3379ZM10.2435 23.7176C10.0729 23.8882 9.79246 23.8799 9.61347 23.7009C9.43448 23.5219 9.42374 23.2391 9.59438 23.0685C9.70177 22.9611 9.802 22.9492 9.90223 22.9826L9.80439 22.8847L9.96428 22.7248L10.5848 23.3453L10.4285 23.5016L10.327 23.4002C10.364 23.504 10.3545 23.6066 10.2435 23.7176ZM9.77336 23.5386C9.86763 23.6329 10.0216 23.6484 10.1242 23.5458C10.2304 23.4396 10.2173 23.2904 10.1206 23.1938C10.0239 23.0971 9.8724 23.0816 9.76621 23.1878C9.66359 23.2904 9.67671 23.442 9.77336 23.5386ZM10.6805 23.2496L9.80941 22.3785L9.9705 22.2174L10.8416 23.0885L10.6805 23.2496ZM11.0383 22.9228C10.9762 22.9849 10.8831 22.9825 10.8259 22.9252C10.7698 22.8691 10.7674 22.7761 10.8294 22.714C10.8915 22.652 10.9834 22.6556 11.0395 22.7116C11.0967 22.7689 11.1003 22.8608 11.0383 22.9228ZM11.4907 22.4705C11.3129 22.6482 11.0253 22.6447 10.8451 22.4645C10.6649 22.2843 10.659 22.0015 10.8475 21.8106C10.9597 21.696 11.0957 21.6483 11.221 21.6686L11.1983 21.8941C11.1267 21.8798 11.0515 21.9001 10.9967 21.955C10.894 22.0576 10.9095 22.2067 11.0062 22.3034C11.1029 22.4 11.2556 22.412 11.3582 22.3094C11.4203 22.2473 11.4298 22.1757 11.4191 22.1005L11.6374 22.085C11.6541 22.2187 11.6124 22.3487 11.4907 22.4705ZM12.0875 21.8736C11.8954 22.0657 11.6114 22.0585 11.4324 21.8795C11.2535 21.7006 11.2451 21.4154 11.4372 21.2233C11.6293 21.0311 11.9145 21.0395 12.0935 21.2185C12.2725 21.3975 12.2796 21.6815 12.0875 21.8736ZM11.5935 21.7185C11.6902 21.8151 11.8381 21.8294 11.9408 21.7268C12.0434 21.6242 12.0291 21.4762 11.9324 21.3796C11.8358 21.2829 11.6866 21.2674 11.584 21.37C11.4814 21.4726 11.4969 21.6218 11.5935 21.7185ZM12.4738 21.4562L11.8534 20.8358L12.0121 20.6771L12.1027 20.7677C12.0658 20.6663 12.092 20.5685 12.1875 20.473C12.2746 20.3859 12.3903 20.3537 12.5061 20.3883C12.4726 20.2714 12.4905 20.1699 12.5991 20.0613C12.7328 19.9277 12.9344 19.9241 13.0907 20.0804L13.4702 20.4599L13.3091 20.621L12.969 20.2809C12.8616 20.1735 12.7638 20.1783 12.691 20.2511C12.6158 20.3262 12.5991 20.4122 12.7185 20.5315L13.0585 20.8716L12.8974 21.0326L12.5574 20.6926C12.45 20.5852 12.3497 20.5923 12.2698 20.6723C12.2018 20.7403 12.1875 20.8477 12.2949 20.9551L12.6349 21.2952L12.4738 21.4562Z" fill="white" fill-opacity="0.03"/>
<path d="M14.9707 18.9904C14.7225 19.2386 14.3418 19.2326 14.1032 18.9939C13.8633 18.7541 13.8466 18.3818 14.1044 18.1241C14.2404 17.988 14.3764 17.9355 14.5411 17.9499L14.5256 18.1706C14.423 18.1682 14.3347 18.204 14.2595 18.2792C14.0984 18.4403 14.1234 18.6682 14.2762 18.8209C14.4289 18.9737 14.6544 18.9963 14.8191 18.8317C14.9003 18.7505 14.9337 18.6622 14.9289 18.5596L15.1544 18.5417C15.1675 18.6813 15.1162 18.8448 14.9707 18.9904ZM15.5909 18.3701C15.4203 18.5407 15.1399 18.5324 14.9609 18.3534C14.7819 18.1744 14.7712 17.8916 14.9418 17.721C15.0492 17.6136 15.1494 17.6017 15.2496 17.6351L15.1518 17.5372L15.3117 17.3773L15.9322 17.9978L15.7759 18.1541L15.6744 18.0527C15.7114 18.1565 15.7019 18.2591 15.5909 18.3701ZM15.1208 18.1911C15.215 18.2854 15.369 18.3009 15.4716 18.1983C15.5778 18.0921 15.5647 17.9429 15.468 17.8463C15.3714 17.7496 15.2198 17.7341 15.1136 17.8403C15.011 17.9429 15.0241 18.0945 15.1208 18.1911ZM16.0279 17.9021L15.1568 17.031L15.3179 16.8699L16.189 17.741L16.0279 17.9021ZM16.3857 17.5753C16.3236 17.6374 16.2306 17.635 16.1733 17.5777C16.1172 17.5216 16.1148 17.4286 16.1769 17.3665C16.2389 17.3045 16.3308 17.308 16.3869 17.3641C16.4441 17.4214 16.4477 17.5133 16.3857 17.5753ZM16.8381 17.1229C16.6603 17.3007 16.3727 17.2972 16.1925 17.117C16.0123 16.9368 16.0064 16.654 16.1949 16.4631C16.3071 16.3485 16.4431 16.3008 16.5684 16.3211L16.5457 16.5466C16.4741 16.5323 16.399 16.5526 16.3441 16.6075C16.2414 16.7101 16.257 16.8592 16.3536 16.9559C16.4503 17.0525 16.603 17.0645 16.7056 16.9619C16.7677 16.8998 16.7772 16.8282 16.7665 16.753L16.9848 16.7375C17.0015 16.8712 16.9598 17.0012 16.8381 17.1229ZM17.4349 16.5261C17.2428 16.7182 16.9588 16.711 16.7799 16.532C16.6009 16.3531 16.5925 16.0679 16.7846 15.8758C16.9767 15.6836 17.2619 15.692 17.4409 15.871C17.6199 16.05 17.6271 16.334 17.4349 16.5261ZM16.9409 16.371C17.0376 16.4676 17.1856 16.4819 17.2882 16.3793C17.3908 16.2767 17.3765 16.1287 17.2798 16.0321C17.1832 15.9354 17.034 15.9199 16.9314 16.0225C16.8288 16.1251 16.8443 16.2743 16.9409 16.371ZM17.8213 16.1087L17.2008 15.4883L17.3595 15.3295L17.4502 15.4202C17.4132 15.3188 17.4394 15.221 17.5349 15.1255C17.622 15.0384 17.7377 15.0062 17.8535 15.0408C17.8201 14.9238 17.838 14.8224 17.9465 14.7138C18.0802 14.5802 18.2818 14.5766 18.4382 14.7329L18.8176 15.1124L18.6565 15.2735L18.3164 14.9334C18.2091 14.826 18.1112 14.8308 18.0384 14.9036C17.9632 14.9787 17.9465 15.0646 18.0659 15.184L18.4059 15.524L18.2449 15.6851L17.9048 15.3451C17.7974 15.2377 17.6972 15.2448 17.6172 15.3248C17.5492 15.3928 17.5349 15.5002 17.6423 15.6076L17.9823 15.9476L17.8213 16.1087Z" fill="white" fill-opacity="0.03"/>
<path d="M20.3182 13.6429C20.07 13.8911 19.6893 13.8851 19.4507 13.6465C19.2109 13.4066 19.1942 13.0343 19.4519 12.7766C19.5879 12.6405 19.724 12.588 19.8886 12.6024L19.8731 12.8231C19.7705 12.8207 19.6822 12.8565 19.607 12.9317C19.4459 13.0928 19.471 13.3207 19.6237 13.4734C19.7765 13.6262 20.002 13.6488 20.1666 13.4842C20.2478 13.403 20.2812 13.3147 20.2764 13.2121L20.5019 13.1942C20.5151 13.3338 20.4638 13.4973 20.3182 13.6429ZM20.9384 13.0226C20.7678 13.1932 20.4874 13.1849 20.3084 13.0059C20.1294 12.8269 20.1187 12.5441 20.2893 12.3735C20.3967 12.2661 20.4969 12.2542 20.5972 12.2876L20.4993 12.1897L20.6592 12.0298L21.2797 12.6503L21.1234 12.8066L21.022 12.7052C21.059 12.809 21.0494 12.9116 20.9384 13.0226ZM20.4683 12.8436C20.5626 12.9379 20.7165 12.9534 20.8191 12.8508C20.9253 12.7446 20.9122 12.5954 20.8155 12.4988C20.7189 12.4021 20.5674 12.3866 20.4612 12.4928C20.3585 12.5954 20.3717 12.747 20.4683 12.8436ZM21.3754 12.5546L20.5044 11.6835L20.6654 11.5225L21.5365 12.3935L21.3754 12.5546ZM21.7332 12.2278C21.6712 12.2899 21.5781 12.2875 21.5208 12.2302C21.4647 12.1742 21.4623 12.0811 21.5244 12.019C21.5864 11.957 21.6783 11.9606 21.7344 12.0166C21.7917 12.0739 21.7953 12.1658 21.7332 12.2278ZM22.1856 11.7755C22.0078 11.9533 21.7202 11.9497 21.5401 11.7695C21.3599 11.5893 21.3539 11.3065 21.5424 11.1156C21.6546 11.001 21.7906 10.9533 21.9159 10.9736L21.8933 11.1991C21.8217 11.1848 21.7465 11.2051 21.6916 11.26C21.589 11.3626 21.6045 11.5118 21.7011 11.6084C21.7978 11.7051 21.9505 11.717 22.0532 11.6144C22.1152 11.5523 22.1247 11.4807 22.114 11.4056L22.3324 11.39C22.3491 11.5237 22.3073 11.6537 22.1856 11.7755ZM22.7825 11.1786C22.5904 11.3707 22.3064 11.3635 22.1274 11.1846C21.9484 11.0056 21.94 10.7204 22.1322 10.5283C22.3243 10.3362 22.6095 10.3445 22.7884 10.5235C22.9674 10.7025 22.9746 10.9865 22.7825 11.1786ZM22.2885 11.0235C22.3851 11.1201 22.5331 11.1344 22.6357 11.0318C22.7383 10.9292 22.724 10.7812 22.6274 10.6846C22.5307 10.5879 22.3815 10.5724 22.2789 10.675C22.1763 10.7777 22.1918 10.9268 22.2885 11.0235ZM23.1688 10.7612L22.5483 10.1408L22.707 9.98206L22.7977 10.0727C22.7607 9.97132 22.7869 9.87348 22.8824 9.77802C22.9695 9.69091 23.0853 9.65869 23.201 9.6933C23.1676 9.57636 23.1855 9.47493 23.2941 9.36635C23.4277 9.2327 23.6294 9.22912 23.7857 9.38544L24.1651 9.76489L24.0041 9.92598L23.664 9.5859C23.5566 9.47851 23.4587 9.48329 23.386 9.55607C23.3108 9.63125 23.2941 9.71716 23.4134 9.83649L23.7535 10.1766L23.5924 10.3376L23.2523 9.99757C23.1449 9.89018 23.0447 9.89734 22.9647 9.97729C22.8967 10.0453 22.8824 10.1527 22.9898 10.2601L23.3299 10.6002L23.1688 10.7612Z" fill="white" fill-opacity="0.03"/>
<path d="M11.0375 25.7521C10.7894 26.0003 10.4087 25.9943 10.1701 25.7557C9.93022 25.5158 9.91351 25.1435 10.1713 24.8858C10.3073 24.7498 10.4433 24.6973 10.608 24.7116L10.5925 24.9323C10.4898 24.9299 10.4015 24.9657 10.3264 25.0409C10.1653 25.202 10.1903 25.4299 10.3431 25.5826C10.4958 25.7354 10.7213 25.758 10.886 25.5934C10.9671 25.5122 11.0006 25.4239 10.9958 25.3213L11.2213 25.3034C11.2344 25.443 11.1831 25.6065 11.0375 25.7521ZM11.6578 25.1318C11.4872 25.3025 11.2068 25.2941 11.0278 25.1151C10.8488 24.9361 10.8381 24.6533 11.0087 24.4827C11.1161 24.3753 11.2163 24.3634 11.3165 24.3968L11.2187 24.2989L11.3786 24.139L11.9991 24.7595L11.8428 24.9158L11.7413 24.8144C11.7783 24.9182 11.7688 25.0208 11.6578 25.1318ZM11.1877 24.9528C11.2819 25.0471 11.4359 25.0626 11.5385 24.96C11.6447 24.8538 11.6316 24.7046 11.5349 24.608C11.4383 24.5113 11.2867 24.4958 11.1805 24.602C11.0779 24.7046 11.091 24.8562 11.1877 24.9528ZM12.0948 24.6638L11.2237 23.7927L11.3848 23.6317L12.2559 24.5027L12.0948 24.6638ZM12.4526 24.3371C12.3905 24.3991 12.2975 24.3967 12.2402 24.3394C12.1841 24.2834 12.1817 24.1903 12.2438 24.1282C12.3058 24.0662 12.3977 24.0698 12.4538 24.1258C12.511 24.1831 12.5146 24.275 12.4526 24.3371ZM12.905 23.8847C12.7272 24.0625 12.4396 24.0589 12.2594 23.8787C12.0792 23.6985 12.0733 23.4157 12.2618 23.2248C12.374 23.1103 12.51 23.0625 12.6353 23.0828L12.6126 23.3083C12.541 23.294 12.4658 23.3143 12.411 23.3692C12.3083 23.4718 12.3239 23.621 12.4205 23.7176C12.5172 23.8143 12.6699 23.8262 12.7725 23.7236C12.8346 23.6615 12.8441 23.5899 12.8334 23.5148L13.0517 23.4992C13.0684 23.6329 13.0267 23.763 12.905 23.8847ZM13.5018 23.2878C13.3097 23.4799 13.0257 23.4727 12.8467 23.2938C12.6678 23.1148 12.6594 22.8296 12.8515 22.6375C13.0436 22.4454 13.3288 22.4537 13.5078 22.6327C13.6868 22.8117 13.6939 23.0957 13.5018 23.2878ZM13.0078 23.1327C13.1045 23.2293 13.2524 23.2436 13.3551 23.141C13.4577 23.0384 13.4434 22.8904 13.3467 22.7938C13.2501 22.6971 13.1009 22.6816 12.9983 22.7842C12.8957 22.8869 12.9112 23.036 13.0078 23.1327ZM13.8881 22.8705L13.2677 22.25L13.4264 22.0913L13.517 22.182C13.4801 22.0805 13.5063 21.9827 13.6018 21.8872C13.6889 21.8001 13.8046 21.7679 13.9204 21.8025C13.887 21.6856 13.9049 21.5841 14.0134 21.4756C14.1471 21.3419 14.3487 21.3383 14.5051 21.4946L14.8845 21.8741L14.7234 22.0352L14.3833 21.6951C14.276 21.5877 14.1781 21.5925 14.1053 21.6653C14.0301 21.7405 14.0134 21.8264 14.1328 21.9457L14.4728 22.2858L14.3117 22.4469L13.9717 22.1068C13.8643 21.9994 13.764 22.0065 13.6841 22.0865C13.6161 22.1545 13.6018 22.2619 13.7092 22.3693L14.0492 22.7094L13.8881 22.8705Z" fill="white" fill-opacity="0.03"/>
<path d="M16.385 20.4046C16.1368 20.6528 15.7561 20.6468 15.5175 20.4082C15.2776 20.1683 15.2609 19.796 15.5187 19.5383C15.6547 19.4023 15.7907 19.3498 15.9554 19.3641L15.9399 19.5848C15.8373 19.5824 15.749 19.6182 15.6738 19.6934C15.5127 19.8545 15.5378 20.0824 15.6905 20.2351C15.8432 20.3879 16.0687 20.4105 16.2334 20.2459C16.3146 20.1647 16.348 20.0764 16.3432 19.9738L16.5687 19.9559C16.5818 20.0955 16.5305 20.259 16.385 20.4046ZM17.0052 19.7843C16.8346 19.9549 16.5542 19.9466 16.3752 19.7676C16.1962 19.5886 16.1855 19.3058 16.3561 19.1352C16.4635 19.0278 16.5637 19.0159 16.664 19.0493L16.5661 18.9514L16.726 18.7915L17.3465 19.412L17.1902 19.5683L17.0887 19.4669C17.1257 19.5707 17.1162 19.6733 17.0052 19.7843ZM16.5351 19.6053C16.6293 19.6996 16.7833 19.7151 16.8859 19.6125C16.9921 19.5063 16.979 19.3571 16.8823 19.2605C16.7857 19.1638 16.6341 19.1483 16.5279 19.2545C16.4253 19.3571 16.4384 19.5087 16.5351 19.6053ZM17.4422 19.3163L16.5711 18.4452L16.7322 18.2842L17.6033 19.1552L17.4422 19.3163ZM17.8 18.9895C17.7379 19.0516 17.6449 19.0492 17.5876 18.9919C17.5315 18.9359 17.5291 18.8428 17.5912 18.7807C17.6532 18.7187 17.7451 18.7223 17.8012 18.7783C17.8585 18.8356 17.862 18.9275 17.8 18.9895ZM18.2524 18.5372C18.0746 18.715 17.787 18.7114 17.6068 18.5312C17.4267 18.351 17.4207 18.0682 17.6092 17.8773C17.7214 17.7627 17.8574 17.715 17.9827 17.7353L17.96 17.9608C17.8884 17.9465 17.8133 17.9668 17.7584 18.0217C17.6558 18.1243 17.6713 18.2735 17.7679 18.3701C17.8646 18.4668 18.0173 18.4787 18.1199 18.3761C18.182 18.314 18.1915 18.2424 18.1808 18.1673L18.3991 18.1517C18.4158 18.2854 18.3741 18.4155 18.2524 18.5372ZM18.8492 17.9403C18.6571 18.1324 18.3731 18.1252 18.1942 17.9463C18.0152 17.7673 18.0068 17.4821 18.1989 17.29C18.391 17.0979 18.6762 17.1062 18.8552 17.2852C19.0342 17.4642 19.0414 17.7482 18.8492 17.9403ZM18.3552 17.7852C18.4519 17.8818 18.5999 17.8961 18.7025 17.7935C18.8051 17.6909 18.7908 17.5429 18.6941 17.4463C18.5975 17.3496 18.4483 17.3341 18.3457 17.4367C18.2431 17.5394 18.2586 17.6885 18.3552 17.7852ZM19.2356 17.523L18.6151 16.9025L18.7738 16.7438L18.8645 16.8345C18.8275 16.733 18.8537 16.6352 18.9492 16.5397C19.0363 16.4526 19.152 16.4204 19.2678 16.455C19.2344 16.3381 19.2523 16.2366 19.3608 16.1281C19.4945 15.9944 19.6962 15.9908 19.8525 16.1471L20.2319 16.5266L20.0708 16.6877L19.7308 16.3476C19.6234 16.2402 19.5255 16.245 19.4527 16.3178C19.3776 16.393 19.3608 16.4789 19.4802 16.5982L19.8202 16.9383L19.6592 17.0994L19.3191 16.7593C19.2117 16.6519 19.1115 16.659 19.0315 16.739C18.9635 16.807 18.9492 16.9144 19.0566 17.0218L19.3966 17.3619L19.2356 17.523Z" fill="white" fill-opacity="0.03"/>
<path d="M21.7325 15.0571C21.4843 15.3053 21.1037 15.2993 20.865 15.0607C20.6252 14.8208 20.6085 14.4485 20.8662 14.1908C21.0022 14.0548 21.1383 14.0023 21.3029 14.0166L21.2874 14.2373C21.1848 14.2349 21.0965 14.2707 21.0213 14.3459C20.8602 14.507 20.8853 14.7349 21.038 14.8876C21.1908 15.0404 21.4163 15.0631 21.581 14.8984C21.6621 14.8172 21.6955 14.7289 21.6907 14.6263L21.9163 14.6084C21.9294 14.748 21.8781 14.9115 21.7325 15.0571ZM22.3528 14.4368C22.1821 14.6075 21.9017 14.5991 21.7227 14.4201C21.5437 14.2411 21.533 13.9583 21.7036 13.7877C21.811 13.6803 21.9113 13.6684 22.0115 13.7018L21.9136 13.6039L22.0735 13.444L22.694 14.0645L22.5377 14.2208L22.4363 14.1194C22.4733 14.2232 22.4637 14.3259 22.3528 14.4368ZM21.8826 14.2578C21.9769 14.3521 22.1308 14.3676 22.2334 14.265C22.3396 14.1588 22.3265 14.0096 22.2299 13.913C22.1332 13.8163 21.9817 13.8008 21.8755 13.907C21.7728 14.0096 21.786 14.1612 21.8826 14.2578ZM22.7897 13.9688L21.9187 13.0978L22.0798 12.9367L22.9508 13.8077L22.7897 13.9688ZM23.1475 13.6421C23.0855 13.7041 22.9924 13.7017 22.9351 13.6444C22.879 13.5884 22.8767 13.4953 22.9387 13.4332C23.0008 13.3712 23.0926 13.3748 23.1487 13.4309C23.206 13.4881 23.2096 13.58 23.1475 13.6421ZM23.5999 13.1897C23.4221 13.3675 23.1345 13.3639 22.9544 13.1837C22.7742 13.0035 22.7682 12.7207 22.9568 12.5298C23.0689 12.4153 23.2049 12.3675 23.3302 12.3878L23.3076 12.6133C23.236 12.599 23.1608 12.6193 23.1059 12.6742C23.0033 12.7768 23.0188 12.926 23.1155 13.0226C23.2121 13.1193 23.3648 13.1312 23.4675 13.0286C23.5295 12.9665 23.5391 12.8949 23.5283 12.8198L23.7467 12.8043C23.7634 12.9379 23.7216 13.068 23.5999 13.1897ZM24.1968 12.5928C24.0047 12.7849 23.7207 12.7778 23.5417 12.5988C23.3627 12.4198 23.3544 12.1346 23.5465 11.9425C23.7386 11.7504 24.0238 11.7587 24.2027 11.9377C24.3817 12.1167 24.3889 12.4007 24.1968 12.5928ZM23.7028 12.4377C23.7994 12.5343 23.9474 12.5487 24.05 12.446C24.1526 12.3434 24.1383 12.1955 24.0417 12.0988C23.945 12.0021 23.7959 11.9866 23.6932 12.0893C23.5906 12.1919 23.6061 12.341 23.7028 12.4377ZM24.5831 12.1755L23.9626 11.555L24.1213 11.3963L24.212 11.487C24.175 11.3855 24.2013 11.2877 24.2967 11.1922C24.3838 11.1051 24.4996 11.0729 24.6153 11.1075C24.5819 10.9906 24.5998 10.8891 24.7084 10.7806C24.842 10.6469 25.0437 10.6433 25.2 10.7997L25.5795 11.1791L25.4184 11.3402L25.0783 11.0001C24.9709 10.8927 24.8731 10.8975 24.8003 10.9703C24.7251 11.0455 24.7084 11.1314 24.8277 11.2507L25.1678 11.5908L25.0067 11.7519L24.6666 11.4118C24.5592 11.3044 24.459 11.3116 24.379 11.3915C24.311 11.4595 24.2967 11.5669 24.4041 11.6743L24.7442 12.0144L24.5831 12.1755Z" fill="white" fill-opacity="0.03"/>
<path d="M12.4517 27.1663C12.2035 27.4145 11.8229 27.4085 11.5842 27.1699C11.3444 26.93 11.3277 26.5577 11.5854 26.3C11.7215 26.164 11.8575 26.1115 12.0222 26.1258L12.0067 26.3465C11.904 26.3442 11.8157 26.3799 11.7406 26.4551C11.5795 26.6162 11.6045 26.8441 11.7573 26.9969C11.91 27.1496 12.1355 27.1723 12.3002 27.0076C12.3813 26.9265 12.4147 26.8382 12.41 26.7355L12.6355 26.7176C12.6486 26.8572 12.5973 27.0207 12.4517 27.1663ZM13.072 26.546C12.9014 26.7167 12.6209 26.7083 12.442 26.5293C12.263 26.3503 12.2522 26.0675 12.4229 25.8969C12.5303 25.7895 12.6305 25.7776 12.7307 25.811L12.6329 25.7131L12.7928 25.5533L13.4133 26.1737L13.2569 26.3301L13.1555 26.2286C13.1925 26.3324 13.183 26.4351 13.072 26.546ZM12.6019 26.367C12.6961 26.4613 12.8501 26.4768 12.9527 26.3742C13.0589 26.268 13.0457 26.1189 12.9491 26.0222C12.8524 25.9255 12.7009 25.91 12.5947 26.0162C12.4921 26.1189 12.5052 26.2704 12.6019 26.367ZM13.509 26.078L12.6379 25.207L12.799 25.0459L13.6701 25.9169L13.509 26.078ZM13.8668 25.7513C13.8047 25.8133 13.7116 25.8109 13.6544 25.7537C13.5983 25.6976 13.5959 25.6045 13.6579 25.5425C13.72 25.4804 13.8119 25.484 13.868 25.5401C13.9252 25.5973 13.9288 25.6892 13.8668 25.7513ZM14.3191 25.2989C14.1414 25.4767 13.8538 25.4731 13.6736 25.2929C13.4934 25.1127 13.4875 24.8299 13.676 24.639C13.7882 24.5245 13.9242 24.4767 14.0495 24.497L14.0268 24.7225C13.9552 24.7082 13.88 24.7285 13.8251 24.7834C13.7225 24.886 13.738 25.0352 13.8347 25.1318C13.9313 25.2285 14.0841 25.2404 14.1867 25.1378C14.2487 25.0757 14.2583 25.0041 14.2476 24.929L14.4659 24.9135C14.4826 25.0471 14.4409 25.1772 14.3191 25.2989ZM14.916 24.702C14.7239 24.8941 14.4399 24.887 14.2609 24.708C14.0819 24.529 14.0736 24.2438 14.2657 24.0517C14.4578 23.8596 14.743 23.8679 14.922 24.0469C15.101 24.2259 15.1081 24.5099 14.916 24.702ZM14.422 24.5469C14.5187 24.6435 14.6666 24.6579 14.7693 24.5552C14.8719 24.4526 14.8576 24.3047 14.7609 24.208C14.6642 24.1114 14.5151 24.0958 14.4125 24.1985C14.3099 24.3011 14.3254 24.4502 14.422 24.5469ZM15.3023 24.2847L14.6818 23.6642L14.8405 23.5055L14.9312 23.5962C14.8942 23.4947 14.9205 23.3969 15.016 23.3014C15.1031 23.2143 15.2188 23.1821 15.3345 23.2167C15.3011 23.0998 15.319 22.9984 15.4276 22.8898C15.5613 22.7561 15.7629 22.7525 15.9192 22.9089L16.2987 23.2883L16.1376 23.4494L15.7975 23.1093C15.6901 23.0019 15.5923 23.0067 15.5195 23.0795C15.4443 23.1547 15.4276 23.2406 15.5469 23.3599L15.887 23.7L15.7259 23.8611L15.3859 23.521C15.2785 23.4136 15.1782 23.4208 15.0983 23.5007C15.0303 23.5687 15.016 23.6761 15.1233 23.7835L15.4634 24.1236L15.3023 24.2847Z" fill="white" fill-opacity="0.03"/>
<path d="M17.7991 21.8188C17.5509 22.067 17.1703 22.061 16.9317 21.8224C16.6918 21.5825 16.6751 21.2102 16.9328 20.9525C17.0689 20.8165 17.2049 20.764 17.3696 20.7783L17.3541 20.999C17.2514 20.9966 17.1631 21.0324 17.088 21.1076C16.9269 21.2687 16.9519 21.4966 17.1047 21.6494C17.2574 21.8021 17.4829 21.8248 17.6476 21.6601C17.7287 21.579 17.7622 21.4907 17.7574 21.388L17.9829 21.3701C17.996 21.5097 17.9447 21.6732 17.7991 21.8188ZM18.4194 21.1985C18.2488 21.3692 17.9684 21.3608 17.7894 21.1818C17.6104 21.0028 17.5996 20.72 17.7703 20.5494C17.8777 20.442 17.9779 20.4301 18.0781 20.4635L17.9803 20.3656L18.1402 20.2058L18.7607 20.8262L18.6044 20.9826L18.5029 20.8811C18.5399 20.9849 18.5304 21.0876 18.4194 21.1985ZM17.9493 21.0195C18.0435 21.1138 18.1975 21.1293 18.3001 21.0267C18.4063 20.9205 18.3932 20.7713 18.2965 20.6747C18.1998 20.578 18.0483 20.5625 17.9421 20.6687C17.8395 20.7713 17.8526 20.9229 17.9493 21.0195ZM18.8564 20.7305L17.9853 19.8595L18.1464 19.6984L19.0175 20.5694L18.8564 20.7305ZM19.2142 20.4038C19.1521 20.4658 19.059 20.4634 19.0018 20.4062C18.9457 20.3501 18.9433 20.257 19.0054 20.1949C19.0674 20.1329 19.1593 20.1365 19.2154 20.1926C19.2726 20.2498 19.2762 20.3417 19.2142 20.4038ZM19.6666 19.9514C19.4888 20.1292 19.2012 20.1256 19.021 19.9454C18.8408 19.7652 18.8349 19.4824 19.0234 19.2915C19.1356 19.177 19.2716 19.1292 19.3969 19.1495L19.3742 19.375C19.3026 19.3607 19.2274 19.381 19.1726 19.4359C19.0699 19.5385 19.0854 19.6877 19.1821 19.7843C19.2788 19.881 19.4315 19.8929 19.5341 19.7903C19.5962 19.7282 19.6057 19.6566 19.595 19.5815L19.8133 19.566C19.83 19.6996 19.7883 19.8297 19.6666 19.9514ZM20.2634 19.3545C20.0713 19.5466 19.7873 19.5395 19.6083 19.3605C19.4294 19.1815 19.421 18.8963 19.6131 18.7042C19.8052 18.5121 20.0904 18.5204 20.2694 18.6994C20.4484 18.8784 20.4555 19.1624 20.2634 19.3545ZM19.7694 19.1994C19.8661 19.296 20.014 19.3104 20.1167 19.2077C20.2193 19.1051 20.205 18.9572 20.1083 18.8605C20.0117 18.7638 19.8625 18.7483 19.7599 18.851C19.6573 18.9536 19.6728 19.1027 19.7694 19.1994ZM20.6497 18.9372L20.0293 18.3167L20.188 18.158L20.2786 18.2487C20.2417 18.1472 20.2679 18.0494 20.3634 17.9539C20.4505 17.8668 20.5662 17.8346 20.682 17.8692C20.6486 17.7523 20.6664 17.6509 20.775 17.5423C20.9087 17.4086 21.1103 17.405 21.2667 17.5614L21.6461 17.9408L21.485 18.1019L21.1449 17.7618C21.0375 17.6544 20.9397 17.6592 20.8669 17.732C20.7917 17.8072 20.775 17.8931 20.8944 18.0124L21.2344 18.3525L21.0733 18.5136L20.7333 18.1735C20.6259 18.0661 20.5256 18.0733 20.4457 18.1532C20.3777 18.2212 20.3634 18.3286 20.4708 18.436L20.8108 18.7761L20.6497 18.9372Z" fill="white" fill-opacity="0.03"/>
<path d="M23.1467 16.4713C22.8985 16.7195 22.5178 16.7135 22.2792 16.4749C22.0393 16.235 22.0226 15.8627 22.2804 15.605C22.4164 15.469 22.5524 15.4165 22.7171 15.4308L22.7016 15.6515C22.599 15.6492 22.5107 15.685 22.4355 15.7601C22.2744 15.9212 22.2995 16.1491 22.4522 16.3019C22.6049 16.4546 22.8305 16.4773 22.9951 16.3126C23.0763 16.2315 23.1097 16.1432 23.1049 16.0405L23.3304 16.0226C23.3436 16.1623 23.2923 16.3257 23.1467 16.4713ZM23.7669 15.851C23.5963 16.0217 23.3159 16.0133 23.1369 15.8343C22.9579 15.6553 22.9472 15.3726 23.1178 15.2019C23.2252 15.0945 23.3254 15.0826 23.4257 15.116L23.3278 15.0182L23.4877 14.8583L24.1082 15.4787L23.9519 15.6351L23.8505 15.5336C23.8875 15.6375 23.8779 15.7401 23.7669 15.851ZM23.2968 15.6721C23.3911 15.7663 23.545 15.7818 23.6476 15.6792C23.7538 15.573 23.7407 15.4239 23.644 15.3272C23.5474 15.2306 23.3958 15.215 23.2896 15.3212C23.187 15.4239 23.2001 15.5754 23.2968 15.6721ZM24.2039 15.383L23.3329 14.512L23.4939 14.3509L24.365 15.222L24.2039 15.383ZM24.5617 15.0563C24.4997 15.1183 24.4066 15.1159 24.3493 15.0587C24.2932 15.0026 24.2908 14.9095 24.3529 14.8475C24.4149 14.7854 24.5068 14.789 24.5629 14.8451C24.6202 14.9023 24.6238 14.9942 24.5617 15.0563ZM25.0141 14.6039C24.8363 14.7817 24.5487 14.7781 24.3685 14.5979C24.1884 14.4177 24.1824 14.1349 24.3709 13.944C24.4831 13.8295 24.6191 13.7817 24.7444 13.802L24.7217 14.0276C24.6502 14.0132 24.575 14.0335 24.5201 14.0884C24.4175 14.191 24.433 14.3402 24.5296 14.4368C24.6263 14.5335 24.779 14.5454 24.8816 14.4428C24.9437 14.3808 24.9532 14.3092 24.9425 14.234L25.1609 14.2185C25.1776 14.3521 25.1358 14.4822 25.0141 14.6039ZM25.611 14.007C25.4189 14.1991 25.1349 14.192 24.9559 14.013C24.7769 13.834 24.7685 13.5488 24.9606 13.3567C25.1528 13.1646 25.4379 13.1729 25.6169 13.3519C25.7959 13.5309 25.8031 13.8149 25.611 14.007ZM25.117 13.8519C25.2136 13.9485 25.3616 13.9629 25.4642 13.8602C25.5668 13.7576 25.5525 13.6097 25.4558 13.513C25.3592 13.4164 25.21 13.4008 25.1074 13.5035C25.0048 13.6061 25.0203 13.7552 25.117 13.8519ZM25.9973 13.5897L25.3768 12.9692L25.5355 12.8105L25.6262 12.9012C25.5892 12.7998 25.6154 12.7019 25.7109 12.6064C25.798 12.5193 25.9138 12.4871 26.0295 12.5217C25.9961 12.4048 26.014 12.3034 26.1226 12.1948C26.2562 12.0611 26.4579 12.0576 26.6142 12.2139L26.9936 12.5933L26.8325 12.7544L26.4925 12.4143C26.3851 12.3069 26.2872 12.3117 26.2144 12.3845C26.1393 12.4597 26.1226 12.5456 26.2419 12.6649L26.582 13.005L26.4209 13.1661L26.0808 12.826C25.9734 12.7186 25.8732 12.7258 25.7932 12.8057C25.7252 12.8737 25.7109 12.9811 25.8183 13.0885L26.1584 13.4286L25.9973 13.5897Z" fill="white" fill-opacity="0.03"/>
<path d="M13.8659 28.5805C13.6177 28.8287 13.2371 28.8227 12.9984 28.5841C12.7586 28.3442 12.7419 27.972 12.9996 27.7142C13.1357 27.5782 13.2717 27.5257 13.4363 27.54L13.4208 27.7608C13.3182 27.7584 13.2299 27.7942 13.1547 27.8693C12.9937 28.0304 13.0187 28.2583 13.1714 28.4111C13.3242 28.5638 13.5497 28.5865 13.7144 28.4218C13.7955 28.3407 13.8289 28.2524 13.8242 28.1498L14.0497 28.1319C14.0628 28.2715 14.0115 28.4349 13.8659 28.5805ZM14.4862 27.9602C14.3155 28.1309 14.0351 28.1225 13.8561 27.9435C13.6772 27.7646 13.6664 27.4818 13.8371 27.3111C13.9444 27.2037 14.0447 27.1918 14.1449 27.2252L14.0471 27.1274L14.207 26.9675L14.8274 27.588L14.6711 27.7443L14.5697 27.6428C14.6067 27.7467 14.5971 27.8493 14.4862 27.9602ZM14.016 27.7813C14.1103 27.8755 14.2642 27.891 14.3669 27.7884C14.4731 27.6822 14.4599 27.5331 14.3633 27.4364C14.2666 27.3398 14.1151 27.3243 14.0089 27.4304C13.9063 27.5331 13.9194 27.6846 14.016 27.7813ZM14.9232 27.4922L14.0521 26.6212L14.2132 26.4601L15.0842 27.3312L14.9232 27.4922ZM15.2809 27.1655C15.2189 27.2275 15.1258 27.2251 15.0685 27.1679C15.0125 27.1118 15.0101 27.0187 15.0721 26.9567C15.1342 26.8946 15.2261 26.8982 15.2821 26.9543C15.3394 27.0116 15.343 27.1034 15.2809 27.1655ZM15.7333 26.7131C15.5555 26.8909 15.268 26.8873 15.0878 26.7071C14.9076 26.5269 14.9016 26.2442 15.0902 26.0532C15.2023 25.9387 15.3384 25.891 15.4637 25.9112L15.441 26.1368C15.3694 26.1224 15.2942 26.1427 15.2393 26.1976C15.1367 26.3002 15.1522 26.4494 15.2489 26.546C15.3455 26.6427 15.4983 26.6546 15.6009 26.552C15.6629 26.49 15.6725 26.4184 15.6617 26.3432L15.8801 26.3277C15.8968 26.4613 15.855 26.5914 15.7333 26.7131ZM16.3302 26.1162C16.1381 26.3083 15.8541 26.3012 15.6751 26.1222C15.4961 25.9432 15.4878 25.658 15.6799 25.4659C15.872 25.2738 16.1572 25.2821 16.3362 25.4611C16.5152 25.6401 16.5223 25.9241 16.3302 26.1162ZM15.8362 25.9611C15.9329 26.0578 16.0808 26.0721 16.1834 25.9695C16.2861 25.8668 16.2717 25.7189 16.1751 25.6222C16.0784 25.5256 15.9293 25.5101 15.8267 25.6127C15.724 25.7153 15.7395 25.8644 15.8362 25.9611ZM16.7165 25.6989L16.096 25.0784L16.2547 24.9197L16.3454 25.0104C16.3084 24.909 16.3347 24.8111 16.4301 24.7157C16.5172 24.6285 16.633 24.5963 16.7487 24.6309C16.7153 24.514 16.7332 24.4126 16.8418 24.304C16.9755 24.1703 17.1771 24.1668 17.3334 24.3231L17.7129 24.7025L17.5518 24.8636L17.2117 24.5235C17.1043 24.4161 17.0065 24.4209 16.9337 24.4937C16.8585 24.5689 16.8418 24.6548 16.9611 24.7741L17.3012 25.1142L17.1401 25.2753L16.8 24.9352C16.6927 24.8278 16.5924 24.835 16.5125 24.9149C16.4445 24.9829 16.4301 25.0903 16.5375 25.1977L16.8776 25.5378L16.7165 25.6989Z" fill="white" fill-opacity="0.03"/>
<path d="M19.2133 23.233C18.9651 23.4812 18.5845 23.4752 18.3458 23.2366C18.106 22.9967 18.0893 22.6245 18.347 22.3667C18.4831 22.2307 18.6191 22.1782 18.7838 22.1925L18.7682 22.4132C18.6656 22.4109 18.5773 22.4467 18.5022 22.5218C18.3411 22.6829 18.3661 22.9108 18.5189 23.0636C18.6716 23.2163 18.8971 23.239 19.0618 23.0743C19.1429 22.9932 19.1763 22.9049 19.1716 22.8022L19.3971 22.7843C19.4102 22.924 19.3589 23.0874 19.2133 23.233ZM19.8336 22.6127C19.663 22.7834 19.3825 22.775 19.2036 22.596C19.0246 22.4171 19.0138 22.1343 19.1845 21.9636C19.2919 21.8562 19.3921 21.8443 19.4923 21.8777L19.3945 21.7799L19.5544 21.62L20.1749 22.2405L20.0185 22.3968L19.9171 22.2953C19.9541 22.3992 19.9446 22.5018 19.8336 22.6127ZM19.3635 22.4338C19.4577 22.528 19.6116 22.5435 19.7143 22.4409C19.8205 22.3347 19.8073 22.1856 19.7107 22.0889C19.614 21.9923 19.4625 21.9767 19.3563 22.0829C19.2537 22.1856 19.2668 22.3371 19.3635 22.4338ZM20.2706 22.1447L19.3995 21.2737L19.5606 21.1126L20.4317 21.9837L20.2706 22.1447ZM20.6284 21.818C20.5663 21.88 20.4732 21.8776 20.416 21.8204C20.3599 21.7643 20.3575 21.6712 20.4195 21.6092C20.4816 21.5471 20.5735 21.5507 20.6295 21.6068C20.6868 21.6641 20.6904 21.7559 20.6284 21.818ZM21.0807 21.3656C20.9029 21.5434 20.6154 21.5398 20.4352 21.3596C20.255 21.1794 20.2491 20.8966 20.4376 20.7057C20.5498 20.5912 20.6858 20.5434 20.8111 20.5637L20.7884 20.7893C20.7168 20.7749 20.6416 20.7952 20.5867 20.8501C20.4841 20.9527 20.4996 21.1019 20.5963 21.1985C20.6929 21.2952 20.8457 21.3071 20.9483 21.2045C21.0103 21.1425 21.0199 21.0709 21.0091 20.9957L21.2275 20.9802C21.2442 21.1138 21.2025 21.2439 21.0807 21.3656ZM21.6776 20.7687C21.4855 20.9608 21.2015 20.9537 21.0225 20.7747C20.8435 20.5957 20.8352 20.3105 21.0273 20.1184C21.2194 19.9263 21.5046 19.9346 21.6836 20.1136C21.8626 20.2926 21.8697 20.5766 21.6776 20.7687ZM21.1836 20.6136C21.2803 20.7102 21.4282 20.7246 21.5308 20.6219C21.6335 20.5193 21.6191 20.3714 21.5225 20.2747C21.4258 20.1781 21.2767 20.1626 21.1741 20.2652C21.0714 20.3678 21.087 20.5169 21.1836 20.6136ZM22.0639 20.3514L21.4434 19.7309L21.6021 19.5722L21.6928 19.6629C21.6558 19.5615 21.6821 19.4636 21.7776 19.3682C21.8647 19.281 21.9804 19.2488 22.0961 19.2834C22.0627 19.1665 22.0806 19.0651 22.1892 18.9565C22.3229 18.8228 22.5245 18.8193 22.6808 18.9756L23.0603 19.355L22.8992 19.5161L22.5591 19.176C22.4517 19.0686 22.3539 19.0734 22.2811 19.1462C22.2059 19.2214 22.1892 19.3073 22.3085 19.4266L22.6486 19.7667L22.4875 19.9278L22.1475 19.5877C22.0401 19.4803 21.9398 19.4875 21.8599 19.5674C21.7919 19.6354 21.7776 19.7428 21.8849 19.8502L22.225 20.1903L22.0639 20.3514Z" fill="white" fill-opacity="0.03"/>
<path d="M24.5609 17.8855C24.3127 18.1337 23.932 18.1277 23.6934 17.8891C23.4535 17.6493 23.4368 17.277 23.6946 17.0192C23.8306 16.8832 23.9666 16.8307 24.1313 16.845L24.1158 17.0658C24.0132 17.0634 23.9249 17.0992 23.8497 17.1743C23.6886 17.3354 23.7137 17.5633 23.8664 17.7161C24.0191 17.8688 24.2447 17.8915 24.4093 17.7268C24.4905 17.6457 24.5239 17.5574 24.5191 17.4548L24.7446 17.4369C24.7577 17.5765 24.7064 17.7399 24.5609 17.8855ZM25.1811 17.2653C25.0105 17.4359 24.7301 17.4275 24.5511 17.2486C24.3721 17.0696 24.3614 16.7868 24.532 16.6161C24.6394 16.5087 24.7396 16.4968 24.8399 16.5302L24.742 16.4324L24.9019 16.2725L25.5224 16.893L25.3661 17.0493L25.2647 16.9479C25.3016 17.0517 25.2921 17.1543 25.1811 17.2653ZM24.711 17.0863C24.8053 17.1805 24.9592 17.196 25.0618 17.0934C25.168 16.9872 25.1549 16.8381 25.0582 16.7414C24.9616 16.6448 24.81 16.6293 24.7038 16.7355C24.6012 16.8381 24.6143 16.9896 24.711 17.0863ZM25.6181 16.7973L24.747 15.9262L24.9081 15.7651L25.7792 16.6362L25.6181 16.7973ZM25.9759 16.4705C25.9138 16.5325 25.8208 16.5302 25.7635 16.4729C25.7074 16.4168 25.705 16.3237 25.7671 16.2617C25.8291 16.1996 25.921 16.2032 25.9771 16.2593C26.0344 16.3166 26.0379 16.4084 25.9759 16.4705ZM26.4283 16.0181C26.2505 16.1959 25.9629 16.1923 25.7827 16.0121C25.6026 15.832 25.5966 15.5492 25.7851 15.3582C25.8973 15.2437 26.0333 15.196 26.1586 15.2162L26.1359 15.4418C26.0643 15.4274 25.9892 15.4477 25.9343 15.5026C25.8317 15.6052 25.8472 15.7544 25.9438 15.851C26.0405 15.9477 26.1932 15.9596 26.2958 15.857C26.3579 15.795 26.3674 15.7234 26.3567 15.6482L26.575 15.6327C26.5918 15.7663 26.55 15.8964 26.4283 16.0181ZM27.0252 15.4212C26.833 15.6133 26.549 15.6062 26.3701 15.4272C26.1911 15.2482 26.1827 14.963 26.3748 14.7709C26.5669 14.5788 26.8521 14.5872 27.0311 14.7661C27.2101 14.9451 27.2173 15.2291 27.0252 15.4212ZM26.5311 15.2661C26.6278 15.3628 26.7758 15.3771 26.8784 15.2745C26.981 15.1718 26.9667 15.0239 26.87 14.9272C26.7734 14.8306 26.6242 14.8151 26.5216 14.9177C26.419 15.0203 26.4345 15.1695 26.5311 15.2661ZM27.4115 15.0039L26.791 14.3834L26.9497 14.2247L27.0404 14.3154C27.0034 14.214 27.0296 14.1161 27.1251 14.0207C27.2122 13.9336 27.3279 13.9013 27.4437 13.9359C27.4103 13.819 27.4282 13.7176 27.5368 13.609C27.6704 13.4753 27.8721 13.4718 28.0284 13.6281L28.4078 14.0075L28.2467 14.1686L27.9067 13.8285C27.7993 13.7212 27.7014 13.7259 27.6286 13.7987C27.5535 13.8739 27.5368 13.9598 27.6561 14.0791L27.9962 14.4192L27.8351 14.5803L27.495 14.2402C27.3876 14.1328 27.2874 14.14 27.2074 14.2199C27.1394 14.2879 27.1251 14.3953 27.2325 14.5027L27.5726 14.8428L27.4115 15.0039Z" fill="white" fill-opacity="0.03"/>
<path d="M20.6275 24.6472C20.3793 24.8954 19.9987 24.8895 19.76 24.6508C19.5202 24.411 19.5035 24.0387 19.7612 23.7809C19.8972 23.6449 20.0333 23.5924 20.1979 23.6067L20.1824 23.8275C20.0798 23.8251 19.9915 23.8609 19.9163 23.936C19.7553 24.0971 19.7803 24.325 19.933 24.4778C20.0858 24.6305 20.3113 24.6532 20.476 24.4885C20.5571 24.4074 20.5905 24.3191 20.5857 24.2165L20.8113 24.1986C20.8244 24.3382 20.7731 24.5016 20.6275 24.6472ZM21.2478 24.027C21.0771 24.1976 20.7967 24.1892 20.6177 24.0103C20.4388 23.8313 20.428 23.5485 20.5987 23.3778C20.706 23.2704 20.8063 23.2585 20.9065 23.2919L20.8087 23.1941L20.9686 23.0342L21.589 23.6547L21.4327 23.811L21.3313 23.7096C21.3683 23.8134 21.3587 23.916 21.2478 24.027ZM20.7776 23.848C20.8719 23.9422 21.0258 23.9578 21.1285 23.8551C21.2346 23.7489 21.2215 23.5998 21.1249 23.5031C21.0282 23.4065 20.8767 23.391 20.7705 23.4972C20.6679 23.5998 20.681 23.7513 20.7776 23.848ZM21.6848 23.559L20.8137 22.6879L20.9748 22.5268L21.8458 23.3979L21.6848 23.559ZM22.0425 23.2322C21.9805 23.2942 21.8874 23.2919 21.8301 23.2346C21.7741 23.1785 21.7717 23.0854 21.8337 23.0234C21.8958 22.9613 21.9877 22.9649 22.0437 23.021C22.101 23.0783 22.1046 23.1701 22.0425 23.2322ZM22.4949 22.7798C22.3171 22.9576 22.0296 22.954 21.8494 22.7738C21.6692 22.5937 21.6632 22.3109 21.8518 22.1199C21.9639 22.0054 22.1 21.9577 22.2253 21.9779L22.2026 22.2035C22.131 22.1892 22.0558 22.2094 22.0009 22.2643C21.8983 22.3669 21.9138 22.5161 22.0105 22.6128C22.1071 22.7094 22.2599 22.7213 22.3625 22.6187C22.4245 22.5567 22.4341 22.4851 22.4233 22.4099L22.6417 22.3944C22.6584 22.528 22.6166 22.6581 22.4949 22.7798ZM23.0918 22.1829C22.8997 22.375 22.6157 22.3679 22.4367 22.1889C22.2577 22.0099 22.2494 21.7247 22.4415 21.5326C22.6336 21.3405 22.9188 21.3489 23.0978 21.5278C23.2768 21.7068 23.2839 21.9908 23.0918 22.1829ZM22.5978 22.0278C22.6945 22.1245 22.8424 22.1388 22.945 22.0362C23.0477 21.9335 23.0333 21.7856 22.9367 21.6889C22.84 21.5923 22.6909 21.5768 22.5883 21.6794C22.4856 21.782 22.5011 21.9312 22.5978 22.0278ZM23.4781 21.7656L22.8576 21.1451L23.0163 20.9864L23.107 21.0771C23.07 20.9757 23.0963 20.8778 23.1917 20.7824C23.2788 20.6953 23.3946 20.663 23.5103 20.6976C23.4769 20.5807 23.4948 20.4793 23.6034 20.3707C23.737 20.2371 23.9387 20.2335 24.095 20.3898L24.4745 20.7692L24.3134 20.9303L23.9733 20.5903C23.8659 20.4829 23.7681 20.4876 23.6953 20.5604C23.6201 20.6356 23.6034 20.7215 23.7227 20.8408L24.0628 21.1809L23.9017 21.342L23.5616 21.0019C23.4542 20.8945 23.354 20.9017 23.2741 20.9816C23.2061 21.0497 23.1917 21.157 23.2991 21.2644L23.6392 21.6045L23.4781 21.7656Z" fill="white" fill-opacity="0.03"/>
</g>
<g filter="url(#filter0_dd_10423_610363)">
<rect x="4.21875" y="7.21875" width="10.5693" height="9.54172" rx="2.20193" fill="url(#paint2_linear_10423_610363)"/>
</g>
<g filter="url(#filter1_ddi_10423_610363)">
<path d="M15.4874 12.9913V10.9145C15.4874 10.569 15.6247 10.2376 15.869 9.99328L17.8658 7.99648C18.0818 7.78048 18.3748 7.65913 18.6802 7.65913H18.7162C18.9986 7.65913 19.2695 7.77134 19.4693 7.97107C19.669 8.17081 19.7812 8.4417 19.7812 8.72417V15.1816C19.7812 15.4641 19.669 15.735 19.4693 15.9347C19.2695 16.1345 18.9986 16.2467 18.7162 16.2467H18.6802C18.3748 16.2467 18.0818 16.1253 17.8658 15.9093L15.869 13.9125C15.6247 13.6682 15.4874 13.3368 15.4874 12.9913Z" fill="url(#paint3_linear_10423_610363)"/>
</g>
</g>
<rect x="0.0703125" y="0.0703125" width="23.8594" height="23.8594" rx="5.36719" stroke="#EDE9FE" stroke-opacity="0.25" stroke-width="0.140625"/>
<defs>
<filter id="filter0_dd_10423_610363" x="3.22988" y="6.5625" width="12.5471" height="11.6363" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="0.449486"/>
<feGaussianBlur stdDeviation="0.494435"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_10423_610363"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="0.1875"/>
<feGaussianBlur stdDeviation="0.421875"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_10423_610363" result="effect2_dropShadow_10423_610363"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_10423_610363" result="shape"/>
</filter>
<filter id="filter1_ddi_10423_610363" x="14.4986" y="7.00288" width="6.27156" height="10.6821" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="0.449486"/>
<feGaussianBlur stdDeviation="0.494435"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_10423_610363"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="0.1875"/>
<feGaussianBlur stdDeviation="0.421875"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_10423_610363" result="effect2_dropShadow_10423_610363"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_10423_610363" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="0.046875" operator="erode" in="SourceAlpha" result="effect3_innerShadow_10423_610363"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.28125"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_10423_610363"/>
</filter>
<linearGradient id="paint0_linear_10423_610363" x1="12" y1="0" x2="12" y2="28.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#2E3440"/>
<stop offset="1" stop-color="#13161C"/>
</linearGradient>
<linearGradient id="paint1_linear_10423_610363" x1="7.03128" y1="19.0969" x2="-2.87927" y2="37.8905" gradientUnits="userSpaceOnUse">
<stop stop-color="#D9D9D9" stop-opacity="0"/>
<stop offset="1" stop-color="#D9D9D9"/>
</linearGradient>
<linearGradient id="paint2_linear_10423_610363" x1="9.50339" y1="7.21875" x2="9.50339" y2="16.7605" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E8EDF0"/>
</linearGradient>
<linearGradient id="paint3_linear_10423_610363" x1="17.6343" y1="7.65913" x2="17.6343" y2="16.2467" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E8EDF0"/>
</linearGradient>
<clipPath id="clip0_10423_610363">
<rect width="24" height="24" rx="5.4375" fill="white"/>
</clipPath>
</defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 142 KiB

Loaded 100 of 309 files, more files were not shown because too many files have changed in this diff. Show more