kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/715/head
rodzic
ab85f07c6d
commit
db4d24a452
|
@ -2,8 +2,8 @@ import Link from 'next/link'
|
|||
|
||||
import { DotsSection } from '@/components/dots-section'
|
||||
import { ExampleAgenticConfigs } from '@/components/example-agentic-configs'
|
||||
import { Features } from '@/components/features'
|
||||
import { GitHubStarCounter } from '@/components/github-star-counter'
|
||||
import { MCPGatewayFeatures } from '@/components/mcp-gateway-features'
|
||||
import { SupplySideCTA } from '@/components/supply-side-cta'
|
||||
import { githubUrl, twitterUrl } from '@/lib/config'
|
||||
|
||||
|
@ -63,7 +63,7 @@ export default function MCPAuthorsPage() {
|
|||
Production-Ready MCP Gateway
|
||||
</h2>
|
||||
|
||||
<Features />
|
||||
<MCPGatewayFeatures />
|
||||
</section>
|
||||
|
||||
{/* Open source section */}
|
||||
|
|
|
@ -5,6 +5,8 @@ import { DemandSideCTA } from '@/components/demand-side-cta'
|
|||
import { DotsSection } from '@/components/dots-section'
|
||||
import { ExampleUsage } from '@/components/example-usage'
|
||||
import { GitHubStarCounter } from '@/components/github-star-counter'
|
||||
import { HeroSimulation2 } from '@/components/hero-simulation-2'
|
||||
import { MCPMarketplaceFeatures } from '@/components/mcp-marketplace-features'
|
||||
import { githubUrl, twitterUrl } from '@/lib/config'
|
||||
import {
|
||||
defaultConfig,
|
||||
|
@ -50,10 +52,6 @@ export default async function TheBestDamnLandingPageEver() {
|
|||
</div>
|
||||
</DotsSection>
|
||||
|
||||
{/* <div className='w-[40%] h-full min-h-full' />
|
||||
|
||||
<HeroSimulation2 className='absolute! top-[-50%]! left-[30%] w-full h-[200%]!' /> */}
|
||||
|
||||
{/* How it works section */}
|
||||
<section className='flex flex-col gap-8 mb-16'>
|
||||
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||
|
@ -90,15 +88,26 @@ export default async function TheBestDamnLandingPageEver() {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
{/* Marketplace section */}
|
||||
<section className='flex flex-col gap-8 mb-16'>
|
||||
<section className='flex flex-col items-center gap-8 text-center mb-16'>
|
||||
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||
MCP Tools that just work
|
||||
Agentic tools are{' '}
|
||||
<span className='font-semibold'>production-ready</span>
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<i>Coming soon...</i>
|
||||
</p>
|
||||
<MCPMarketplaceFeatures />
|
||||
</section>
|
||||
|
||||
<section className='flex flex-col items-center gap-8 text-center mb-16 max-w-2xl'>
|
||||
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||
Agentic makes managing{' '}
|
||||
<span className='font-semibold'>MCP servers</span> simple
|
||||
</h2>
|
||||
|
||||
<div className='h-96 w-full rounded-lg overflow-hidden shadow-sm'>
|
||||
<HeroSimulation2 />
|
||||
</div>
|
||||
|
||||
<p className='text-sm'>TODO</p>
|
||||
</section>
|
||||
|
||||
{/* Open source section */}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
'use client'
|
||||
|
||||
import type { ComponentType, ReactNode } from 'react'
|
||||
import {
|
||||
motion,
|
||||
type MotionValue,
|
||||
useMotionTemplate,
|
||||
useMotionValue
|
||||
} from 'motion/react'
|
||||
import Link from 'next/link'
|
||||
|
||||
import { GridPattern } from './grid-pattern'
|
||||
|
||||
export type FeatureData = {
|
||||
name: string
|
||||
description: ReactNode
|
||||
icon: ComponentType<{ className?: string }>
|
||||
pattern: Omit<GridPattern, 'width' | 'height' | 'x'>
|
||||
href?: string
|
||||
}
|
||||
|
||||
export function Feature({
|
||||
name,
|
||||
description,
|
||||
icon,
|
||||
pattern,
|
||||
href
|
||||
}: FeatureData) {
|
||||
const mouseX = useMotionValue(0)
|
||||
const mouseY = useMotionValue(0)
|
||||
|
||||
function onMouseMove({
|
||||
currentTarget,
|
||||
clientX,
|
||||
clientY
|
||||
}: React.MouseEvent<HTMLElement>) {
|
||||
const { left, top } = currentTarget.getBoundingClientRect()
|
||||
mouseX.set(clientX - left)
|
||||
mouseY.set(clientY - top)
|
||||
}
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<FeaturePattern {...pattern} mouseX={mouseX} mouseY={mouseY} />
|
||||
|
||||
<div className='ring-gray-900/7.5 group-hover:ring-gray-900/10 absolute inset-0 rounded-2xl ring-1 ring-inset dark:ring-white/10 dark:group-hover:ring-white/20' />
|
||||
|
||||
<div className='relative rounded-2xl p-4 flex flex-col gap-6 pt-12 text-start'>
|
||||
<FeatureIcon icon={icon} />
|
||||
|
||||
<h3 className='text-gray-900 text-lg font-semibold leading-0 dark:text-white'>
|
||||
{/* <span className='absolute inset-0 rounded-2xl' /> */}
|
||||
{name}
|
||||
</h3>
|
||||
|
||||
<p className='text-gray-600 dark:text-gray-400 text-[0.875rem] leading-[1.5rem]'>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
const className =
|
||||
'dark:bg-white/2.5 bg-gray-50 hover:shadow-gray-900/5 group relative flex rounded-2xl transition-shadow hover:shadow-md dark:hover:shadow-black/5'
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
key={name}
|
||||
onMouseMove={onMouseMove}
|
||||
className={className}
|
||||
>
|
||||
{content}
|
||||
</Link>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div key={name} onMouseMove={onMouseMove} className={className}>
|
||||
{content}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
function FeatureIcon({ icon: Icon }: { icon: FeatureData['icon'] }) {
|
||||
return (
|
||||
<div className='dark:bg-white/7.5 bg-gray-900/5 ring-gray-900/25 group-hover:ring-gray-900/25 dark:group-hover:bg-sky-300/10 dark:group-hover:ring-sky-400 flex size-7 items-center justify-center rounded-full ring-1 backdrop-blur-[2px] transition duration-300 group-hover:bg-white/50 dark:ring-white/15'>
|
||||
<Icon className='fill-gray-700/10 stroke-gray-700 group-hover:stroke-gray-900 dark:stroke-gray-400 dark:group-hover:stroke-sky-400 dark:group-hover:fill-sky-300/10 size-5 transition-colors duration-300 dark:fill-white/10' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FeaturePattern({
|
||||
mouseX,
|
||||
mouseY,
|
||||
...gridProps
|
||||
}: FeatureData['pattern'] & {
|
||||
mouseX: MotionValue<number>
|
||||
mouseY: MotionValue<number>
|
||||
}) {
|
||||
const maskImage = useMotionTemplate`radial-gradient(180px at ${mouseX}px ${mouseY}px, white, transparent)`
|
||||
const style = { maskImage, WebkitMaskImage: maskImage }
|
||||
|
||||
return (
|
||||
<div className='pointer-events-none'>
|
||||
<div className='absolute inset-0 rounded-2xl transition duration-300 [mask-image:linear-gradient(white,transparent)] group-hover:opacity-50'>
|
||||
<GridPattern
|
||||
width={72}
|
||||
height={56}
|
||||
x='50%'
|
||||
className='dark:fill-white/1 dark:stroke-white/2.5 absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/[0.02] stroke-black/5'
|
||||
{...gridProps}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
className='from-sky-100 to-sky-300 dark:from-sky-500 dark:to-sky-300 absolute inset-0 rounded-2xl bg-gradient-to-r opacity-0 transition duration-300 group-hover:opacity-50 dark:group-hover:opacity-15'
|
||||
style={style}
|
||||
/>
|
||||
|
||||
<motion.div
|
||||
className='absolute inset-0 rounded-2xl opacity-0 mix-blend-overlay transition duration-300 group-hover:opacity-100'
|
||||
style={style}
|
||||
>
|
||||
<GridPattern
|
||||
width={72}
|
||||
height={56}
|
||||
x='50%'
|
||||
className='dark:fill-white/2.5 absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/50 stroke-black/70 dark:stroke-white/10'
|
||||
{...gridProps}
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -10,6 +10,7 @@ import {
|
|||
SMAA,
|
||||
SSAO
|
||||
} from '@react-three/postprocessing'
|
||||
import { useEffect, useState } from 'react'
|
||||
import * as THREE from 'three'
|
||||
|
||||
const rfs = THREE.MathUtils.randFloatSpread
|
||||
|
@ -21,6 +22,22 @@ const baubleMaterial = new THREE.MeshStandardMaterial({
|
|||
})
|
||||
|
||||
export function HeroSimulation2({ className }: { className?: string }) {
|
||||
const [hovered, setHovered] = useState(false)
|
||||
|
||||
// Change cursor on hovered state
|
||||
useEffect(() => {
|
||||
if (hovered) {
|
||||
document.body.style.cursor = 'none'
|
||||
} else {
|
||||
document.body.style.cursor = 'auto'
|
||||
}
|
||||
// document.body.style.cursor = hovered
|
||||
// ? 'none'
|
||||
// : `url('data:image/svg+xml;base64,${btoa(
|
||||
// '<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="16" cy="16" r="10" fill="#E8B059"/></svg>'
|
||||
// )}'), auto`
|
||||
}, [hovered])
|
||||
|
||||
return (
|
||||
<Canvas
|
||||
shadows
|
||||
|
@ -28,6 +45,8 @@ export function HeroSimulation2({ className }: { className?: string }) {
|
|||
dpr={[1, 1.5]}
|
||||
camera={{ position: [0, 0, 20], fov: 35, near: 1, far: 40 }}
|
||||
className={className}
|
||||
onPointerOver={() => setHovered(true)}
|
||||
onPointerOut={() => setHovered(false)}
|
||||
>
|
||||
<ambientLight intensity={0.5} />
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
'use client'
|
||||
|
||||
import type { ComponentType, ReactNode } from 'react'
|
||||
import {
|
||||
ChartNoAxesCombinedIcon,
|
||||
CheckCheckIcon,
|
||||
|
@ -12,27 +11,13 @@ import {
|
|||
TextSelectIcon,
|
||||
UserIcon
|
||||
} from 'lucide-react'
|
||||
import {
|
||||
motion,
|
||||
type MotionValue,
|
||||
useMotionTemplate,
|
||||
useMotionValue
|
||||
} from 'motion/react'
|
||||
import Link from 'next/link'
|
||||
|
||||
import { calendarBookingUrl, docsUrl } from '@/lib/config'
|
||||
|
||||
import { GridPattern } from './grid-pattern'
|
||||
import { Feature, type FeatureData } from './feature'
|
||||
|
||||
type Feature = {
|
||||
name: string
|
||||
description: ReactNode
|
||||
icon: ComponentType<{ className?: string }>
|
||||
pattern: Omit<GridPattern, 'width' | 'height' | 'x'>
|
||||
href?: string
|
||||
}
|
||||
|
||||
const FEATURES: Feature[] = [
|
||||
const mcpGatewayFeatures: FeatureData[] = [
|
||||
{
|
||||
name: 'Auth',
|
||||
description: (
|
||||
|
@ -210,122 +195,11 @@ const FEATURES: Feature[] = [
|
|||
}
|
||||
]
|
||||
|
||||
function Feature({ name, description, icon, pattern, href }: Feature) {
|
||||
const mouseX = useMotionValue(0)
|
||||
const mouseY = useMotionValue(0)
|
||||
|
||||
function onMouseMove({
|
||||
currentTarget,
|
||||
clientX,
|
||||
clientY
|
||||
}: React.MouseEvent<HTMLElement>) {
|
||||
const { left, top } = currentTarget.getBoundingClientRect()
|
||||
mouseX.set(clientX - left)
|
||||
mouseY.set(clientY - top)
|
||||
}
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<FeaturePattern {...pattern} mouseX={mouseX} mouseY={mouseY} />
|
||||
|
||||
<div className='ring-gray-900/7.5 group-hover:ring-gray-900/10 absolute inset-0 rounded-2xl ring-1 ring-inset dark:ring-white/10 dark:group-hover:ring-white/20' />
|
||||
|
||||
<div className='relative rounded-2xl p-4 flex flex-col gap-6 pt-12'>
|
||||
<FeatureIcon icon={icon} />
|
||||
|
||||
<h3 className='text-gray-900 text-lg font-semibold leading-0 dark:text-white'>
|
||||
{/* <span className='absolute inset-0 rounded-2xl' /> */}
|
||||
{name}
|
||||
</h3>
|
||||
|
||||
<p className='text-gray-600 dark:text-gray-400 text-[0.875rem] leading-[1.5rem]'>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
const className =
|
||||
'dark:bg-white/2.5 bg-gray-50 hover:shadow-gray-900/5 group relative flex rounded-2xl transition-shadow hover:shadow-md dark:hover:shadow-black/5'
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
key={name}
|
||||
onMouseMove={onMouseMove}
|
||||
className={className}
|
||||
>
|
||||
{content}
|
||||
</Link>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div key={name} onMouseMove={onMouseMove} className={className}>
|
||||
{content}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
function FeatureIcon({ icon: Icon }: { icon: Feature['icon'] }) {
|
||||
return (
|
||||
<div className='dark:bg-white/7.5 bg-gray-900/5 ring-gray-900/25 group-hover:ring-gray-900/25 dark:group-hover:bg-sky-300/10 dark:group-hover:ring-sky-400 flex size-7 items-center justify-center rounded-full ring-1 backdrop-blur-[2px] transition duration-300 group-hover:bg-white/50 dark:ring-white/15'>
|
||||
<Icon className='fill-gray-700/10 stroke-gray-700 group-hover:stroke-gray-900 dark:stroke-gray-400 dark:group-hover:stroke-sky-400 dark:group-hover:fill-sky-300/10 size-5 transition-colors duration-300 dark:fill-white/10' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FeaturePattern({
|
||||
mouseX,
|
||||
mouseY,
|
||||
...gridProps
|
||||
}: Feature['pattern'] & {
|
||||
mouseX: MotionValue<number>
|
||||
mouseY: MotionValue<number>
|
||||
}) {
|
||||
const maskImage = useMotionTemplate`radial-gradient(180px at ${mouseX}px ${mouseY}px, white, transparent)`
|
||||
const style = { maskImage, WebkitMaskImage: maskImage }
|
||||
|
||||
return (
|
||||
<div className='pointer-events-none'>
|
||||
<div className='absolute inset-0 rounded-2xl transition duration-300 [mask-image:linear-gradient(white,transparent)] group-hover:opacity-50'>
|
||||
<GridPattern
|
||||
width={72}
|
||||
height={56}
|
||||
x='50%'
|
||||
className='dark:fill-white/1 dark:stroke-white/2.5 absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/[0.02] stroke-black/5'
|
||||
{...gridProps}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
className='from-sky-100 to-sky-300 dark:from-sky-500 dark:to-sky-300 absolute inset-0 rounded-2xl bg-gradient-to-r opacity-0 transition duration-300 group-hover:opacity-50 dark:group-hover:opacity-15'
|
||||
style={style}
|
||||
/>
|
||||
|
||||
<motion.div
|
||||
className='absolute inset-0 rounded-2xl opacity-0 mix-blend-overlay transition duration-300 group-hover:opacity-100'
|
||||
style={style}
|
||||
>
|
||||
<GridPattern
|
||||
width={72}
|
||||
height={56}
|
||||
x='50%'
|
||||
className='dark:fill-white/2.5 absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/50 stroke-black/70 dark:stroke-white/10'
|
||||
{...gridProps}
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Features() {
|
||||
export function MCPGatewayFeatures() {
|
||||
return (
|
||||
<div className='xl:max-w-none'>
|
||||
<div className='not-prose grid grid-cols-1 gap-8 sm:grid-cols-2 xl:grid-cols-3'>
|
||||
{FEATURES.map((feature) => (
|
||||
{mcpGatewayFeatures.map((feature) => (
|
||||
<Feature key={feature.name} {...feature} />
|
||||
))}
|
||||
</div>
|
|
@ -0,0 +1,136 @@
|
|||
'use client'
|
||||
|
||||
import {
|
||||
CheckCheckIcon,
|
||||
CreditCardIcon,
|
||||
FileJsonIcon,
|
||||
HistoryIcon,
|
||||
ShieldCheckIcon,
|
||||
StarIcon
|
||||
} from 'lucide-react'
|
||||
|
||||
import { Feature, type FeatureData } from './feature'
|
||||
|
||||
const mcpMarketplaceFeatures: FeatureData[] = [
|
||||
{
|
||||
name: 'Highly Curated Tools',
|
||||
description: (
|
||||
<>
|
||||
All Agentic tools have been hand-crafted specifically for LLM tool use.
|
||||
We call this Agentic DX, and it's at the heart of why Agentic tools work
|
||||
better for LLM & MCP use cases than legacy APIs.
|
||||
</>
|
||||
),
|
||||
icon: StarIcon,
|
||||
pattern: {
|
||||
y: 16,
|
||||
squares: [
|
||||
[0, 1],
|
||||
[1, 3]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Battle-Tested',
|
||||
description: (
|
||||
<>
|
||||
Forget random GitHub repos and piping MCP servers together. Agentic
|
||||
tools are all battle-tested in production and come with real SLAs.
|
||||
</>
|
||||
),
|
||||
icon: ShieldCheckIcon,
|
||||
pattern: {
|
||||
y: 22,
|
||||
squares: [[0, 1]]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'World-Class TypeScript DX',
|
||||
description: (
|
||||
<>
|
||||
Agentic is written in TypeScript and strives for a Vercel-like DX.
|
||||
<span className='font-semibold'>One-line tool integrations</span> for
|
||||
all the popular TS LLM SDKs (
|
||||
<span className='font-semibold'>Vercel AI SDK</span>,{' '}
|
||||
<span className='font-semibold'>OpenAI</span>,{' '}
|
||||
<span className='font-semibold'>LangChain</span>, etc).
|
||||
</>
|
||||
),
|
||||
icon: FileJsonIcon,
|
||||
pattern: {
|
||||
y: 8,
|
||||
squares: [
|
||||
[0, 2],
|
||||
[-1, 1]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Stripe Billing',
|
||||
description: (
|
||||
<>
|
||||
Agentic uses Stripe for billing, and most tools are{' '}
|
||||
<span className='font-semibold'>usage-based</span>, so you'll only pay
|
||||
for what you (and your agents) actually use.
|
||||
</>
|
||||
),
|
||||
icon: CreditCardIcon,
|
||||
pattern: {
|
||||
y: -6,
|
||||
squares: [
|
||||
[-1, 2],
|
||||
[1, 3]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Support both MCP and HTTP',
|
||||
description: (
|
||||
<>
|
||||
All Agentic tools are exposed as both{' '}
|
||||
<span className='font-semibold'>MCP servers</span> as well as simple{' '}
|
||||
<span className='font-semibold'>HTTP APIs</span>. MCP is important for
|
||||
interop and future-proofing, whereas simple HTTP POST requests make
|
||||
tools easy to debug and simplifies integrating with LLM SDKs.
|
||||
</>
|
||||
),
|
||||
icon: CheckCheckIcon,
|
||||
pattern: {
|
||||
y: 32,
|
||||
squares: [
|
||||
[0, 2],
|
||||
[1, 4]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Semantic Versioning',
|
||||
description: (
|
||||
<>
|
||||
All Agentic tools are versioned using{' '}
|
||||
<span className='font-semibold'>semver</span>, so you can choose how to
|
||||
handle breaking changes.
|
||||
</>
|
||||
),
|
||||
icon: HistoryIcon,
|
||||
pattern: {
|
||||
y: 26,
|
||||
squares: [
|
||||
[2, 4],
|
||||
[-2, 3]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export function MCPMarketplaceFeatures() {
|
||||
return (
|
||||
<div className='xl:max-w-none'>
|
||||
<div className='not-prose grid grid-cols-1 gap-8 sm:grid-cols-2 xl:grid-cols-3'>
|
||||
{mcpMarketplaceFeatures.map((feature) => (
|
||||
<Feature key={feature.name} {...feature} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import { cn } from '@/lib/utils'
|
||||
|
||||
export function TypeScriptIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg viewBox='0 0 400 400' className={cn('w-4 h-4', className)}>
|
||||
<path fill='#007acc' d='M0 200V0h400v400H0' />
|
||||
<path
|
||||
fill='#fff'
|
||||
d='M87.7 200.7V217h52v148h36.9V217h52v-16c0-9 0-16.3-.4-16.5 0-.3-31.7-.4-70.2-.4l-70 .3v16.4l-.3-.1zM321.4 184c10.2 2.4 18 7 25 14.3 3.7 4 9.2 11 9.6 12.8 0 .6-17.3 12.3-27.8 18.8-.4.3-2-1.4-3.6-4-5.2-7.4-10.5-10.6-18.8-11.2-12-.8-20 5.5-20 16 0 3.2.6 5 1.8 7.6 2.7 5.5 7.7 8.8 23.2 15.6 28.6 12.3 41 20.4 48.5 32 8.5 13 10.4 33.4 4.7 48.7-6.4 16.7-22 28-44.3 31.7-7 1.2-23 1-30.5-.3-16-3-31.3-11-40.7-21.3-3.7-4-10.8-14.7-10.4-15.4l3.8-2.4 15-8.7 11.3-6.6 2.6 3.5c3.3 5.2 10.7 12.2 15 14.6 13 6.7 30.4 5.8 39-2 3.7-3.4 5.3-7 5.3-12 0-4.6-.7-6.7-3-10.2-3.2-4.4-9.6-8-27.6-16-20.7-8.8-29.5-14.4-37.7-23-4.7-5.2-9-13.3-11-20-1.5-5.8-2-20-.6-25.7 4.3-20 19.4-34 41-38 7-1.4 23.5-.8 30.4 1l-.2.2z'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
Ładowanie…
Reference in New Issue