initiall commit

This commit is contained in:
FloatingGhost 2022-11-07 17:12:00 +00:00
commit 3e6d96b932
43 changed files with 9145 additions and 0 deletions

3
.eslintrc.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

32
.gitignore vendored Normal file
View File

@ -0,0 +1,32 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# vercel
.vercel

35
README.md Normal file
View File

@ -0,0 +1,35 @@
# Pocket
Pocket is a [Tailwind UI](https://tailwindui.com) site template built using [Tailwind CSS](https://tailwindcss.com) and [Next.js](https://nextjs.org).
## Getting started
To get started with this template, first install the npm dependencies:
```bash
npm install
```
Next, run the development server:
```bash
npm run dev
```
Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
## Customizing
You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files.
## License
This site template is a commercial product and is licensed under the [Tailwind UI license](https://tailwindui.com/license).
## Learn more
To learn more about the technologies used in this site template, see the following resources:
- [Tailwind CSS](https://tailwindcss.com/docs) - the official Tailwind CSS documentation
- [Next.js](https://nextjs.org/docs) - the official Next.js documentation
- [Headless UI](https://headlessui.dev) - the official Headless UI documentation

8
jsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}

9
next.config.js Normal file
View File

@ -0,0 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
experimental: {
scrollRestoration: true,
},
}
module.exports = nextConfig

6592
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

33
package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "tailwindui-pocket",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"browserslist": "defaults, not ie <= 11",
"dependencies": {
"@headlessui/react": "^1.7.2",
"@heroicons/react": "^2.0.13",
"@tailwindcss/forms": "^0.5.3",
"autoprefixer": "^10.4.12",
"clsx": "^1.2.1",
"focus-visible": "^5.2.0",
"framer-motion": "^6.5.1",
"next": "13.0.2",
"postcss-focus-visible": "^6.0.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "^3.2.1",
"use-debounce": "^8.0.4"
},
"devDependencies": {
"eslint": "8.26.0",
"eslint-config-next": "13.0.2",
"prettier": "^2.7.1",
"prettier-plugin-tailwindcss": "^0.1.13"
}
}

9
postcss.config.js Normal file
View File

@ -0,0 +1,9 @@
module.exports = {
plugins: {
tailwindcss: {},
'postcss-focus-visible': {
replaceWith: '[data-focus-visible-added]',
},
autoprefixer: {},
},
}

5
prettier.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
singleQuote: true,
semi: false,
plugins: [require('prettier-plugin-tailwindcss')],
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,91 @@
import { forwardRef } from 'react'
import clsx from 'clsx'
function Logo(props) {
return (
<svg viewBox="0 0 79 24" fill="none" aria-hidden="true" {...props}>
<path
d="M12 24C5.373 24 0 18.627 0 12S5.373 0 12 0s12 5.373 12 12-5.373 12-12 12ZM2.4 12a9.004 9.004 0 0 0 6.055 8.507c1.565.542 2.945-.85 2.945-2.507V6c0-1.657-1.38-3.049-2.945-2.507A9.004 9.004 0 0 0 2.4 12Z"
fill="#06B6D4"
/>
<path
d="M33.004 17V6.818h3.818c.783 0 1.439.146 1.97.438.533.291.935.692 1.207 1.203.275.507.413 1.084.413 1.73 0 .653-.138 1.233-.413 1.74a2.948 2.948 0 0 1-1.218 1.198c-.537.288-1.198.433-1.983.433h-2.531v-1.517h2.282c.457 0 .832-.08 1.124-.238.291-.16.507-.378.646-.657.142-.278.214-.598.214-.96 0-.36-.072-.679-.214-.954a1.452 1.452 0 0 0-.651-.641c-.292-.156-.668-.234-1.129-.234h-1.69V17h-1.845Zm12.152.15c-.746 0-1.392-.165-1.939-.493a3.343 3.343 0 0 1-1.273-1.377c-.298-.59-.447-1.28-.447-2.068 0-.79.15-1.48.447-2.073a3.335 3.335 0 0 1 1.273-1.383c.547-.328 1.193-.492 1.94-.492.745 0 1.391.164 1.938.492.547.329.97.79 1.268 1.383.301.593.452 1.284.452 2.073 0 .789-.15 1.478-.452 2.068a3.309 3.309 0 0 1-1.268 1.377c-.547.328-1.193.492-1.939.492Zm.01-1.443c.404 0 .742-.11 1.014-.333.272-.225.474-.527.607-.905.136-.377.204-.798.204-1.262 0-.468-.068-.89-.204-1.268a2.007 2.007 0 0 0-.607-.91c-.272-.225-.61-.338-1.014-.338-.414 0-.759.113-1.034.338a2.041 2.041 0 0 0-.612.91 3.81 3.81 0 0 0-.198 1.268c0 .464.066.885.198 1.262.136.378.34.68.612.905.275.222.62.333 1.034.333Zm8.508 1.442c-.763 0-1.417-.167-1.964-.502a3.352 3.352 0 0 1-1.258-1.387c-.292-.593-.437-1.276-.437-2.048 0-.776.149-1.46.447-2.054a3.34 3.34 0 0 1 1.263-1.392c.547-.334 1.193-.502 1.939-.502.62 0 1.168.115 1.645.343.48.226.864.546 1.149.96.285.41.447.891.487 1.441h-1.72a1.644 1.644 0 0 0-.497-.92c-.259-.248-.605-.372-1.04-.372-.367 0-.69.1-.969.298-.278.196-.495.478-.651.845-.153.368-.229.81-.229 1.323 0 .52.076.968.229 1.342.152.371.366.658.641.86.279.2.605.298.98.298.265 0 .502-.05.71-.149.213-.102.39-.25.532-.442.143-.192.24-.426.294-.701h1.72a2.999 2.999 0 0 1-.477 1.437c-.275.414-.65.739-1.124.974-.474.232-1.03.348-1.67.348Zm6.39-2.545-.006-2.173h.289l2.744-3.067h2.103l-3.376 3.758h-.372l-1.383 1.482ZM58.422 17V6.818h1.8V17h-1.8Zm4.792 0-2.485-3.475 1.213-1.268L65.368 17h-2.153Zm6.245.15c-.766 0-1.427-.16-1.984-.478a3.233 3.233 0 0 1-1.278-1.362c-.298-.59-.447-1.285-.447-2.083 0-.786.149-1.475.447-2.069a3.384 3.384 0 0 1 1.263-1.392c.54-.334 1.175-.502 1.904-.502.47 0 .915.076 1.333.229.42.149.792.381 1.113.696.325.315.58.716.766 1.203.186.484.278 1.06.278 1.73v.552h-6.259v-1.213h4.534a1.935 1.935 0 0 0-.224-.92 1.625 1.625 0 0 0-.611-.641 1.719 1.719 0 0 0-.905-.234c-.368 0-.691.09-.97.269a1.848 1.848 0 0 0-.65.696c-.153.285-.231.598-.234.94v1.058c0 .444.08.825.243 1.144.163.315.39.556.681.726.292.165.634.248 1.025.248.261 0 .498-.036.71-.11.213-.075.397-.187.552-.332.156-.146.274-.327.353-.542l1.68.189a2.62 2.62 0 0 1-.606 1.163 2.958 2.958 0 0 1-1.133.766c-.461.179-.988.268-1.581.268Zm8.731-7.786v1.392h-4.39V9.364h4.39Zm-3.306-1.83h1.8v7.17c0 .241.036.427.109.556a.59.59 0 0 0 .298.258c.123.047.259.07.408.07.113 0 .215-.008.308-.025.096-.016.17-.031.219-.045l.303 1.407c-.096.034-.233.07-.412.11-.176.04-.392.063-.647.07a2.934 2.934 0 0 1-1.218-.204 1.895 1.895 0 0 1-.86-.706c-.209-.319-.311-.716-.308-1.194V7.534Z"
fill="#fff"
/>
</svg>
)
}
function MenuIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
<path
d="M5 6h14M5 18h14M5 12h14"
stroke="#fff"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
function UserIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
<path
d="M15 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM6.696 19h10.608c1.175 0 2.08-.935 1.532-1.897C18.028 15.69 16.187 14 12 14s-6.028 1.689-6.836 3.103C4.616 18.065 5.521 19 6.696 19Z"
stroke="#fff"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
export function AppScreen({ children, className, ...props }) {
return (
<div className={clsx('flex flex-col', className)} {...props}>
{children}
</div>
)
}
AppScreen.Header = forwardRef(function AppScreenHeader({ children }, ref) {
return (
<div ref={ref} className="mt-6 px-4 text-white">
{children}
</div>
)
})
AppScreen.Title = forwardRef(function AppScreenTitle({ children }, ref) {
return (
<div ref={ref} className="text-2xl text-white">
{children}
</div>
)
})
AppScreen.Subtitle = forwardRef(function AppScreenSubtitle({ children }, ref) {
return (
<div ref={ref} className="text-sm text-gray-500">
{children}
</div>
)
})
AppScreen.Body = forwardRef(function AppScreenBody(
{ children, className },
ref
) {
return (
<div
ref={ref}
className={clsx('mt-6 flex-auto rounded-t-2xl bg-white', className)}
>
{children}
</div>
)
})

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,48 @@
import Link from 'next/link'
import { Logo } from '@/components/Logo'
function BackgroundIllustration(props) {
return (
<svg
viewBox="0 0 1090 1090"
aria-hidden="true"
fill="none"
preserveAspectRatio="none"
{...props}
>
<circle cx={545} cy={545} r="544.5" />
<circle cx={545} cy={545} r="480.5" />
<circle cx={545} cy={545} r="416.5" />
<circle cx={545} cy={545} r="352.5" />
</svg>
)
}
export function AuthLayout({ title, subtitle, children }) {
return (
<main className="flex min-h-full overflow-hidden pt-16 sm:py-28">
<div className="mx-auto flex w-full max-w-2xl flex-col px-4 sm:px-6">
<Link href="/" aria-label="Home">
<Logo className="mx-auto h-10 w-auto" />
</Link>
<div className="relative mt-12 sm:mt-16">
<BackgroundIllustration
width="1090"
height="1090"
className="absolute -top-7 left-1/2 -z-10 h-[788px] -translate-x-1/2 stroke-gray-300/30 [mask-image:linear-gradient(to_bottom,white_20%,transparent_75%)] sm:-top-9 sm:h-auto"
/>
<h1 className="text-center text-2xl font-medium tracking-tight text-gray-900">
{title}
</h1>
{subtitle && (
<p className="mt-3 text-center text-lg text-gray-600">{subtitle}</p>
)}
</div>
<div className="-mx-4 mt-10 flex-auto bg-white py-10 px-4 shadow-2xl shadow-gray-900/10 sm:mx-0 sm:flex-none sm:rounded-5xl sm:p-24">
{children}
</div>
</div>
</main>
)
}

39
src/components/Button.jsx Normal file
View File

@ -0,0 +1,39 @@
import { forwardRef } from 'react'
import Link from 'next/link'
import clsx from 'clsx'
const baseStyles = {
solid:
'inline-flex justify-center rounded-lg py-2 px-3 text-sm font-semibold outline-2 outline-offset-2 transition-colors',
outline:
'inline-flex justify-center rounded-lg border py-[calc(theme(spacing.2)-1px)] px-[calc(theme(spacing.3)-1px)] text-sm outline-2 outline-offset-2 transition-colors',
}
const variantStyles = {
solid: {
cyan: 'relative overflow-hidden bg-cyan-500 text-white before:absolute before:inset-0 active:before:bg-transparent hover:before:bg-white/10 active:bg-cyan-600 active:text-white/80 before:transition-colors',
white:
'bg-white text-cyan-900 hover:bg-white/90 active:bg-white/90 active:text-cyan-900/70',
gray: 'bg-gray-800 text-white hover:bg-gray-900 active:bg-gray-800 active:text-white/80',
},
outline: {
gray: 'border-gray-300 text-gray-700 hover:border-gray-400 active:bg-gray-100 active:text-gray-700/80',
},
}
export const Button = forwardRef(function Button(
{ variant = 'solid', color = 'gray', className, href, ...props },
ref
) {
className = clsx(
baseStyles[variant],
variantStyles[variant][color],
className
)
return href ? (
<Link ref={ref} href={href} className={className} {...props} />
) : (
<button ref={ref} className={className} {...props} />
)
})

View File

@ -0,0 +1,35 @@
import { AppStoreLink } from '@/components/AppStoreLink'
import { CircleBackground } from '@/components/CircleBackground'
import { Container } from '@/components/Container'
import Link from 'next/link'
export function CallToAction() {
return (
<section
id="join"
className="relative overflow-hidden bg-gray-900 py-20 sm:py-28"
>
<div className="absolute top-1/2 left-20 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2">
<CircleBackground color="#fff" className="animate-spin-slower" />
</div>
<Container className="relative">
<div className="mx-auto max-w-md sm:text-center">
<h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl">
Join an Akkoma instance today!
</h2>
<p className="mt-4 text-lg text-gray-300">
It's really easy to sign up and start posting!
Try one of the following instances if you don't have one of your own.
</p>
<div className="mt-8 flex justify-center">
<ul className={"text-white list-disc"}>
<li>
<Link href={"https://outerheaven.club"}>Outer Heaven</Link>
</li>
</ul>
</div>
</div>
</Container>
</section>
)
}

View File

@ -0,0 +1,45 @@
import { useId } from 'react'
export function CircleBackground({
color,
width = 558,
height = 558,
...props
}) {
let id = useId()
return (
<svg
viewBox="0 0 558 558"
width={width}
height={height}
fill="none"
aria-hidden="true"
{...props}
>
<defs>
<linearGradient
id={id}
x1="79"
y1="16"
x2="105"
y2="237"
gradientUnits="userSpaceOnUse"
>
<stop stopColor={color} />
<stop offset="1" stopColor={color} stopOpacity="0" />
</linearGradient>
</defs>
<path
opacity=".2"
d="M1 279C1 125.465 125.465 1 279 1s278 124.465 278 278-124.465 278-278 278S1 432.535 1 279Z"
stroke={color}
/>
<path
d="M1 279C1 125.465 125.465 1 279 1"
stroke={`url(#${id})`}
strokeLinecap="round"
/>
</svg>
)
}

View File

@ -0,0 +1,10 @@
import clsx from 'clsx'
export function Container({ className, ...props }) {
return (
<div
className={clsx('mx-auto max-w-7xl px-4 sm:px-6 lg:px-8', className)}
{...props}
/>
)
}

62
src/components/Faqs.jsx Normal file
View File

@ -0,0 +1,62 @@
import Link from 'next/link'
import { Container } from '@/components/Container'
const faqs = [
[
{
question: 'What is an \'instance\'?',
answer:
'An instance is one server running some fediverse software. It forms a network with all other instances, to create a social network'
},
{
question: 'Why did you fork from Pleroma?',
answer:
'Long story. Boils down to not having faith that pleroma dev will ever recover. A longer-form explanation is available at https://coffee-and-dreams.uk/development/2022/06/24/akkoma.html',
},
]
]
export function Faqs() {
return (
<section
id="faqs"
aria-labelledby="faqs-title"
className="border-t border-gray-200 py-20 sm:py-32"
>
<Container>
<div className="mx-auto max-w-2xl lg:mx-0">
<h2
id="faqs-title"
className="text-3xl font-medium tracking-tight text-gray-900"
>
Frequently asked questions
</h2>
<p className="mt-2 text-lg text-gray-600">
If you have anything else you want to ask, hop on the IRC at <span className={"font-mono"}>ircs://irc.akkoma.dev:6697</span>,
or raise an issue on <Link className="text-blue-600" href={"https://akkoma.dev/AkkomaGang/akkoma"}>the gitea</Link>!
</p>
</div>
<ul
role="list"
className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-8 sm:mt-20 lg:max-w-none lg:grid-cols-3"
>
{faqs.map((column, columnIndex) => (
<li key={columnIndex}>
<ul role="list" className="space-y-10">
{column.map((faq, faqIndex) => (
<li key={faqIndex}>
<h3 className="text-lg font-semibold leading-6 text-gray-900">
{faq.question}
</h3>
<p className="mt-4 text-sm text-gray-700">{faq.answer}</p>
</li>
))}
</ul>
</li>
))}
</ul>
</Container>
</section>
)
}

33
src/components/Fields.jsx Normal file
View File

@ -0,0 +1,33 @@
import clsx from 'clsx'
const formClasses =
'block w-full appearance-none rounded-lg border border-gray-200 bg-white py-[calc(theme(spacing.2)-1px)] px-[calc(theme(spacing.3)-1px)] text-gray-900 placeholder:text-gray-400 focus:border-cyan-500 focus:outline-none focus:ring-cyan-500 sm:text-sm'
function Label({ id, children }) {
return (
<label
htmlFor={id}
className="mb-2 block text-sm font-semibold text-gray-900"
>
{children}
</label>
)
}
export function TextField({ id, label, type = 'text', className, ...props }) {
return (
<div className={className}>
{label && <Label id={id}>{label}</Label>}
<input id={id} type={type} {...props} className={formClasses} />
</div>
)
}
export function SelectField({ id, label, className, ...props }) {
return (
<div className={className}>
{label && <Label id={id}>{label}</Label>}
<select id={id} {...props} className={clsx(formClasses, 'pr-8')} />
</div>
)
}

39
src/components/Footer.jsx Normal file
View File

@ -0,0 +1,39 @@
import Image from 'next/image'
import Link from 'next/link'
import { Button } from '@/components/Button'
import { Container } from '@/components/Container'
import { TextField } from '@/components/Fields'
import { Logomark } from '@/components/Logo'
import { NavLinks } from '@/components/NavLinks'
import qrCode from '@/images/qr-code.svg'
export function Footer() {
return (
<footer className="border-t border-gray-200">
<Container>
<div className="flex flex-col items-start justify-between gap-y-12 pt-16 pb-6 lg:flex-row lg:items-center lg:py-16">
<div>
<div className="flex items-center text-gray-900">`
<div className="ml-4">
<p className="text-base font-semibold">Akkoma</p>
<p className="mt-1 text-sm">Magically expressive social media</p>
</div>
</div>
<nav className="mt-11 flex gap-8">
<NavLinks />
</nav>
</div>
</div>
<div className="flex flex-col items-center border-t border-gray-200 pt-8 pb-12 md:flex-row-reverse md:justify-between md:pt-6">
<Link href={"https://docs.akkoma.dev/stable/"}>Documentation</Link>
<Link href={"https://akkoma.dev/AkkomaGang/akkoma"}>Source code</Link>
<p className="mt-6 text-sm text-gray-500 md:mt-0">
&copy; Copyright {new Date().getFullYear()}. All rights reserved.
</p>
</div>
</Container>
</footer>
)
}

124
src/components/Header.jsx Normal file
View File

@ -0,0 +1,124 @@
import Link from 'next/link'
import { Popover } from '@headlessui/react'
import { AnimatePresence, motion } from 'framer-motion'
import { Button } from '@/components/Button'
import { Container } from '@/components/Container'
import { Logo } from '@/components/Logo'
import { NavLinks } from '@/components/NavLinks'
function MenuIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
<path
d="M5 6h14M5 18h14M5 12h14"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
function ChevronUpIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
<path
d="M17 14l-5-5-5 5"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
function MobileNavLink({ children, ...props }) {
return (
<Popover.Button
as={Link}
className="block text-base leading-7 tracking-tight text-gray-700"
{...props}
>
{children}
</Popover.Button>
)
}
export function Header() {
return (
<header className={"bg-purple-1000 text-white"}>
<nav>
<Container className="relative z-50 flex justify-between py-8">
<div className="relative z-10 flex items-center gap-16">
<Link href="/" aria-label="Home" className={"text-lg font-bold"}>
Akkoma
</Link>
<div className="hidden lg:flex lg:gap-10">
<NavLinks />
</div>
</div>
<div className="flex items-center gap-6">
<Popover className="lg:hidden">
{({ open }) => (
<>
<Popover.Button
className="relative z-10 -m-2 inline-flex items-center rounded-lg stroke-gray-900 p-2 hover:bg-gray-200/50 hover:stroke-gray-600 active:stroke-gray-900 [&:not(:focus-visible)]:focus:outline-none"
aria-label="Toggle site navigation"
>
{({ open }) =>
open ? (
<ChevronUpIcon className="h-6 w-6" />
) : (
<MenuIcon className="h-6 w-6" />
)
}
</Popover.Button>
<AnimatePresence initial={false}>
{open && (
<>
<Popover.Overlay
static
as={motion.div}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-0 bg-gray-300/60 backdrop-blur"
/>
<Popover.Panel
static
as={motion.div}
initial={{ opacity: 0, y: -32 }}
animate={{ opacity: 1, y: 0 }}
exit={{
opacity: 0,
y: -32,
transition: { duration: 0.2 },
}}
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-gray-50 px-6 pb-6 pt-32 shadow-2xl shadow-gray-900/20"
>
<div className="space-y-4">
<MobileNavLink href="#features">
Features
</MobileNavLink>
<MobileNavLink href="#faqs">FAQ</MobileNavLink>
</div>
<div className="mt-8 flex flex-col gap-4 text-white">
<Button href="#join">Join today</Button >
</div>
</Popover.Panel>
</>
)}
</AnimatePresence>
</>
)}
</Popover>
<Button href="#join" variant="outline" className="hidden lg:block bg-white hover:bg-purple-900 hover:text-white">
Join today
</Button>
</div>
</Container>
</nav>
</header>
)
}

325
src/components/Hero.jsx Normal file
View File

@ -0,0 +1,325 @@
import { useId, useRef, useState } from 'react'
import Image from 'next/image'
import clsx from 'clsx'
import { motion, useInView, useMotionValue } from 'framer-motion'
import { AppScreen } from '@/components/AppScreen'
import { AppStoreLink } from '@/components/AppStoreLink'
import { Button } from '@/components/Button'
import { Container } from '@/components/Container'
import { PhoneFrame } from '@/components/PhoneFrame'
import berniePic from '@/images/profiles/bernie.png'
import profile1 from '@/images/profiles/profile-1.png'
import profile2 from '@/images/profiles/profile-2.png'
import {ArrowPathRoundedSquareIcon, ArrowUturnLeftIcon, Bars3Icon} from '@heroicons/react/20/solid'
import Link from 'next/link'
function BackgroundIllustration(props) {
let id = useId()
return (
<div {...props}>
<svg
viewBox="0 0 1026 1026"
fill="none"
aria-hidden="true"
className="absolute inset-0 h-full w-full animate-spin-slow"
>
<path
d="M1025 513c0 282.77-229.23 512-512 512S1 795.77 1 513 230.23 1 513 1s512 229.23 512 512Z"
stroke="#D4D4D4"
strokeOpacity="0.7"
/>
<path
d="M513 1025C230.23 1025 1 795.77 1 513"
stroke={`url(#${id}-gradient-1)`}
strokeLinecap="round"
/>
<defs>
<linearGradient
id={`${id}-gradient-1`}
x1="1"
y1="513"
x2="1"
y2="1025"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#06b6d4" />
<stop offset="1" stopColor="#06b6d4" stopOpacity="0" />
</linearGradient>
</defs>
</svg>
<svg
viewBox="0 0 1026 1026"
fill="none"
aria-hidden="true"
className="absolute inset-0 h-full w-full animate-spin-reverse-slower"
>
<path
d="M913 513c0 220.914-179.086 400-400 400S113 733.914 113 513s179.086-400 400-400 400 179.086 400 400Z"
stroke="#D4D4D4"
strokeOpacity="0.7"
/>
<path
d="M913 513c0 220.914-179.086 400-400 400"
stroke={`url(#${id}-gradient-2)`}
strokeLinecap="round"
/>
<defs>
<linearGradient
id={`${id}-gradient-2`}
x1="913"
y1="513"
x2="913"
y2="913"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#06b6d4" />
<stop offset="1" stopColor="#06b6d4" stopOpacity="0" />
</linearGradient>
</defs>
</svg>
</div>
)
}
function PlayIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
<circle cx="12" cy="12" r="11.5" stroke="#D4D4D4" />
<path
d="M9.5 14.382V9.618a.5.5 0 0 1 .724-.447l4.764 2.382a.5.5 0 0 1 0 .894l-4.764 2.382a.5.5 0 0 1-.724-.447Z"
fill="#A3A3A3"
stroke="#A3A3A3"
/>
</svg>
)
}
const prices = [
997.56, 944.34, 972.25, 832.4, 888.76, 834.8, 805.56, 767.38, 861.21, 669.6,
694.39, 721.32, 694.03, 610.1, 502.2, 549.56, 611.03, 583.4, 610.14, 660.6,
752.11, 721.19, 638.89, 661.7, 694.51, 580.3, 638.0, 613.3, 651.64, 560.51,
611.45, 670.68, 752.56,
]
const maxPrice = Math.max(...prices)
const minPrice = Math.min(...prices)
function Chart({
className,
activePointIndex,
onChangeActivePointIndex,
width: totalWidth,
height: totalHeight,
paddingX = 0,
paddingY = 0,
gridLines = 6,
...props
}) {
let width = totalWidth - paddingX * 2
let height = totalHeight - paddingY * 2
let id = useId()
let svgRef = useRef()
let pathRef = useRef()
let isInView = useInView(svgRef, { amount: 0.5, once: true })
let pathWidth = useMotionValue(0)
let [interactionEnabled, setInteractionEnabled] = useState(false)
let path = ''
let points = []
for (let index = 0; index < prices.length; index++) {
let x = paddingX + (index / (prices.length - 1)) * width
let y =
paddingY +
(1 - (prices[index] - minPrice) / (maxPrice - minPrice)) * height
points.push({ x, y })
path += `${index === 0 ? 'M' : 'L'} ${x.toFixed(4)} ${y.toFixed(4)}`
}
return (
<svg
ref={svgRef}
viewBox={`0 0 ${totalWidth} ${totalHeight}`}
className={clsx(className, 'overflow-visible')}
{...(interactionEnabled
? {
onPointerLeave: () => onChangeActivePointIndex(null),
onPointerMove: (event) => {
let x = event.nativeEvent.offsetX
let closestPointIndex
let closestDistance = Infinity
for (
let pointIndex = 0;
pointIndex < points.length;
pointIndex++
) {
let point = points[pointIndex]
let distance = Math.abs(point.x - x)
if (distance < closestDistance) {
closestDistance = distance
closestPointIndex = pointIndex
} else {
break
}
}
onChangeActivePointIndex(closestPointIndex)
},
}
: {})}
{...props}
>
<defs>
<clipPath id={`${id}-clip`}>
<path d={`${path} V ${height + paddingY} H ${paddingX} Z`} />
</clipPath>
<linearGradient id={`${id}-gradient`} x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stopColor="#13B5C8" />
<stop offset="100%" stopColor="#13B5C8" stopOpacity="0" />
</linearGradient>
</defs>
{[...Array(gridLines - 1).keys()].map((index) => (
<line
key={index}
stroke="#a3a3a3"
opacity="0.1"
x1="0"
y1={(totalHeight / gridLines) * (index + 1)}
x2={totalWidth}
y2={(totalHeight / gridLines) * (index + 1)}
/>
))}
<motion.rect
y={paddingY}
width={pathWidth}
height={height}
fill={`url(#${id}-gradient)`}
clipPath={`url(#${id}-clip)`}
opacity="0.5"
/>
<motion.path
ref={pathRef}
d={path}
fill="none"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
initial={{ pathLength: 0 }}
transition={{ duration: 1 }}
{...(isInView ? { stroke: '#06b6d4', animate: { pathLength: 1 } } : {})}
onUpdate={({ pathLength }) => {
pathWidth.set(
pathRef.current.getPointAtLength(
pathLength * pathRef.current.getTotalLength()
).x
)
}}
onAnimationComplete={() => setInteractionEnabled(true)}
/>
{activePointIndex !== null && (
<>
<line
x1="0"
y1={points[activePointIndex].y}
x2={totalWidth}
y2={points[activePointIndex].y}
stroke="#06b6d4"
strokeDasharray="1 3"
/>
<circle
r="4"
cx={points[activePointIndex].x}
cy={points[activePointIndex].y}
fill="#fff"
strokeWidth="2"
stroke="#06b6d4"
/>
</>
)}
</svg>
)
}
function Post({ username, text, profileImage }) {
return (
<div className="flex flex-col w-full h-full text-white">
<div className={"flex"}>
<Image src={profileImage} className="w-8 rounded-lg mr-2" />
<div className="font-bold mt-1">
{ username }
</div>
</div>
<div className="ml-10">
<p>{ text }</p>
</div>
<div className={"ml-10 flex space-x-5"}>
<ArrowUturnLeftIcon className={"w-4 text-gray-500"} />
<ArrowPathRoundedSquareIcon className={"w-4 text-gray-500"} />
</div>
</div>
)
}
function AppDemo() {
return (
<AppScreen>
<AppScreen.Body>
<div className="p-4 bg-blue-1000">
<div className="flex gap-2">
<div className="text-xs leading-6 text-white py-2 pb-4">
<Bars3Icon className="w-4" />
</div>
<div className={"text-white pt-1"}>
Akkoma
</div>
</div>
<Post text={"I must become the strongest bocchi"} username={"Jimbob"} profileImage={berniePic} />
<Post text={"Anyone know how I write examples?"} username={"Jones"} profileImage={profile1} />
<Post text={"Wowee isn't writing fun"} username={"Meta"} profileImage={profile2} />
<Post text={"What you're referring to as mastodon is actually the fediverse and..."} username={"That One Guy"} />
</div>
</AppScreen.Body>
</AppScreen>
)
}
export function Hero() {
return (
<div className="overflow-hidden py-20 sm:py-32 lg:pb-32 xl:pb-36">
<Container>
<div className="lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20">
<div className="relative z-10 mx-auto max-w-2xl lg:col-span-7 lg:max-w-none lg:pt-6 xl:col-span-6">
<h1 className="text-4xl font-medium tracking-tight text-gray-900">
Be very cool on the internet
</h1>
<p className="mt-6 text-lg text-gray-600">
Communicate with all your friends on the fediverse, no matter if they're
on mastodon, pleroma, or any other fediverse software.<br/>
Send them fancy markdown animations! React to their posts with custom emoji!
</p>
<ul className={"list mt-6 text-lg text-blue-800"}>
<li>
<Link href={"https://akkoma.dev"}>Source Code</Link>
</li>
<li>
<Link href={"https://docs.akkoma.dev/stable"}>Documentation</Link>
</li>
</ul>
</div>
<div className="relative mt-10 sm:mt-20 lg:col-span-5 lg:row-span-2 lg:mt-0 xl:col-span-6">
<BackgroundIllustration className="absolute left-1/2 top-4 h-[1026px] w-[1026px] -translate-x-1/3 stroke-gray-300/70 [mask-image:linear-gradient(to_bottom,white_20%,transparent_75%)] sm:top-16 sm:-translate-x-1/2 lg:-top-16 lg:ml-12 xl:-top-14 xl:ml-0" />
<div className="-mx-4 h-[448px] px-9 [mask-image:linear-gradient(to_bottom,white_60%,transparent)] sm:mx-0 lg:absolute lg:-inset-x-10 lg:-top-10 lg:-bottom-20 lg:h-auto lg:px-0 lg:pt-10 xl:-bottom-32">
<PhoneFrame className="mx-auto max-w-[366px]" priority>
<AppDemo />
</PhoneFrame>
</div>
</div>
</div>
</Container>
</div>
)
}

23
src/components/Logo.jsx Normal file
View File

@ -0,0 +1,23 @@
export function Logomark(props) {
return (
<svg viewBox="0 0 40 40" aria-hidden="true" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M20 40C8.954 40 0 31.046 0 20S8.954 0 20 0s20 8.954 20 20-8.954 20-20 20ZM4 20c0 7.264 5.163 13.321 12.02 14.704C17.642 35.03 19 33.657 19 32V8c0-1.657-1.357-3.031-2.98-2.704C9.162 6.68 4 12.736 4 20Z"
/>
</svg>
)
}
export function Logo(props) {
return (
<svg viewBox="0 0 106 40" aria-hidden="true" {...props}>
<Logomark width="40" height="40" className="fill-cyan-500" />
<path
className="fill-gray-900"
d="M53.1477 26V14.3636H57.5114C58.4053 14.3636 59.1553 14.5303 59.7614 14.8636C60.3712 15.197 60.8314 15.6553 61.142 16.2386C61.4564 16.8182 61.6136 17.4773 61.6136 18.2159C61.6136 18.9621 61.4564 19.625 61.142 20.2045C60.8277 20.7841 60.3636 21.2405 59.75 21.5739C59.1364 21.9034 58.3807 22.0682 57.483 22.0682H54.5909V20.3352H57.1989C57.7216 20.3352 58.1496 20.2443 58.483 20.0625C58.8163 19.8807 59.0625 19.6307 59.2216 19.3125C59.3845 18.9943 59.4659 18.6288 59.4659 18.2159C59.4659 17.803 59.3845 17.4394 59.2216 17.125C59.0625 16.8106 58.8144 16.5663 58.4773 16.392C58.1439 16.214 57.714 16.125 57.1875 16.125H55.2557V26H53.1477ZM67.0355 26.1705C66.1832 26.1705 65.4446 25.983 64.8196 25.608C64.1946 25.233 63.7098 24.7083 63.3651 24.0341C63.0241 23.3598 62.8537 22.572 62.8537 21.6705C62.8537 20.7689 63.0241 19.9792 63.3651 19.3011C63.7098 18.6231 64.1946 18.0966 64.8196 17.7216C65.4446 17.3466 66.1832 17.1591 67.0355 17.1591C67.8878 17.1591 68.6264 17.3466 69.2514 17.7216C69.8764 18.0966 70.3594 18.6231 70.7003 19.3011C71.045 19.9792 71.2173 20.7689 71.2173 21.6705C71.2173 22.572 71.045 23.3598 70.7003 24.0341C70.3594 24.7083 69.8764 25.233 69.2514 25.608C68.6264 25.983 67.8878 26.1705 67.0355 26.1705ZM67.0469 24.5227C67.509 24.5227 67.8954 24.3958 68.206 24.142C68.5166 23.8845 68.7476 23.5398 68.8991 23.108C69.0545 22.6761 69.1321 22.1951 69.1321 21.6648C69.1321 21.1307 69.0545 20.6477 68.8991 20.2159C68.7476 19.7803 68.5166 19.4337 68.206 19.1761C67.8954 18.9186 67.509 18.7898 67.0469 18.7898C66.5734 18.7898 66.1795 18.9186 65.8651 19.1761C65.5545 19.4337 65.3215 19.7803 65.1662 20.2159C65.0147 20.6477 64.9389 21.1307 64.9389 21.6648C64.9389 22.1951 65.0147 22.6761 65.1662 23.108C65.3215 23.5398 65.5545 23.8845 65.8651 24.142C66.1795 24.3958 66.5734 24.5227 67.0469 24.5227ZM76.7699 26.1705C75.8987 26.1705 75.1506 25.9792 74.5256 25.5966C73.9044 25.214 73.4252 24.6856 73.0881 24.0114C72.7547 23.3333 72.5881 22.553 72.5881 21.6705C72.5881 20.7841 72.7585 20.0019 73.0994 19.3239C73.4403 18.642 73.9214 18.1117 74.5426 17.733C75.1676 17.3504 75.9063 17.1591 76.7585 17.1591C77.4669 17.1591 78.0938 17.2898 78.6392 17.5511C79.1884 17.8087 79.6259 18.1742 79.9517 18.6477C80.2775 19.1174 80.4631 19.6667 80.5085 20.2955H78.5426C78.4631 19.875 78.2737 19.5246 77.9744 19.2443C77.679 18.9602 77.2831 18.8182 76.7869 18.8182C76.3665 18.8182 75.9972 18.9318 75.679 19.1591C75.3608 19.3826 75.1127 19.7045 74.9347 20.125C74.7604 20.5455 74.6733 21.0492 74.6733 21.6364C74.6733 22.2311 74.7604 22.7424 74.9347 23.1705C75.1089 23.5947 75.3532 23.9223 75.6676 24.1534C75.9858 24.3807 76.3589 24.4943 76.7869 24.4943C77.09 24.4943 77.3608 24.4375 77.5994 24.3239C77.8419 24.2064 78.0445 24.0379 78.2074 23.8182C78.3703 23.5985 78.482 23.3314 78.5426 23.017H80.5085C80.4593 23.6345 80.2775 24.1818 79.9631 24.6591C79.6487 25.1326 79.2206 25.5038 78.679 25.7727C78.1373 26.0379 77.5009 26.1705 76.7699 26.1705ZM84.0724 23.2614L84.0668 20.7784H84.3963L87.5327 17.2727H89.9361L86.0781 21.5682H85.652L84.0724 23.2614ZM82.1974 26V14.3636H84.2543V26H82.1974ZM87.6747 26L84.8338 22.0284L86.2202 20.5795L90.1349 26H87.6747ZM94.8111 26.1705C93.9361 26.1705 93.1804 25.9886 92.544 25.625C91.9115 25.2576 91.4247 24.7386 91.0838 24.0682C90.7429 23.3939 90.5724 22.6004 90.5724 21.6875C90.5724 20.7898 90.7429 20.0019 91.0838 19.3239C91.4285 18.642 91.9096 18.1117 92.527 17.733C93.1444 17.3504 93.8698 17.1591 94.7031 17.1591C95.241 17.1591 95.7486 17.2462 96.2259 17.4205C96.7069 17.5909 97.1312 17.8561 97.4986 18.2159C97.8698 18.5758 98.1615 19.0341 98.3736 19.5909C98.5857 20.1439 98.6918 20.803 98.6918 21.5682V22.1989H91.5384V20.8125H96.7202C96.7164 20.4186 96.6312 20.0682 96.4645 19.7614C96.2978 19.4508 96.0649 19.2064 95.7656 19.0284C95.4702 18.8504 95.1255 18.7614 94.7315 18.7614C94.3111 18.7614 93.9418 18.8636 93.6236 19.0682C93.3054 19.2689 93.0573 19.5341 92.8793 19.8636C92.705 20.1894 92.616 20.5473 92.6122 20.9375V22.1477C92.6122 22.6553 92.705 23.0909 92.8906 23.4545C93.0762 23.8144 93.3357 24.0909 93.669 24.2841C94.0024 24.4735 94.3925 24.5682 94.8395 24.5682C95.1387 24.5682 95.4096 24.5265 95.652 24.4432C95.8944 24.3561 96.1046 24.2292 96.2827 24.0625C96.4607 23.8958 96.5952 23.6894 96.6861 23.4432L98.6065 23.6591C98.4853 24.1667 98.2543 24.6098 97.9134 24.9886C97.5762 25.3636 97.1444 25.6553 96.6179 25.8636C96.0914 26.0682 95.4891 26.1705 94.8111 26.1705ZM104.79 17.2727V18.8636H99.7727V17.2727H104.79ZM101.011 15.1818H103.068V23.375C103.068 23.6515 103.11 23.8636 103.193 24.0114C103.28 24.1553 103.394 24.2538 103.534 24.3068C103.674 24.3598 103.83 24.3864 104 24.3864C104.129 24.3864 104.246 24.3769 104.352 24.358C104.462 24.339 104.545 24.322 104.602 24.3068L104.949 25.9148C104.839 25.9527 104.682 25.9943 104.477 26.0398C104.277 26.0852 104.03 26.1117 103.739 26.1193C103.223 26.1345 102.759 26.0568 102.347 25.8864C101.934 25.7121 101.606 25.4432 101.364 25.0795C101.125 24.7159 101.008 24.2614 101.011 23.7159V15.1818Z"
/>
</svg>
)
}

View File

@ -0,0 +1,22 @@
import { useState } from 'react'
import Link from 'next/link'
import { AnimatePresence, motion } from 'framer-motion'
export function NavLinks() {
let [hoveredIndex, setHoveredIndex] = useState(null)
return [
['Features', '#features'],
['FAQ', '#faqs'],
].map(([label, href], index) => (
<Link
key={label}
href={href}
className="relative -my-2 -mx-3 rounded-lg px-3 py-2 text-sm text-white transition-colors delay-150 hover:text-gray-900 hover:bg-white hover:delay-[0ms]"
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
>
<span className="relative z-10">{label}</span>
</Link>
))
}

View File

@ -0,0 +1,42 @@
import Image from 'next/image'
import clsx from 'clsx'
import frame from '@/images/phone-frame.svg'
function PlaceholderFrame(props) {
return (
<svg viewBox="0 0 366 729" aria-hidden="true" {...props}>
<path
fill="#F2F2F2"
fillRule="evenodd"
clipRule="evenodd"
d="M300.092 1c41.22 0 63.223 21.99 63.223 63.213V184.94c-.173.184-.329.476-.458.851.188-.282.404-.547.647-.791.844-.073 2.496.257 2.496 2.157V268.719c-.406 2.023-2.605 2.023-2.605 2.023a7.119 7.119 0 0 1-.08-.102v394.462c0 41.213-22.001 63.212-63.223 63.212h-95.074c-.881-.468-2.474-.795-4.323-.838l-33.704-.005-.049.001h-.231l-.141-.001c-2.028 0-3.798.339-4.745.843H66.751c-41.223 0-63.223-21.995-63.223-63.208V287.739c-.402-.024-2.165-.23-2.524-2.02v-.973A2.039 2.039 0 0 1 1 284.62v-47.611c0-.042.001-.084.004-.126v-.726c0-1.9 1.652-2.23 2.496-2.157l.028.028v-16.289c-.402-.024-2.165-.23-2.524-2.02v-.973A2.039 2.039 0 0 1 1 214.62v-47.611c0-.042.001-.084.004-.126v-.726c0-1.9 1.652-2.23 2.496-2.157l.028.028v-26.041a2.26 2.26 0 0 0 .093-.236l-.064-.01a3.337 3.337 0 0 1-.72-.12l-.166-.028A2 2 0 0 1 1 135.62v-24.611a2 2 0 0 1 1.671-1.973l.857-.143v-44.68C3.528 22.99 25.53 1 66.75 1h233.341ZM3.952 234.516a5.481 5.481 0 0 0-.229-.278c.082.071.159.163.228.278Zm89.99-206.304A4.213 4.213 0 0 0 89.727 24H56.864C38.714 24 24 38.708 24 56.852v618.296C24 693.292 38.714 708 56.864 708h250.272c18.15 0 32.864-14.708 32.864-32.852V56.852C340 38.708 325.286 24 307.136 24h-32.864a4.212 4.212 0 0 0-4.213 4.212v2.527c0 10.235-8.3 18.532-18.539 18.532H112.48c-10.239 0-18.539-8.297-18.539-18.532v-2.527Z"
/>
<rect x="154" y="29" width="56" height="5" rx="2.5" fill="#D4D4D4" />
</svg>
)
}
export function PhoneFrame({
className,
children,
priority = false,
...props
}) {
return (
<div className={clsx('relative aspect-[366/729]', className)} {...props}>
<div className="absolute inset-y-[calc(1/729*100%)] right-[calc(5/729*100%)] left-[calc(7/729*100%)] rounded-[calc(58/366*100%)/calc(58/729*100%)] shadow-2xl" />
<div className="absolute top-[calc(23/729*100%)] left-[calc(23/366*100%)] grid h-[calc(686/729*100%)] w-[calc(318/366*100%)] transform grid-cols-1 overflow-hidden bg-gray-900 pt-[calc(23/318*100%)]">
{children}
</div>
<PlaceholderFrame className="pointer-events-none absolute inset-0 h-full w-full fill-gray-100" />
<Image
src={frame}
alt=""
className="pointer-events-none absolute inset-0 h-full w-full"
unoptimized
priority={priority}
/>
</div>
)
}

269
src/components/Pricing.jsx Normal file
View File

@ -0,0 +1,269 @@
import { useState } from 'react'
import { RadioGroup } from '@headlessui/react'
import clsx from 'clsx'
import { Button } from '@/components/Button'
import { Container } from '@/components/Container'
import { Logomark } from '@/components/Logo'
const plans = [
{
name: 'Starter',
featured: false,
price: { Monthly: '$0', Annually: '$0' },
description:
'Youre new to investing but want to do it right. Get started for free.',
button: {
label: 'Get started for free',
href: '/register',
},
features: [
'Commission-free trading',
'Multi-layered encryption',
'One tip every day',
'Invest up to $1,500 each month',
],
logomarkClassName: 'fill-gray-300',
},
{
name: 'Investor',
featured: false,
price: { Monthly: '$7', Annually: '$70' },
description:
'Youve been investing for a while. Invest more and grow your wealth faster.',
button: {
label: 'Subscribe',
href: '/register',
},
features: [
'Commission-free trading',
'Multi-layered encryption',
'One tip every hour',
'Invest up to $15,000 each month',
'Basic transaction anonymization',
],
logomarkClassName: 'fill-gray-500',
},
{
name: 'VIP',
featured: true,
price: { Monthly: '$199', Annually: '$1,990' },
description:
'Youve got a huge amount of assets but its not enough. To the moon.',
button: {
label: 'Subscribe',
href: '/register',
},
features: [
'Commission-free trading',
'Multi-layered encryption',
'Real-time tip notifications',
'No investment limits',
'Advanced transaction anonymization',
'Automated tax-loss harvesting',
],
logomarkClassName: 'fill-cyan-500',
},
]
function CheckIcon(props) {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
<path
d="M9.307 12.248a.75.75 0 1 0-1.114 1.004l1.114-1.004ZM11 15.25l-.557.502a.75.75 0 0 0 1.15-.043L11 15.25Zm4.844-5.041a.75.75 0 0 0-1.188-.918l1.188.918Zm-7.651 3.043 2.25 2.5 1.114-1.004-2.25-2.5-1.114 1.004Zm3.4 2.457 4.25-5.5-1.187-.918-4.25 5.5 1.188.918Z"
fill="currentColor"
/>
<circle
cx="12"
cy="12"
r="8.25"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
function Plan({
name,
price,
description,
button,
features,
featured = false,
activePeriod,
logomarkClassName,
}) {
return (
<section
className={clsx(
'flex flex-col overflow-hidden rounded-3xl p-6 shadow-lg shadow-gray-900/5',
featured ? 'order-first bg-gray-900 lg:order-none' : 'bg-white'
)}
>
<h3
className={clsx(
'flex items-center text-sm font-semibold',
featured ? 'text-white' : 'text-gray-900'
)}
>
<Logomark className={clsx('h-6 w-6 flex-none', logomarkClassName)} />
<span className="ml-4">{name}</span>
</h3>
<p
className={clsx(
'relative mt-5 flex text-3xl tracking-tight',
featured ? 'text-white' : 'text-gray-900'
)}
>
{price.Monthly === price.Annually ? (
price.Monthly
) : (
<>
<span
aria-hidden={activePeriod === 'Annually'}
className={clsx(
'transition duration-300',
activePeriod === 'Annually' &&
'pointer-events-none translate-x-6 select-none opacity-0'
)}
>
{price.Monthly}
</span>
<span
aria-hidden={activePeriod === 'Monthly'}
className={clsx(
'absolute left-0 top-0 transition duration-300',
activePeriod === 'Monthly' &&
'pointer-events-none -translate-x-6 select-none opacity-0'
)}
>
{price.Annually}
</span>
</>
)}
</p>
<p
className={clsx(
'mt-3 text-sm',
featured ? 'text-gray-300' : 'text-gray-700'
)}
>
{description}
</p>
<div className="order-last mt-6">
<ul
role="list"
className={clsx(
'-my-2 divide-y text-sm',
featured
? 'divide-gray-800 text-gray-300'
: 'divide-gray-200 text-gray-700'
)}
>
{features.map((feature) => (
<li key={feature} className="flex py-2">
<CheckIcon
className={clsx(
'h-6 w-6 flex-none',
featured ? 'text-white' : 'text-cyan-500'
)}
/>
<span className="ml-4">{feature}</span>
</li>
))}
</ul>
</div>
<Button
href={button.href}
color={featured ? 'cyan' : 'gray'}
className="mt-6"
aria-label={`Get started with the ${name} plan for ${price}`}
>
{button.label}
</Button>
</section>
)
}
export function Pricing() {
let [activePeriod, setActivePeriod] = useState('Monthly')
return (
<section
id="pricing"
aria-labelledby="pricing-title"
className="border-t border-gray-200 bg-gray-100 py-20 sm:py-32"
>
<Container>
<div className="mx-auto max-w-2xl text-center">
<h2
id="pricing-title"
className="text-3xl font-medium tracking-tight text-gray-900"
>
Flat pricing, no management fees.
</h2>
<p className="mt-2 text-lg text-gray-600">
Whether youre one person trying to get ahead or a big firm trying
to take over the world, weve got a plan for you.
</p>
</div>
<div className="mt-8 flex justify-center">
<div className="relative">
<RadioGroup
value={activePeriod}
onChange={setActivePeriod}
className="grid grid-cols-2"
>
{['Monthly', 'Annually'].map((period) => (
<RadioGroup.Option
key={period}
value={period}
className={clsx(
'cursor-pointer border border-gray-300 py-[calc(theme(spacing.2)-1px)] px-[calc(theme(spacing.3)-1px)] text-sm text-gray-700 outline-2 outline-offset-2 transition-colors hover:border-gray-400',
period === 'Monthly'
? 'rounded-l-lg'
: '-ml-px rounded-r-lg'
)}
>
{period}
</RadioGroup.Option>
))}
</RadioGroup>
<div
aria-hidden="true"
className={clsx(
'pointer-events-none absolute inset-0 z-10 grid grid-cols-2 overflow-hidden rounded-lg bg-cyan-500 transition-all duration-300',
activePeriod === 'Monthly'
? '[clip-path:inset(0_50%_0_0)]'
: '[clip-path:inset(0_0_0_calc(50%-1px))]'
)}
>
{['Monthly', 'Annually'].map((period) => (
<div
key={period}
className={clsx(
'py-2 text-center text-sm font-semibold text-white [&:not(:focus-visible)]:focus:outline-none',
period === 'Annually' && '-ml-px'
)}
>
{period}
</div>
))}
</div>
</div>
</div>
<div className="mx-auto mt-16 grid max-w-2xl grid-cols-1 items-start gap-x-8 gap-y-10 sm:mt-20 lg:max-w-none lg:grid-cols-3">
{plans.map((plan) => (
<Plan key={plan.name} {...plan} activePeriod={activePeriod} />
))}
</div>
</Container>
</section>
)
}

View File

@ -0,0 +1,235 @@
import { Fragment, useEffect, useId, useRef, useState } from 'react'
import { Tab } from '@headlessui/react'
import clsx from 'clsx'
import { AnimatePresence, motion } from 'framer-motion'
import { useDebouncedCallback } from 'use-debounce'
import Image from 'next/image'
import { AppScreen } from '@/components/AppScreen'
import { CircleBackground } from '@/components/CircleBackground'
import { Container } from '@/components/Container'
import { PhoneFrame } from '@/components/PhoneFrame'
import {
DiageoLogo,
LaravelLogo,
MirageLogo,
ReversableLogo,
StatamicLogo,
StaticKitLogo,
TransistorLogo,
TupleLogo,
} from '@/components/StockLogos'
import exampleApp from '@/images/example-app.png'
const MotionAppScreenHeader = motion(AppScreen.Header)
const MotionAppScreenBody = motion(AppScreen.Body)
const features = [
{
name: 'Invite friends for better returns',
description:
'For every friend you invite to Pocket, you get insider notifications 5 seconds sooner. And its 10 seconds if you invite an insider.',
icon: DeviceUserIcon
},
{
name: 'Notifications on stock dips',
description:
'Get a push notification every time we find out something thats going to lower the share price on your holdings so you can sell before the information hits the public markets.',
icon: DeviceNotificationIcon
},
{
name: 'Invest what you want',
description:
'We hide your stock purchases behind thousands of anonymous trading accounts, so suspicious activity can never be traced back to you.',
icon: DeviceTouchIcon
},
]
function DeviceUserIcon(props) {
return (
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16 23a3 3 0 100-6 3 3 0 000 6zm-1 2a4 4 0 00-4 4v1a2 2 0 002 2h6a2 2 0 002-2v-1a4 4 0 00-4-4h-2z"
fill="#737373"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v24a4.002 4.002 0 01-3.01 3.877c-.535.136-.99-.325-.99-.877s.474-.98.959-1.244A2 2 0 0025 28V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 001.041 1.756C8.525 30.02 9 30.448 9 31s-.455 1.013-.99.877A4.002 4.002 0 015 28V4z"
fill="#A3A3A3"
/>
</svg>
)
}
function DeviceNotificationIcon(props) {
return (
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
fill="#A3A3A3"
/>
<path
d="M9 8a2 2 0 012-2h10a2 2 0 012 2v2a2 2 0 01-2 2H11a2 2 0 01-2-2V8z"
fill="#737373"
/>
</svg>
)
}
function DeviceTouchIcon(props) {
let id = useId()
return (
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true" {...props}>
<defs>
<linearGradient
id={`${id}-gradient`}
x1={14}
y1={14.5}
x2={7}
y2={17}
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#737373" />
<stop offset={1} stopColor="#D4D4D4" stopOpacity={0} />
</linearGradient>
</defs>
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v13h-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 002 2h4v2H9a4 4 0 01-4-4V4z"
fill="#A3A3A3"
/>
<path
d="M7 22c0-4.694 3.5-8 8-8"
stroke={`url(#${id}-gradient)`}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M21 20l.217-5.513a1.431 1.431 0 00-2.85-.226L17.5 21.5l-1.51-1.51a2.107 2.107 0 00-2.98 0 .024.024 0 00-.005.024l3.083 9.25A4 4 0 0019.883 32H25a4 4 0 004-4v-5a3 3 0 00-3-3h-5z"
fill="#A3A3A3"
/>
</svg>
)
}
const headerAnimation = {
initial: { opacity: 0, transition: { duration: 0.3 } },
animate: { opacity: 1, transition: { duration: 0.3, delay: 0.3 } },
exit: { opacity: 0, transition: { duration: 0.3 } },
}
const maxZIndex = 2147483647
const bodyVariantBackwards = {
opacity: 0.4,
scale: 0.8,
zIndex: 0,
filter: 'blur(4px)',
zIndex: 0,
transition: { duration: 0.4 },
}
const bodyVariantForwards = (custom) => ({
y: '100%',
zIndex: maxZIndex - custom.changeCount,
transition: { duration: 0.4 },
})
const bodyAnimation = {
initial: 'initial',
animate: 'animate',
exit: 'exit',
variants: {
initial: (custom) =>
custom.isForwards ? bodyVariantForwards(custom) : bodyVariantBackwards,
animate: (custom) => ({
y: '0%',
opacity: 1,
scale: 1,
zIndex: maxZIndex / 2 - custom.changeCount,
filter: 'blur(0px)',
transition: { duration: 0.4 },
}),
exit: (custom) =>
custom.isForwards ? bodyVariantBackwards : bodyVariantForwards(custom),
},
}
function InviteScreen({ custom, animated = false }) {
return (
<AppScreen className="w-full">
<MotionAppScreenHeader {...(animated ? headerAnimation : {})}>
<AppScreen.Title>Invite people</AppScreen.Title>
<AppScreen.Subtitle>
Get tips <span className="text-white">5s sooner</span> for every
invite.
</AppScreen.Subtitle>
</MotionAppScreenHeader>
<MotionAppScreenBody {...(animated ? { ...bodyAnimation, custom } : {})}>
<div className="px-4 py-6">
<div className="space-y-6">
{[
{ label: 'Full name', value: 'Albert H. Wiggin' },
{ label: 'Email address', value: 'awiggin@chase.com' },
].map((field) => (
<div key={field.label}>
<div className="text-sm text-gray-500">{field.label}</div>
<div className="mt-2 border-b border-gray-200 pb-2 text-sm text-gray-900">
{field.value}
</div>
</div>
))}
</div>
<div className="mt-6 rounded-lg bg-cyan-500 py-2 px-3 text-center text-sm font-semibold text-white">
Invite person
</div>
</div>
</MotionAppScreenBody>
</AppScreen>
)
}
export function PrimaryFeatures() {
return (
<section
id="features"
aria-label="Features for investing all your money"
className="bg-gray-900 py-20 sm:py-32"
>
<Container>
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-3xl">
<h2 className="text-3xl font-medium tracking-tight text-white">
Every way you could possibly want to express yourself and talk with people
</h2>
<p className="mt-2 text-lg text-gray-400">
Akkoma is a part of the "fediverse"; that means it's a social network with no central
authority. You can follow and talk with anyone else that has an account on any other fediverse
service, and you can even host your own server if you want.
</p>
<br />
<p className="mt-2 text-lg text-gray-400">
For those more familiar with the fediverse, Akkoma is a specialised fork of Pleroma.
It is faster-paced in development and aligns itself more closely with Misskey than Pleroma mainline.
<br/>
It differentiates itself with a focus on custom expression, for example with custom emoji reactions,
or Misskey-Flavoured Markdown.
</p>
</div>
<div className={"items-center"}>
<Image src={exampleApp} className={"justify-center align-center rounded-lg pt-10"}/>
</div>
</Container>
</section>
)
}

274
src/components/Reviews.jsx Normal file
View File

@ -0,0 +1,274 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import clsx from 'clsx'
import {
motion,
useAnimationFrame,
useInView,
useMotionValue,
useSpring,
useTransform,
} from 'framer-motion'
import { Container } from '@/components/Container'
const reviews = [
{
title: 'It really works.',
body: 'I downloaded Pocket today and turned $5000 into $25,000 in half an hour.',
author: 'CrazyInvestor',
rating: 5,
},
{
title: 'You need this app.',
body: 'I didnt understand the stock market at all before Pocket. I still dont, but at least Im rich now.',
author: 'CluelessButRich',
rating: 5,
},
{
title: 'This shouldnt be legal.',
body: 'Pocket makes it so easy to win big in the stock market that I cant believe its actually legal.',
author: 'LivingDaDream',
rating: 5,
},
{
title: 'Screw financial advisors.',
body: 'I barely made any money investing in mutual funds. With Pocket, Im doubling my net-worth every single month.',
author: 'JordanBelfort1962',
rating: 5,
},
{
title: 'I love it!',
body: 'I started providing insider information myself and now I get new insider tips every 5 minutes. I dont even have time to act on all of them. New Lamborghini is being delivered next week!',
author: 'MrBurns',
rating: 5,
},
{
title: 'Too good to be true.',
body: 'I was making money so fast with Pocket that it felt like a scam. But I sold my shares and withdrew the money and its really there, right in my bank account. This app is crazy!',
author: 'LazyRich99',
rating: 5,
},
{
title: 'Wish I could give 6 stars',
body: 'This is literally the most important app you will ever download in your life. Get on this before its so popular that everyone else is getting these tips too.',
author: 'SarahLuvzCash',
rating: 5,
},
{
title: 'Bought an island.',
body: 'Yeah, you read that right. Want your own island too? Get Pocket.',
author: 'ScroogeMcduck',
rating: 5,
},
{
title: 'No more debt!',
body: 'After 2 weeks of trading on Pocket I was debt-free. Why did I even go to school at all when Pocket exists?',
author: 'BruceWayne',
rating: 5,
},
{
title: 'Im 13 and Im rich.',
body: 'I love that with Pockets transaction anonymization I could sign up and start trading when I was 12 years old. I had a million dollars before I had armpit hair!',
author: 'RichieRich',
rating: 5,
},
{
title: 'Started an investment firm.',
body: 'I charge clients a 3% management fee and just throw all their investments into Pocket. Easy money!',
author: 'TheCountOfMonteChristo',
rating: 5,
},
{
title: 'Its like a superpower.',
body: 'Every tip Pocket has sent me has paid off. Its like playing Blackjack but knowing exactly what card is coming next!',
author: 'ClarkKent',
rating: 5,
},
{
title: 'Quit my job.',
body: 'I downloaded Pocket three days ago and quit my job today. I cant believe no one else thought to build a stock trading app that works this way!',
author: 'GeorgeCostanza',
rating: 5,
},
{
title: 'Dont download this app',
body: 'Unless you want to have the best life ever! I am literally writing this from a yacht.',
author: 'JeffBezos',
rating: 5,
},
]
function StarIcon(props) {
return (
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
</svg>
)
}
function StarRating({ rating }) {
return (
<div className="flex">
{[...Array(5).keys()].map((index) => (
<StarIcon
key={index}
className={clsx(
'h-5 w-5',
rating > index ? 'fill-cyan-500' : 'fill-gray-300'
)}
/>
))}
</div>
)
}
function Review({ title, body, author, rating, className, ...props }) {
let animationDelay = useMemo(() => {
let possibleAnimationDelays = ['0s', '0.1s', '0.2s', '0.3s', '0.4s', '0.5s']
return possibleAnimationDelays[
Math.floor(Math.random() * possibleAnimationDelays.length)
]
}, [])
return (
<figure
className={clsx(
'animate-fade-in rounded-3xl bg-white p-6 opacity-0 shadow-md shadow-gray-900/5',
className
)}
style={{ animationDelay }}
{...props}
>
<blockquote className="text-gray-900">
<StarRating rating={rating} />
<p className="mt-4 text-lg font-semibold leading-6 before:content-['“'] after:content-['”']">
{title}
</p>
<p className="mt-3 text-base leading-7">{body}</p>
</blockquote>
<figcaption className="mt-3 text-sm text-gray-600 before:content-['_']">
{author}
</figcaption>
</figure>
)
}
function splitArray(array, numParts) {
let result = []
for (let i = 0; i < array.length; i++) {
let index = i % numParts
if (!result[index]) {
result[index] = []
}
result[index].push(array[i])
}
return result
}
function ReviewColumn({
className,
reviews,
reviewClassName = () => {},
msPerPixel = 0,
}) {
let columnRef = useRef()
let [columnHeight, setColumnHeight] = useState(0)
let duration = `${columnHeight * msPerPixel}ms`
useEffect(() => {
let resizeObserver = new window.ResizeObserver(() => {
setColumnHeight(columnRef.current.offsetHeight)
})
resizeObserver.observe(columnRef.current)
return () => {
resizeObserver.disconnect()
}
}, [])
return (
<div
ref={columnRef}
className={clsx('animate-marquee space-y-8 py-4', className)}
style={{ '--marquee-duration': duration }}
>
{reviews.concat(reviews).map((review, reviewIndex) => (
<Review
key={reviewIndex}
aria-hidden={reviewIndex >= reviews.length}
className={reviewClassName(reviewIndex % reviews.length)}
{...review}
/>
))}
</div>
)
}
function ReviewGrid() {
let containerRef = useRef()
let isInView = useInView(containerRef, { once: true, amount: 0.4 })
let columns = splitArray(reviews, 3)
columns = [columns[0], columns[1], splitArray(columns[2], 2)]
return (
<div
ref={containerRef}
className="relative -mx-4 mt-16 grid h-[49rem] max-h-[150vh] grid-cols-1 items-start gap-8 overflow-hidden px-4 sm:mt-20 md:grid-cols-2 lg:grid-cols-3"
>
{isInView && (
<>
<ReviewColumn
reviews={[...columns[0], ...columns[2].flat(), ...columns[1]]}
reviewClassName={(reviewIndex) =>
clsx(
reviewIndex >= columns[0].length + columns[2][0].length &&
'md:hidden',
reviewIndex >= columns[0].length && 'lg:hidden'
)
}
msPerPixel={10}
/>
<ReviewColumn
reviews={[...columns[1], ...columns[2][1]]}
className="hidden md:block"
reviewClassName={(reviewIndex) =>
reviewIndex >= columns[1].length && 'lg:hidden'
}
msPerPixel={15}
/>
<ReviewColumn
reviews={columns[2].flat()}
className="hidden lg:block"
msPerPixel={10}
/>
</>
)}
<div className="pointer-events-none absolute inset-x-0 top-0 h-32 bg-gradient-to-b from-gray-50" />
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-gray-50" />
</div>
)
}
export function Reviews() {
return (
<section
id="reviews"
aria-labelledby="reviews-title"
className="pt-20 pb-16 sm:pt-32 sm:pb-24"
>
<Container>
<h2
id="reviews-title"
className="text-3xl font-medium tracking-tight text-gray-900 sm:text-center"
>
Everyone is changing their life with Pocket.
</h2>
<p className="mt-2 text-lg text-gray-600 sm:text-center">
Thousands of people have doubled their net-worth in the last 30 days.
</p>
<ReviewGrid />
</Container>
</section>
)
}

View File

@ -0,0 +1,78 @@
import { useId } from 'react'
import { PencilSquareIcon, PhotoIcon, UserGroupIcon, FaceSmileIcon, SparklesIcon, RocketLaunchIcon } from '@heroicons/react/20/solid'
import { Container } from '@/components/Container'
const features = [
{
name: 'Post statuses, with photos',
description:
'With unlimited attachments per post, you can share photos, videos, and more.',
icon: PhotoIcon,
},
{
name: 'Follow people anywhere on the fediverse',
description:
'Keep up with your friends and collect them into lists to customise what posts you see!',
icon: UserGroupIcon,
},
{
name: 'React to your friends posts',
description:
'Have something to say, but not something you can put into words? React to posts with emojis!',
icon: FaceSmileIcon,
},
{
name: 'Post Misskey Markdown',
description:
'Create fancy animations with rich markup!',
icon: SparklesIcon,
},
{
name: 'Edit your posts, as many times as you want',
description:
'There\'s no limit to how many times you can edit your posts, so you can make sure they\'re perfect!',
icon: PencilSquareIcon,
},
{
name: 'Enjoy a substantial speed upgrade',
description:
'Akkoma is consistently 30-50% faster than Pleroma when handling common operations!',
icon: RocketLaunchIcon,
},
]
export function SecondaryFeatures() {
return (
<section
id="secondary-features"
aria-label="Features for building a portfolio"
className="py-20 sm:py-32"
>
<Container>
<div className="mx-auto max-w-2xl sm:text-center">
<h2 className="text-3xl font-medium tracking-tight text-gray-900">
What can I do with Akkoma?
</h2>
</div>
<ul
role="list"
className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-6 text-sm sm:mt-20 sm:grid-cols-2 md:gap-y-10 lg:max-w-none lg:grid-cols-3"
>
{features.map((feature) => (
<li
key={feature.name}
className="rounded-2xl border border-gray-200 p-8"
>
<feature.icon className="h-8 w-8" />
<h3 className="mt-6 font-semibold text-gray-900">
{feature.name}
</h3>
<p className="mt-2 text-gray-700">{feature.description}</p>
</li>
))}
</ul>
</Container>
</section>
)
}

View File

@ -0,0 +1,100 @@
export function LaravelLogo(props) {
return (
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M29.982 14.509c.002.005.006.01.007.015a.316.316 0 0 1 .011.082v4.293a.304.304 0 0 1-.043.156.32.32 0 0 1-.119.115l-3.709 2.075v4.112a.305.305 0 0 1-.043.157.32.32 0 0 1-.119.114l-7.742 4.33a.286.286 0 0 1-.056.023l-.022.008a.33.33 0 0 1-.18-.005l-.01-.005c-.018-.006-.036-.011-.053-.021l-7.742-4.33a.32.32 0 0 1-.119-.115.304.304 0 0 1-.043-.156v-12.88a.33.33 0 0 1 .01-.08c.004-.01.01-.018.012-.027l.01-.027a.158.158 0 0 1 .011-.022c.006-.01.015-.018.023-.028.009-.012.017-.025.028-.036.01-.01.02-.016.031-.024.012-.009.023-.019.036-.026l3.871-2.165a.33.33 0 0 1 .322 0l3.872 2.165c.013.007.024.017.036.026l.01.008c.008.005.015.01.021.016a.175.175 0 0 1 .021.025l.008.011.022.028c.008.015.014.032.02.049l.006.01.006.016a.307.307 0 0 1 .01.082v8.044l3.227-1.804v-4.112c0-.028.004-.055.011-.082.003-.01.008-.017.011-.026l.004-.01a.228.228 0 0 1 .017-.039.132.132 0 0 1 .013-.018.203.203 0 0 0 .01-.01c.009-.012.017-.025.028-.036l.015-.013.016-.01.019-.016a.126.126 0 0 1 .017-.011l3.871-2.165a.33.33 0 0 1 .322 0l3.871 2.165c.014.007.024.018.036.026l.012.008.02.016a.162.162 0 0 1 .02.026l.009.01.008.01c.005.006.01.012.013.018a.254.254 0 0 1 .018.04l.003.009.005.01Zm-15.138 8.717 3.22 1.77 7.094-3.933-3.223-1.803-7.091 3.966Zm10.64-2.704v-3.57l-3.226-1.804v3.57l3.225 1.804Zm3.547-5.916-3.225-1.803-3.224 1.803 3.224 1.803 3.225-1.803Zm-14.515.218v7.863l3.226-1.805V13.02l-3.226 1.804Zm2.902-2.346-3.225-1.803-3.224 1.803 3.224 1.803 3.225-1.803Zm-3.547 2.347-3.226-1.805v12.155l7.098 3.97V25.54l-3.708-2.038h-.001l-.002-.002c-.013-.008-.024-.018-.035-.027a.28.28 0 0 0-.011-.007.133.133 0 0 1-.02-.015v-.001l-.019-.022a.452.452 0 0 0-.008-.011l-.016-.02a.086.086 0 0 1-.008-.01v-.002a.123.123 0 0 1-.013-.027l-.005-.012-.008-.016a.115.115 0 0 1-.007-.02.18.18 0 0 1-.005-.033l-.002-.013a.293.293 0 0 0-.002-.013l-.002-.022v-8.405Zm4.516 10.715v3.605l7.096-3.969v-3.572l-7.096 3.935Zm7.742-5.019 3.226-1.804v-3.57l-3.226 1.805v3.57Z"
/>
</svg>
)
}
export function TupleLogo(props) {
return (
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M22.5 8 12 11.692v12l3.5 1.231v3.385L26 32V12.615l-3.5 1.231V8Zm-5.833 17.334 5.833 2.05v-12.24l2.333-.82v15.968l-8.166-2.87v-2.088Z"
/>
</svg>
)
}
export function TransistorLogo(props) {
return (
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
<path d="M20 32c-6.617 0-12-5.383-12-12S13.383 8 20 8s12 5.383 12 12-5.383 12-12 12Zm0-22.4C14.267 9.6 9.6 14.266 9.6 20S14.267 30.4 20 30.4c5.734 0 10.4-4.666 10.4-10.4S25.734 9.6 20 9.6Z" />
<path d="M19.434 27.749c.15.15.354.234.566.235.433 0 .8-.368.8-.8V12.815a.8.8 0 0 0-1.6 0v14.368c0 .212.084.415.234.565ZM12.833 20.8h3.833a.802.802 0 0 0 .802-.8.8.8 0 0 0-.801-.8h-3.834c-.45 0-.8.35-.8.8a.8.8 0 0 0 .8.8ZM23.333 20.8h3.85c.433 0 .783-.35.783-.8a.799.799 0 0 0-.8-.8h-3.833c-.45 0-.8.35-.8.8a.8.8 0 0 0 .8.8Z" />
</svg>
)
}
export function DiageoLogo(props) {
return (
<svg
viewBox="0 0 40 40"
fill="#fff"
stroke="#fff"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
{...props}
>
<path d="M22.16 19 26 13H14l3.84 6" fill="none" />
<path d="M25 24a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z" />
</svg>
)
}
export function StaticKitLogo(props) {
return (
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
<path d="m26.068 10.555-11.49 13.089L12 21.089 23.489 8l2.58 2.555ZM28 18.91 16.512 32l-2.579-2.555 11.489-13.089L28 18.911Z" />
</svg>
)
}
export function StatamicLogo(props) {
return (
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M30.177 27.293c0 1.921-.644 2.707-2.398 2.707H12.22c-1.754 0-2.397-.786-2.397-2.707v-3.741c0-1.805-.837-2.824-1.642-3.291a.385.385 0 0 1-.133-.143.403.403 0 0 1 .133-.526c.837-.551 1.642-1.704 1.642-3.241v-3.677c0-2.072.547-2.674 2.3-2.674h15.754c1.754 0 2.3.602 2.3 2.674v3.675c0 1.537.805 2.69 1.641 3.24.243.168.243.52 0 .67-.804.484-1.64 1.503-1.64 3.29v3.743h-.001Zm-14.739-2.455c1.271 1.152 2.64 1.737 4.522 1.737 2.96 0 4.891-1.537 4.891-4.026 0-2.637-2.3-3.31-4.17-3.856-1.282-.375-2.363-.691-2.363-1.54 0-.551.564-1.086 1.513-1.086.917 0 1.674.2 2.397.584.242.117.467.2.676.2.306 0 .547-.15.756-.45l.29-.451a.955.955 0 0 0 .161-.55c0-.336-.161-.67-.402-.837-.966-.635-2.27-1.17-4.039-1.17-2.51 0-4.44 1.37-4.44 3.826 0 2.746 2.349 3.443 4.23 4h.001c1.255.372 2.3.681 2.3 1.497 0 .785-.707 1.17-1.592 1.17a5.19 5.19 0 0 1-2.992-.92c-.274-.183-.532-.3-.805-.3-.242 0-.451.117-.644.368l-.387.517a.888.888 0 0 0-.192.585c0 .25.08.501.29.702Z"
/>
</svg>
)
}
export function MirageLogo(props) {
return (
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M24.05 9c2.307 0 4.177 1.885 4.177 4.21a4.21 4.21 0 0 1-2.762 3.964l3.366 6.057h2.304c.355 0 .642.29.642.647a.645.645 0 0 1-.642.647H7.142a.645.645 0 0 1-.642-.647c0-.358.288-.647.643-.647h2.304l5.994-10.747a.641.641 0 0 1 1.097-.036l3.444 5.32 1.071-1.627a4.214 4.214 0 0 1-1.178-2.93c0-2.326 1.87-4.211 4.176-4.211Zm-3.304 9.948 2.772 4.283h3.84l-4.317-7.769-2.295 3.486Zm1.239 4.283-5.944-9.183-5.121 9.183h11.065Zm5.038-10.02a2.995 2.995 0 0 1-2.159 2.883l-1.216-2.19a.64.64 0 0 0-1.096-.04l-.811 1.232a3 3 0 0 1-.663-1.885c0-1.655 1.332-2.997 2.973-2.997 1.641 0 2.972 1.341 2.972 2.997Z"
/>
<path d="M12.069 26.469c-.354 0-.641.289-.641.646 0 .358.287.646.64.646h14.139c.354 0 .641-.29.641-.646a.644.644 0 0 0-.64-.646h-14.14Zm4.928 3.236a.645.645 0 0 0-.642.648c0 .357.288.647.642.647h4.282c.355 0 .643-.29.643-.647a.645.645 0 0 0-.643-.648h-4.282Z" />
</svg>
)
}
export function ReversableLogo(props) {
return (
<svg
viewBox="0 0 40 40"
fill="none"
stroke="#fff"
strokeWidth="2"
strokeLinecap="square"
strokeLinejoin="round"
aria-hidden="true"
{...props}
>
<path d="M15 26v-5.25m0 0V16a2 2 0 0 1 2-2h4.21c.968 0 1.37 1.24.587 1.809L15 20.75Zm0 0L25 26" />
</svg>
)
}

BIN
src/images/example-app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

231
src/images/phone-frame.svg Normal file
View File

@ -0,0 +1,231 @@
<svg width="366" height="729" fill="none" xmlns="http://www.w3.org/2000/svg">
<g mask="url(#mask)">
<g filter="url(#a)">
<path
d="M363.315 64.213C363.315 22.99 341.312 1 300.092 1H66.751C25.53 1 3.528 22.99 3.528 64.213v44.68l-.857.143A2 2 0 0 0 1 111.009v24.611a2 2 0 0 0 1.671 1.973l.95.158a2.26 2.26 0 0 1-.093.236v26.173c.212.1.398.296.541.643l-1.398.233A2 2 0 0 0 1 167.009v47.611a2 2 0 0 0 1.671 1.973l1.368.228c-.139.319-.314.533-.511.653v16.637c.221.104.414.313.56.689l-1.417.236A2 2 0 0 0 1 237.009v47.611a2 2 0 0 0 1.671 1.973l1.347.225c-.135.294-.302.493-.49.607v377.681c0 41.213 22 63.208 63.223 63.208h95.074c.947-.504 2.717-.843 4.745-.843l.141.001h.194l.086-.001 33.704.005c1.849.043 3.442.37 4.323.838h95.074c41.222 0 63.223-21.999 63.223-63.212v-394.63c-.259-.275-.48-.796-.63-1.47l-.011-.133 1.655-.276A2 2 0 0 0 366 266.62v-77.611a2 2 0 0 0-1.671-1.973l-1.712-.285c.148-.839.396-1.491.698-1.811V64.213Z"
fill="url(#b)" />
<path
d="M363.315 64.213C363.315 22.99 341.312 1 300.092 1H66.751C25.53 1 3.528 22.99 3.528 64.213v44.68l-.857.143A2 2 0 0 0 1 111.009v24.611a2 2 0 0 0 1.671 1.973l.95.158a2.26 2.26 0 0 1-.093.236v26.173c.212.1.398.296.541.643l-1.398.233A2 2 0 0 0 1 167.009v47.611a2 2 0 0 0 1.671 1.973l1.368.228c-.139.319-.314.533-.511.653v16.637c.221.104.414.313.56.689l-1.417.236A2 2 0 0 0 1 237.009v47.611a2 2 0 0 0 1.671 1.973l1.347.225c-.135.294-.302.493-.49.607v377.681c0 41.213 22 63.208 63.223 63.208h95.074c.947-.504 2.717-.843 4.745-.843l.141.001h.194l.086-.001 33.704.005c1.849.043 3.442.37 4.323.838h95.074c41.222 0 63.223-21.999 63.223-63.212v-394.63c-.259-.275-.48-.796-.63-1.47l-.011-.133 1.655-.276A2 2 0 0 0 366 266.62v-77.611a2 2 0 0 0-1.671-1.973l-1.712-.285c.148-.839.396-1.491.698-1.811V64.213Z"
fill="url(#c)" />
</g>
<g filter="url(#d)">
<path
d="M5 133.772v-21.15c0-1.359-.54-2.661-1.5-3.622-.844-.073-2.496.257-2.496 2.157v24.562c.406 2.023 2.605 2.023 2.605 2.023A6.363 6.363 0 0 0 5 133.772Z"
fill="url(#e)" />
<path
d="M5 133.772v-21.15c0-1.359-.54-2.661-1.5-3.622-.844-.073-2.496.257-2.496 2.157v24.562c.406 2.023 2.605 2.023 2.605 2.023A6.363 6.363 0 0 0 5 133.772Z"
fill="url(#f)" fill-opacity=".1" />
</g>
<g filter="url(#g)">
<path
d="M5 213.772v-46.15c0-1.359-.54-2.661-1.5-3.622-.844-.073-2.496.257-2.496 2.157v49.562c.406 2.023 2.605 2.023 2.605 2.023A6.363 6.363 0 0 0 5 213.772Z"
fill="url(#h)" />
<path
d="M5 213.772v-46.15c0-1.359-.54-2.661-1.5-3.622-.844-.073-2.496.257-2.496 2.157v49.562c.406 2.023 2.605 2.023 2.605 2.023A6.363 6.363 0 0 0 5 213.772Z"
fill="url(#i)" fill-opacity=".1" />
</g>
<g filter="url(#j)">
<path
d="M5 283.772v-46.15c0-1.359-.54-2.661-1.5-3.622-.844-.073-2.496.257-2.496 2.157v49.562c.406 2.023 2.605 2.023 2.605 2.023A6.363 6.363 0 0 0 5 283.772Z"
fill="url(#k)" />
<path
d="M5 283.772v-46.15c0-1.359-.54-2.661-1.5-3.622-.844-.073-2.496.257-2.496 2.157v49.562c.406 2.023 2.605 2.023 2.605 2.023A6.363 6.363 0 0 0 5 283.772Z"
fill="url(#l)" fill-opacity=".1" />
</g>
<g filter="url(#m)">
<path
d="M362.004 266.772v-78.15a5.12 5.12 0 0 1 1.5-3.622c.844-.073 2.496.257 2.496 2.157v81.562c-.406 2.023-2.605 2.023-2.605 2.023a6.359 6.359 0 0 1-1.391-3.97Z"
fill="url(#n)" />
<path
d="M362.004 266.772v-78.15a5.12 5.12 0 0 1 1.5-3.622c.844-.073 2.496.257 2.496 2.157v81.562c-.406 2.023-2.605 2.023-2.605 2.023a6.359 6.359 0 0 1-1.391-3.97Z"
fill="url(#o)" fill-opacity=".1" />
</g>
<path
d="M305 14.5H59c-24.577 0-44.5 19.923-44.5 44.5v615c0 23.472 19.028 42.5 42.5 42.5h250c23.472 0 42.5-19.028 42.5-42.5V59c0-24.577-19.923-44.5-44.5-44.5Z"
stroke="url(#p)" stroke-opacity=".5" />
<g filter="url(#q)" shape-rendering="crispEdges">
<path
d="M16 59c0-23.748 19.252-43 43-43h246c23.748 0 43 19.252 43 43v615c0 23.196-18.804 42-42 42H58c-23.196 0-42-18.804-42-42V59Z"
fill="url(#r)" fill-opacity=".3" />
<path
d="M305 15.5H59c-24.024 0-43.5 19.476-43.5 43.5v615c0 23.472 19.028 42.5 42.5 42.5h248c23.472 0 42.5-19.028 42.5-42.5V59c0-24.024-19.476-43.5-43.5-43.5Z"
stroke="#000" stroke-opacity=".07" />
</g>
<g filter="url(#s)">
<rect x="154" y="29" width="56" height="5" rx="2.5" fill="#D4D4D4" />
</g>
</g>
<defs>
<mask id="mask">
<rect width="366" height="729" fill="#fff" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M89.728 24a4.213 4.213 0 0 1 4.213 4.212v2.527c0 10.235 8.3 18.532 18.539 18.532h139.04c10.239 0 18.539-8.297 18.539-18.532v-2.527A4.212 4.212 0 0 1 274.272 24h32.864C325.286 24 340 38.71 340 56.853v618.295c0 18.144-14.714 32.853-32.864 32.853H56.864c-18.15 0-32.864-14.709-32.864-32.853V56.853C24 38.709 38.714 24 56.864 24h32.864Z"
fill="#000" />
</mask>
<linearGradient id="e" x1="1.004" y1="123.367" x2="5" y2="123.367" gradientUnits="userSpaceOnUse">
<stop stop-color="#D4D4D4" />
<stop offset="1" stop-color="#E6E6E6" />
</linearGradient>
<linearGradient id="f" x1="3.002" y1="108.991" x2="3.002" y2="116.75" gradientUnits="userSpaceOnUse">
<stop stop-color="#171717" />
<stop offset=".783" stop-color="#171717" stop-opacity="0" />
</linearGradient>
<linearGradient id="h" x1="1.004" y1="190.867" x2="5" y2="190.867" gradientUnits="userSpaceOnUse">
<stop stop-color="#D4D4D4" />
<stop offset="1" stop-color="#E6E6E6" />
</linearGradient>
<linearGradient id="i" x1="3.002" y1="163.991" x2="3.002" y2="178.497" gradientUnits="userSpaceOnUse">
<stop stop-color="#171717" />
<stop offset=".783" stop-color="#171717" stop-opacity="0" />
</linearGradient>
<linearGradient id="k" x1="1.004" y1="260.867" x2="5" y2="260.867" gradientUnits="userSpaceOnUse">
<stop stop-color="#D4D4D4" />
<stop offset="1" stop-color="#E6E6E6" />
</linearGradient>
<linearGradient id="l" x1="3.002" y1="233.991" x2="3.002" y2="248.497" gradientUnits="userSpaceOnUse">
<stop stop-color="#171717" />
<stop offset=".783" stop-color="#171717" stop-opacity="0" />
</linearGradient>
<linearGradient id="n" x1="362.004" y1="226.25" x2="366" y2="226.25" gradientUnits="userSpaceOnUse">
<stop offset=".124" stop-color="#E6E6E6" />
<stop offset="1" stop-color="#D4D4D4" />
</linearGradient>
<linearGradient id="o" x1="364.002" y1="184.991" x2="364.002" y2="208.134" gradientUnits="userSpaceOnUse">
<stop stop-color="#171717" />
<stop offset=".783" stop-color="#171717" stop-opacity="0" />
</linearGradient>
<linearGradient id="p" x1="182" y1="15" x2="182" y2="716" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff" />
<stop offset=".381" stop-color="#fff" stop-opacity="0" />
</linearGradient>
<filter id="a" x="-1" y="-1" width="367" height="730.314" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feColorMatrix in="SourceAlpha" 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" />
<feGaussianBlur stdDeviation="1.5" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0" />
<feBlend in2="shape" result="effect1_innerShadow_104_2007" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="-2" />
<feGaussianBlur stdDeviation="2" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0.0901961 0 0 0 0 0.0901961 0 0 0 0 0.0901961 0 0 0 0.17 0" />
<feBlend in2="effect1_innerShadow_104_2007" result="effect2_innerShadow_104_2007" />
<feColorMatrix in="SourceAlpha" 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" />
<feGaussianBlur stdDeviation=".5" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.6 0" />
<feBlend in2="effect2_innerShadow_104_2007" result="effect3_innerShadow_104_2007" />
</filter>
<filter id="d" x="1.004" y="108.991" width="4.996" height="28.751" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="1" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0" />
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_104_2007" />
<feBlend in="SourceGraphic" in2="effect1_dropShadow_104_2007" result="shape" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="-1" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.06 0" />
<feBlend in2="shape" result="effect2_innerShadow_104_2007" />
</filter>
<filter id="g" x="1.004" y="163.991" width="4.996" height="53.751" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="1" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0" />
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_104_2007" />
<feBlend in="SourceGraphic" in2="effect1_dropShadow_104_2007" result="shape" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="-1" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.06 0" />
<feBlend in2="shape" result="effect2_innerShadow_104_2007" />
</filter>
<filter id="j" x="1.004" y="233.991" width="4.996" height="53.751" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="1" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0" />
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_104_2007" />
<feBlend in="SourceGraphic" in2="effect1_dropShadow_104_2007" result="shape" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="-1" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.06 0" />
<feBlend in2="shape" result="effect2_innerShadow_104_2007" />
</filter>
<filter id="m" x="361.004" y="184.991" width="4.996" height="85.751" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="-1" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0" />
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_104_2007" />
<feBlend in="SourceGraphic" in2="effect1_dropShadow_104_2007" result="shape" />
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="1" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.06 0" />
<feBlend in2="shape" result="effect2_innerShadow_104_2007" />
</filter>
<filter id="q" x="15" y="15" width="334" height="703" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" 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="1" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0" />
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_104_2007" />
<feBlend in="SourceGraphic" in2="effect1_dropShadow_104_2007" result="shape" />
<feColorMatrix in="SourceAlpha" 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="1" />
<feGaussianBlur stdDeviation="2.5" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0" />
<feBlend in2="shape" result="effect2_innerShadow_104_2007" />
</filter>
<filter id="s" x="154" y="29" width="56" height="6" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" 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="1" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0" />
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_104_2007" />
<feBlend in="SourceGraphic" in2="effect1_dropShadow_104_2007" result="shape" />
<feColorMatrix in="SourceAlpha" 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="1" />
<feGaussianBlur stdDeviation=".5" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" />
<feBlend in2="shape" result="effect2_innerShadow_104_2007" />
</filter>
<radialGradient id="b" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0 727 -642 0 184 1)">
<stop stop-color="#FAFAFA" />
<stop offset="1" stop-color="#E6E6E6" />
</radialGradient>
<radialGradient id="c" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0 319 -295.5 0 183.5 1)">
<stop stop-color="#fff" />
<stop offset=".533" stop-color="#fff" stop-opacity="0" />
</radialGradient>
<radialGradient id="r" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0 689 -326.783 0 182 27)">
<stop offset=".319" stop-color="#D4D4D4" />
<stop offset="1" stop-color="#E6E6E6" />
</radialGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

118
src/images/qr-code.svg Normal file
View File

@ -0,0 +1,118 @@
<svg width="80" height="80" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.2 0H0v3.2h3.2V0ZM3.2 3.2H0v3.2h3.2V3.2ZM3.2 6.4H0v3.2h3.2V6.4Z" fill="#171717" />
<path
d="M3.2 9.6H0v3.2h3.2V9.6ZM3.2 12.8H0V16h3.2v-3.2ZM3.2 16H0v3.2h3.2V16ZM3.2 19.2H0v3.2h3.2v-3.2ZM3.2 25.6H0v3.2h3.2v-3.2ZM3.2 35.2H0v3.2h3.2v-3.2ZM3.2 57.6H0v3.2h3.2v-3.2Z"
fill="#171717" />
<path d="M3.2 60.8H0V64h3.2v-3.2ZM3.2 64H0v3.2h3.2V64ZM3.2 67.2H0v3.2h3.2v-3.2ZM3.2 70.4H0v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M3.2 73.6H0v3.2h3.2v-3.2ZM3.2 76.8H0V80h3.2v-3.2ZM6.4 0H3.2v3.2h3.2V0ZM6.4 19.2H3.2v3.2h3.2v-3.2ZM6.4 25.6H3.2v3.2h3.2v-3.2ZM6.4 28.8H3.2V32h3.2v-3.2ZM6.4 32H3.2v3.2h3.2V32ZM6.4 35.2H3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M6.4 38.4H3.2v3.2h3.2v-3.2ZM6.4 48H3.2v3.2h3.2V48ZM6.4 51.2H3.2v3.2h3.2v-3.2ZM6.4 57.6H3.2v3.2h3.2v-3.2ZM6.4 76.8H3.2V80h3.2v-3.2ZM9.6 0H6.4v3.2h3.2V0ZM9.6 6.4H6.4v3.2h3.2V6.4Z"
fill="#171717" />
<path
d="M9.6 9.6H6.4v3.2h3.2V9.6ZM9.6 12.8H6.4V16h3.2v-3.2ZM9.6 19.2H6.4v3.2h3.2v-3.2ZM9.6 28.8H6.4V32h3.2v-3.2ZM9.6 32H6.4v3.2h3.2V32ZM9.6 41.6H6.4v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M9.6 44.8H6.4V48h3.2v-3.2ZM9.6 57.6H6.4v3.2h3.2v-3.2ZM9.6 64H6.4v3.2h3.2V64ZM9.6 67.2H6.4v3.2h3.2v-3.2ZM9.6 70.4H6.4v3.2h3.2v-3.2ZM9.6 76.8H6.4V80h3.2v-3.2ZM12.8 0H9.6v3.2h3.2V0ZM12.8 6.4H9.6v3.2h3.2V6.4Z"
fill="#171717" />
<path
d="M12.8 9.6H9.6v3.2h3.2V9.6ZM12.8 12.8H9.6V16h3.2v-3.2ZM12.8 19.2H9.6v3.2h3.2v-3.2ZM12.8 25.6H9.6v3.2h3.2v-3.2ZM12.8 38.4H9.6v3.2h3.2v-3.2ZM12.8 48H9.6v3.2h3.2V48ZM12.8 51.2H9.6v3.2h3.2v-3.2ZM12.8 57.6H9.6v3.2h3.2v-3.2ZM12.8 64H9.6v3.2h3.2V64ZM12.8 67.2H9.6v3.2h3.2v-3.2ZM12.8 70.4H9.6v3.2h3.2v-3.2ZM12.8 76.8H9.6V80h3.2v-3.2ZM16 0h-3.2v3.2H16V0ZM16 6.4h-3.2v3.2H16V6.4Z"
fill="#171717" />
<path
d="M16 9.6h-3.2v3.2H16V9.6ZM16 12.8h-3.2V16H16v-3.2ZM16 19.2h-3.2v3.2H16v-3.2ZM16 25.6h-3.2v3.2H16v-3.2ZM16 41.6h-3.2v3.2H16v-3.2Z"
fill="#171717" />
<path
d="M16 44.8h-3.2V48H16v-3.2ZM16 57.6h-3.2v3.2H16v-3.2ZM16 64h-3.2v3.2H16V64ZM16 67.2h-3.2v3.2H16v-3.2ZM16 70.4h-3.2v3.2H16v-3.2ZM16 76.8h-3.2V80H16v-3.2ZM19.2 0H16v3.2h3.2V0ZM19.2 19.2H16v3.2h3.2v-3.2ZM19.2 28.8H16V32h3.2v-3.2ZM19.2 44.8H16V48h3.2v-3.2ZM19.2 57.6H16v3.2h3.2v-3.2ZM19.2 76.8H16V80h3.2v-3.2ZM22.4 0h-3.2v3.2h3.2V0ZM22.4 3.2h-3.2v3.2h3.2V3.2ZM22.4 6.4h-3.2v3.2h3.2V6.4Z"
fill="#171717" />
<path
d="M22.4 9.6h-3.2v3.2h3.2V9.6ZM22.4 12.8h-3.2V16h3.2v-3.2ZM22.4 16h-3.2v3.2h3.2V16ZM22.4 19.2h-3.2v3.2h3.2v-3.2ZM22.4 25.6h-3.2v3.2h3.2v-3.2ZM22.4 32h-3.2v3.2h3.2V32ZM22.4 38.4h-3.2v3.2h3.2v-3.2ZM22.4 44.8h-3.2V48h3.2v-3.2ZM22.4 51.2h-3.2v3.2h3.2v-3.2ZM22.4 57.6h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M22.4 60.8h-3.2V64h3.2v-3.2ZM22.4 64h-3.2v3.2h3.2V64ZM22.4 67.2h-3.2v3.2h3.2v-3.2ZM22.4 70.4h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M22.4 73.6h-3.2v3.2h3.2v-3.2ZM22.4 76.8h-3.2V80h3.2v-3.2ZM25.6 28.8h-3.2V32h3.2v-3.2ZM25.6 32h-3.2v3.2h3.2V32ZM25.6 35.2h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M25.6 38.4h-3.2v3.2h3.2v-3.2ZM25.6 44.8h-3.2V48h3.2v-3.2ZM25.6 48h-3.2v3.2h3.2V48ZM25.6 51.2h-3.2v3.2h3.2v-3.2ZM28.8 0h-3.2v3.2h3.2V0ZM28.8 19.2h-3.2v3.2h3.2v-3.2ZM28.8 22.4h-3.2v3.2h3.2v-3.2ZM28.8 28.8h-3.2V32h3.2v-3.2ZM28.8 32h-3.2v3.2h3.2V32ZM28.8 35.2h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path d="M28.8 38.4h-3.2v3.2h3.2v-3.2ZM28.8 44.8h-3.2V48h3.2v-3.2ZM28.8 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path
d="M28.8 54.4h-3.2v3.2h3.2v-3.2ZM28.8 64h-3.2v3.2h3.2V64ZM28.8 67.2h-3.2v3.2h3.2v-3.2ZM28.8 73.6h-3.2v3.2h3.2v-3.2ZM28.8 76.8h-3.2V80h3.2v-3.2ZM32 0h-3.2v3.2H32V0ZM32 6.4h-3.2v3.2H32V6.4ZM32 16h-3.2v3.2H32V16ZM32 22.4h-3.2v3.2H32v-3.2ZM32 25.6h-3.2v3.2H32v-3.2ZM32 32h-3.2v3.2H32V32ZM32 38.4h-3.2v3.2H32v-3.2ZM32 54.4h-3.2v3.2H32v-3.2ZM32 57.6h-3.2v3.2H32v-3.2Z"
fill="#171717" />
<path
d="M32 60.8h-3.2V64H32v-3.2ZM32 76.8h-3.2V80H32v-3.2ZM35.2 0H32v3.2h3.2V0ZM35.2 9.6H32v3.2h3.2V9.6ZM35.2 12.8H32V16h3.2v-3.2ZM35.2 19.2H32v3.2h3.2v-3.2ZM35.2 28.8H32V32h3.2v-3.2ZM35.2 38.4H32v3.2h3.2v-3.2ZM35.2 41.6H32v3.2h3.2v-3.2ZM35.2 48H32v3.2h3.2V48ZM35.2 57.6H32v3.2h3.2v-3.2ZM35.2 64H32v3.2h3.2V64ZM35.2 76.8H32V80h3.2v-3.2Z"
fill="#171717" />
<path d="M38.4 0h-3.2v3.2h3.2V0ZM38.4 3.2h-3.2v3.2h3.2V3.2ZM38.4 6.4h-3.2v3.2h3.2V6.4Z" fill="#171717" />
<path
d="M38.4 9.6h-3.2v3.2h3.2V9.6ZM38.4 12.8h-3.2V16h3.2v-3.2ZM38.4 16h-3.2v3.2h3.2V16ZM38.4 51.2h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M38.4 54.4h-3.2v3.2h3.2v-3.2ZM38.4 60.8h-3.2V64h3.2v-3.2ZM38.4 64h-3.2v3.2h3.2V64ZM38.4 70.4h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M38.4 73.6h-3.2v3.2h3.2v-3.2ZM38.4 76.8h-3.2V80h3.2v-3.2ZM41.6 3.2h-3.2v3.2h3.2V3.2ZM41.6 12.8h-3.2V16h3.2v-3.2ZM41.6 19.2h-3.2v3.2h3.2v-3.2ZM41.6 22.4h-3.2v3.2h3.2v-3.2ZM41.6 25.6h-3.2v3.2h3.2v-3.2ZM41.6 32h-3.2v3.2h3.2V32ZM41.6 41.6h-3.2v3.2h3.2v-3.2ZM41.6 48h-3.2v3.2h3.2V48ZM41.6 51.2h-3.2v3.2h3.2v-3.2ZM41.6 57.6h-3.2v3.2h3.2v-3.2ZM41.6 67.2h-3.2v3.2h3.2v-3.2ZM41.6 73.6h-3.2v3.2h3.2v-3.2ZM41.6 76.8h-3.2V80h3.2v-3.2ZM44.8 0h-3.2v3.2h3.2V0ZM44.8 6.4h-3.2v3.2h3.2V6.4Z"
fill="#171717" />
<path d="M44.8 22.4h-3.2v3.2h3.2v-3.2ZM44.8 32h-3.2v3.2h3.2V32ZM44.8 41.6h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path d="M44.8 44.8h-3.2V48h3.2v-3.2ZM44.8 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path d="M44.8 54.4h-3.2v3.2h3.2v-3.2ZM44.8 57.6h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path
d="M44.8 60.8h-3.2V64h3.2v-3.2ZM44.8 64h-3.2v3.2h3.2V64ZM44.8 67.2h-3.2v3.2h3.2v-3.2ZM44.8 70.4h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M44.8 73.6h-3.2v3.2h3.2v-3.2ZM44.8 76.8h-3.2V80h3.2v-3.2ZM48 0h-3.2v3.2H48V0ZM48 16h-3.2v3.2H48V16ZM48 19.2h-3.2v3.2H48v-3.2ZM48 25.6h-3.2v3.2H48v-3.2ZM48 44.8h-3.2V48H48v-3.2ZM48 54.4h-3.2v3.2H48v-3.2ZM48 57.6h-3.2v3.2H48v-3.2Z"
fill="#171717" />
<path
d="M48 60.8h-3.2V64H48v-3.2ZM48 67.2h-3.2v3.2H48v-3.2ZM51.2 6.4H48v3.2h3.2V6.4ZM51.2 12.8H48V16h3.2v-3.2ZM51.2 22.4H48v3.2h3.2v-3.2ZM51.2 25.6H48v3.2h3.2v-3.2ZM51.2 28.8H48V32h3.2v-3.2ZM51.2 32H48v3.2h3.2V32ZM51.2 35.2H48v3.2h3.2v-3.2ZM51.2 41.6H48v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M51.2 44.8H48V48h3.2v-3.2ZM51.2 54.4H48v3.2h3.2v-3.2ZM51.2 60.8H48V64h3.2v-3.2ZM51.2 64H48v3.2h3.2V64ZM54.4 6.4h-3.2v3.2h3.2V6.4ZM54.4 12.8h-3.2V16h3.2v-3.2ZM54.4 19.2h-3.2v3.2h3.2v-3.2ZM54.4 28.8h-3.2V32h3.2v-3.2ZM54.4 32h-3.2v3.2h3.2V32ZM54.4 38.4h-3.2v3.2h3.2v-3.2ZM54.4 48h-3.2v3.2h3.2V48Z"
fill="#171717" />
<path d="M54.4 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path d="M54.4 54.4h-3.2v3.2h3.2v-3.2ZM54.4 57.6h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path
d="M54.4 60.8h-3.2V64h3.2v-3.2ZM54.4 64h-3.2v3.2h3.2V64ZM54.4 67.2h-3.2v3.2h3.2v-3.2ZM54.4 70.4h-3.2v3.2h3.2v-3.2ZM54.4 76.8h-3.2V80h3.2v-3.2ZM57.6 32h-3.2v3.2h3.2V32ZM57.6 41.6h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M57.6 44.8h-3.2V48h3.2v-3.2ZM57.6 51.2h-3.2v3.2h3.2v-3.2ZM57.6 64h-3.2v3.2h3.2V64ZM57.6 70.4h-3.2v3.2h3.2v-3.2ZM57.6 76.8h-3.2V80h3.2v-3.2ZM60.8 0h-3.2v3.2h3.2V0ZM60.8 3.2h-3.2v3.2h3.2V3.2ZM60.8 6.4h-3.2v3.2h3.2V6.4Z"
fill="#171717" />
<path
d="M60.8 9.6h-3.2v3.2h3.2V9.6ZM60.8 12.8h-3.2V16h3.2v-3.2ZM60.8 16h-3.2v3.2h3.2V16ZM60.8 19.2h-3.2v3.2h3.2v-3.2ZM60.8 25.6h-3.2v3.2h3.2v-3.2ZM60.8 35.2h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path
d="M60.8 38.4h-3.2v3.2h3.2v-3.2ZM60.8 44.8h-3.2V48h3.2v-3.2ZM60.8 48h-3.2v3.2h3.2V48ZM60.8 51.2h-3.2v3.2h3.2v-3.2ZM60.8 57.6h-3.2v3.2h3.2v-3.2ZM60.8 64h-3.2v3.2h3.2V64ZM60.8 67.2h-3.2v3.2h3.2v-3.2ZM64 0h-3.2v3.2H64V0ZM64 19.2h-3.2v3.2H64v-3.2ZM64 28.8h-3.2V32H64v-3.2ZM64 38.4h-3.2v3.2H64v-3.2ZM64 48h-3.2v3.2H64V48ZM64 51.2h-3.2v3.2H64v-3.2ZM64 64h-3.2v3.2H64V64ZM64 73.6h-3.2v3.2H64v-3.2ZM67.2 0H64v3.2h3.2V0ZM67.2 6.4H64v3.2h3.2V6.4Z"
fill="#171717" />
<path
d="M67.2 9.6H64v3.2h3.2V9.6ZM67.2 12.8H64V16h3.2v-3.2ZM67.2 19.2H64v3.2h3.2v-3.2ZM67.2 28.8H64V32h3.2v-3.2ZM67.2 41.6H64v3.2h3.2v-3.2Z"
fill="#171717" />
<path d="M67.2 44.8H64V48h3.2v-3.2ZM67.2 51.2H64v3.2h3.2v-3.2Z" fill="#171717" />
<path d="M67.2 54.4H64v3.2h3.2v-3.2ZM67.2 57.6H64v3.2h3.2v-3.2Z" fill="#171717" />
<path d="M67.2 60.8H64V64h3.2v-3.2ZM67.2 64H64v3.2h3.2V64ZM67.2 70.4H64v3.2h3.2v-3.2Z" fill="#171717" />
<path d="M67.2 73.6H64v3.2h3.2v-3.2ZM70.4 0h-3.2v3.2h3.2V0ZM70.4 6.4h-3.2v3.2h3.2V6.4Z" fill="#171717" />
<path
d="M70.4 9.6h-3.2v3.2h3.2V9.6ZM70.4 12.8h-3.2V16h3.2v-3.2ZM70.4 19.2h-3.2v3.2h3.2v-3.2ZM70.4 28.8h-3.2V32h3.2v-3.2ZM70.4 32h-3.2v3.2h3.2V32ZM70.4 35.2h-3.2v3.2h3.2v-3.2ZM70.4 44.8h-3.2V48h3.2v-3.2ZM70.4 48h-3.2v3.2h3.2V48ZM70.4 70.4h-3.2v3.2h3.2v-3.2ZM70.4 76.8h-3.2V80h3.2v-3.2ZM73.6 0h-3.2v3.2h3.2V0Z"
fill="#171717" />
<path d="M73.6 6.4h-3.2v3.2h3.2V6.4Z" fill="#171717" />
<path
d="M73.6 9.6h-3.2v3.2h3.2V9.6ZM73.6 12.8h-3.2V16h3.2v-3.2ZM73.6 19.2h-3.2v3.2h3.2v-3.2ZM73.6 28.8h-3.2V32h3.2v-3.2ZM73.6 35.2h-3.2v3.2h3.2v-3.2ZM73.6 44.8h-3.2V48h3.2v-3.2ZM73.6 48h-3.2v3.2h3.2V48ZM73.6 51.2h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path d="M73.6 54.4h-3.2v3.2h3.2v-3.2ZM73.6 70.4h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path
d="M73.6 73.6h-3.2v3.2h3.2v-3.2ZM76.8 0h-3.2v3.2h3.2V0ZM76.8 19.2h-3.2v3.2h3.2v-3.2ZM76.8 28.8h-3.2V32h3.2v-3.2ZM76.8 35.2h-3.2v3.2h3.2v-3.2ZM76.8 41.6h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path d="M76.8 44.8h-3.2V48h3.2v-3.2ZM76.8 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
<path
d="M76.8 54.4h-3.2v3.2h3.2v-3.2ZM76.8 64h-3.2v3.2h3.2V64ZM76.8 67.2h-3.2v3.2h3.2v-3.2ZM76.8 70.4h-3.2v3.2h3.2v-3.2Z"
fill="#171717" />
<path d="M76.8 73.6h-3.2v3.2h3.2v-3.2ZM80 0h-3.2v3.2H80V0ZM80 3.2h-3.2v3.2H80V3.2ZM80 6.4h-3.2v3.2H80V6.4Z"
fill="#171717" />
<path
d="M80 9.6h-3.2v3.2H80V9.6ZM80 12.8h-3.2V16H80v-3.2ZM80 16h-3.2v3.2H80V16ZM80 19.2h-3.2v3.2H80v-3.2ZM80 25.6h-3.2v3.2H80v-3.2ZM80 32h-3.2v3.2H80V32ZM80 35.2h-3.2v3.2H80v-3.2Z"
fill="#171717" />
<path
d="M80 38.4h-3.2v3.2H80v-3.2ZM80 44.8h-3.2V48H80v-3.2ZM80 48h-3.2v3.2H80V48ZM80 57.6h-3.2v3.2H80v-3.2ZM80 64h-3.2v3.2H80V64ZM80 67.2h-3.2v3.2H80v-3.2ZM80 70.4h-3.2v3.2H80v-3.2Z"
fill="#171717" />
<path d="M80 73.6h-3.2v3.2H80v-3.2ZM80 76.8h-3.2V80H80v-3.2Z" fill="#171717" />
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

6
src/pages/_app.jsx Normal file
View File

@ -0,0 +1,6 @@
import '@/styles/tailwind.css'
import 'focus-visible'
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}

13
src/pages/_document.jsx Normal file
View File

@ -0,0 +1,13 @@
import { Head, Html, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html className="h-full bg-gray-50 antialiased" lang="en">
<Head />
<body className="flex h-full flex-col">
<Main />
<NextScript />
</body>
</Html>
)
}

34
src/pages/index.jsx Normal file
View File

@ -0,0 +1,34 @@
import Head from 'next/head'
import { CallToAction } from '@/components/CallToAction'
import { Faqs } from '@/components/Faqs'
import { Footer } from '@/components/Footer'
import { Header } from '@/components/Header'
import { Hero } from '@/components/Hero'
import { Pricing } from '@/components/Pricing'
import { PrimaryFeatures } from '@/components/PrimaryFeatures'
import { Reviews } from '@/components/Reviews'
import { SecondaryFeatures } from '@/components/SecondaryFeatures'
export default function Home() {
return (
<>
<Head>
<title>Akkoma - Magically Expressive Social Media</title>
<meta
name="description"
content="Join an Akkoma instance today to start expressing yourself alongside a community of like-minded people."
/>
</Head>
<Header />
<main>
<Hero />
<PrimaryFeatures />
<SecondaryFeatures />
<CallToAction />
<Faqs />
</main>
<Footer />
</>
)
}

24
src/styles/tailwind.css Normal file
View File

@ -0,0 +1,24 @@
@font-face {
font-family: 'Inter';
font-weight: 100 900;
font-display: block;
font-style: normal;
font-named-instance: 'Regular';
src: url('/fonts/Inter-roman.var.woff2') format('woff2');
}
@font-face {
font-family: 'Inter';
font-weight: 100 900;
font-display: block;
font-style: italic;
font-named-instance: 'Italic';
src: url('/fonts/Inter-italic.var.woff2') format('woff2');
}
@tailwind base;
@tailwind components;
@tailwind utilities;
#__next {
min-height: 100%;
}

75
tailwind.config.js Normal file
View File

@ -0,0 +1,75 @@
const defaultTheme = require('tailwindcss/defaultTheme')
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{js,jsx}'],
theme: {
fontSize: {
xs: ['0.75rem', { lineHeight: '1rem' }],
sm: ['0.875rem', { lineHeight: '1.5rem' }],
base: ['1rem', { lineHeight: '1.5rem' }],
lg: ['1.125rem', { lineHeight: '2rem' }],
xl: ['1.25rem', { lineHeight: '1.75rem' }],
'2xl': ['1.5rem', { lineHeight: '2rem' }],
'3xl': ['2rem', { lineHeight: '3rem' }],
'4xl': ['2.5rem', { lineHeight: '3rem' }],
'5xl': ['3rem', { lineHeight: '1' }],
'6xl': ['3.75rem', { lineHeight: '1' }],
'7xl': ['4.5rem', { lineHeight: '1' }],
'8xl': ['6rem', { lineHeight: '1' }],
'9xl': ['8rem', { lineHeight: '1' }],
},
extend: {
animation: {
'fade-in': 'fade-in 0.5s linear forwards',
marquee: 'marquee var(--marquee-duration) linear infinite',
'spin-slow': 'spin 4s linear infinite',
'spin-slower': 'spin 6s linear infinite',
'spin-reverse': 'spin-reverse 1s linear infinite',
'spin-reverse-slow': 'spin-reverse 4s linear infinite',
'spin-reverse-slower': 'spin-reverse 6s linear infinite',
},
borderRadius: {
'4xl': '2rem',
'5xl': '2.5rem',
},
colors: ({ colors }) => ({
gray: colors.neutral,
blue: {
'1000': '#070e1b'
},
purple: {
900: '#593196',
1000: '#44247b',
}
}),
fontFamily: {
sans: ['Inter', ...defaultTheme.fontFamily.sans],
},
keyframes: {
'fade-in': {
from: {
opacity: 0,
},
to: {
opacity: 1,
},
},
marquee: {
'100%': {
transform: 'translateY(-50%)',
},
},
'spin-reverse': {
to: {
transform: 'rotate(-360deg)',
},
},
},
maxWidth: {
'2xl': '40rem',
},
},
},
plugins: [require('@tailwindcss/forms')],
}