mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 02:29:55 +02:00
feat(docs): refine product showcase and branding
This commit is contained in:
@@ -137,107 +137,6 @@ p {
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-header {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 100;
|
|
||||||
top: 16px;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
width: min(calc(100% - 32px), 1260px);
|
|
||||||
margin-inline: auto;
|
|
||||||
border: 1px solid rgba(220, 212, 224, 0.82);
|
|
||||||
border-radius: 18px;
|
|
||||||
background: rgba(251, 250, 252, 0.82);
|
|
||||||
box-shadow: 0 12px 40px rgba(42, 26, 49, 0.08);
|
|
||||||
backdrop-filter: blur(20px) saturate(1.4);
|
|
||||||
-webkit-backdrop-filter: blur(20px) saturate(1.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-inner {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr auto 1fr;
|
|
||||||
align-items: center;
|
|
||||||
height: 64px;
|
|
||||||
padding: 0 10px 0 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
width: max-content;
|
|
||||||
font-family: var(--font-display);
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: 750;
|
|
||||||
letter-spacing: -0.04em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-mark-shell {
|
|
||||||
display: grid;
|
|
||||||
width: 38px;
|
|
||||||
height: 38px;
|
|
||||||
place-items: center;
|
|
||||||
border: 1px solid #eadcf1;
|
|
||||||
border-radius: 11px;
|
|
||||||
background: white;
|
|
||||||
box-shadow: 0 5px 15px rgba(105, 42, 145, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-mark-shell svg {
|
|
||||||
width: 27px;
|
|
||||||
height: 27px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-name {
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-nav {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 3px;
|
|
||||||
padding: 4px;
|
|
||||||
border-radius: 13px;
|
|
||||||
background: rgba(239, 235, 241, 0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-nav a {
|
|
||||||
padding: 7px 14px;
|
|
||||||
border-radius: 10px;
|
|
||||||
color: var(--ink-soft);
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 650;
|
|
||||||
transition: background 160ms ease, color 160ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-nav a:hover {
|
|
||||||
background: white;
|
|
||||||
color: var(--ink);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-github {
|
|
||||||
justify-self: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-button {
|
|
||||||
display: none;
|
|
||||||
width: 42px;
|
|
||||||
height: 42px;
|
|
||||||
place-items: center;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 11px;
|
|
||||||
background: var(--surface-soft);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-button svg {
|
|
||||||
width: 21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-nav {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
min-height: 52px;
|
min-height: 52px;
|
||||||
@@ -322,4 +221,3 @@ p {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-mark svg {
|
.footer-mark img {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
@@ -100,4 +100,3 @@
|
|||||||
.footer-bottom p {
|
.footer-bottom p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,29 @@
|
|||||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<rect width="64" height="64" rx="16" fill="#FBF7FF"/>
|
<rect x="40" y="40" width="944" height="944" rx="210" fill="#FFFFFF" stroke="#E9E7F0" stroke-width="8"/>
|
||||||
<path d="M16 12h8.2c2.1 0 3.8 1.7 3.8 3.8v20.4c0 7 4.8 12.2 11.5 12.2S51 43.2 51 36.2V15.8c0-2.1 1.7-3.8 3.8-3.8H58v24.4C58 47.7 50 56 39.5 56S21 47.7 21 36.4V24h-3v-5h-2v-7Z" fill="url(#a)"/>
|
|
||||||
<path d="M39.5 26.5c-2.5 3.3-6.5 8.6-6.5 12.4 0 4 2.8 7.1 6.5 7.1s6.5-3.1 6.5-7.1c0-3.8-4-9.1-6.5-12.4Z" fill="url(#b)"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M236.68 148H338.36C366.24 148 387.56 170.96 387.56 198.84V564.56C387.56 597.36 372.8 620.32 372.8 646.56C372.8 725.28 436.76 787.6 522.04 787.6C607.32 787.6 668 725.28 668 646.56C668 620.32 656.52 597.36 656.52 564.56V198.84C656.52 170.96 677.84 148 705.72 148H781.16C817.24 148 846.76 177.52 846.76 213.6V564.56C846.76 738.4 704.08 879.44 522.04 879.44C340 879.44 194.04 738.4 194.04 564.56V374.32H220.28V305.44C195.68 305.44 176 297.24 176 280.84V246.4C176 231.64 187.48 220.16 202.24 220.16H236.68V148ZM256.36 239.84C251.44 239.84 248.16 244.76 248.16 249.68V275.92C248.16 282.48 253.08 285.76 259.64 285.76H282.6C289.16 285.76 292.44 280.84 292.44 274.28V251.32C292.44 244.76 287.52 239.84 280.96 239.84H256.36Z" fill="url(#paint0_linear_11_12)"/>
|
||||||
<path d="M51 12h7v7l-7-7Z" fill="#E7CBFF"/>
|
<path d="M520.4 431.72C495.8 464.52 443.32 530.12 420.36 577.68C390.84 636.72 403.96 699.04 446.6 731.84C487.6 758.08 549.92 758.08 592.56 730.2C633.56 700.68 646.68 636.72 620.44 577.68C597.48 530.12 546.64 464.52 520.4 431.72Z" fill="url(#paint1_linear_11_12)"/>
|
||||||
<defs>
|
<mask id="mask0_11_12" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="176" y="148" width="671" height="732">
|
||||||
<linearGradient id="a" x1="16" y1="12" x2="59" y2="51" gradientUnits="userSpaceOnUse"><stop stop-color="#B45CFA"/><stop offset="1" stop-color="#7828ED"/></linearGradient>
|
<path d="M236.68 148H338.36C366.24 148 387.56 170.96 387.56 198.84V564.56C387.56 597.36 372.8 620.32 372.8 646.56C372.8 725.28 436.76 787.6 522.04 787.6C607.32 787.6 668 725.28 668 646.56C668 620.32 656.52 597.36 656.52 564.56V198.84C656.52 170.96 677.84 148 705.72 148H781.16C817.24 148 846.76 177.52 846.76 213.6V564.56C846.76 738.4 704.08 879.44 522.04 879.44C340 879.44 194.04 738.4 194.04 564.56V374.32H220.28V305.44C195.68 305.44 176 297.24 176 280.84V246.4C176 231.64 187.48 220.16 202.24 220.16H236.68V148ZM256.36 239.84C251.44 239.84 248.16 244.76 248.16 249.68V275.92C248.16 282.48 253.08 285.76 259.64 285.76H282.6C289.16 285.76 292.44 280.84 292.44 274.28V251.32C292.44 244.76 287.52 239.84 280.96 239.84H256.36Z" fill="white"/>
|
||||||
<linearGradient id="b" x1="33" y1="27" x2="47" y2="43" gradientUnits="userSpaceOnUse"><stop stop-color="#B45CFA"/><stop offset="1" stop-color="#7828ED"/></linearGradient>
|
</mask>
|
||||||
</defs>
|
<g mask="url(#mask0_11_12)">
|
||||||
|
<path d="M688 148H782C832 148 842 171.8 847.48 210V303.68L688 148Z" fill="url(#paint2_linear_11_12)"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_11_12" x1="176" y1="148" x2="904.706" y2="816.252" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#A855F7"/>
|
||||||
|
<stop offset="0.48" stop-color="#9D4DF4"/>
|
||||||
|
<stop offset="1" stop-color="#7C2AEF"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_11_12" x1="404.439" y1="431.72" x2="707.314" y2="649.286" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#A855F7"/>
|
||||||
|
<stop offset="0.48" stop-color="#9D4DF4"/>
|
||||||
|
<stop offset="1" stop-color="#7C2AEF"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint2_linear_11_12" x1="683.48" y1="144.6" x2="793.636" y2="306.833" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#F2DDFF"/>
|
||||||
|
<stop offset="1" stop-color="#C084FC"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 893 B After Width: | Height: | Size: 2.9 KiB |
@@ -3,10 +3,12 @@ import type { ReactNode } from "react";
|
|||||||
import { SiteFooter } from "@/components/site-footer";
|
import { SiteFooter } from "@/components/site-footer";
|
||||||
import { SiteHeader } from "@/components/site-header";
|
import { SiteHeader } from "@/components/site-header";
|
||||||
import "./base.css";
|
import "./base.css";
|
||||||
|
import "../components/header.css";
|
||||||
import "./home.css";
|
import "./home.css";
|
||||||
import "./footer.css";
|
import "./footer.css";
|
||||||
import "./privacy/privacy-document.css";
|
import "./privacy/privacy-document.css";
|
||||||
import "../components/hero-scene.css";
|
import "../components/hero-scene.css";
|
||||||
|
import "../components/hero-device.css";
|
||||||
import "../components/transfer-flow.css";
|
import "../components/transfer-flow.css";
|
||||||
import "../components/invitation-scene.css";
|
import "../components/invitation-scene.css";
|
||||||
import "../components/approval-scene.css";
|
import "../components/approval-scene.css";
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="section invitation-section">
|
<section id="invitations" className="section invitation-section">
|
||||||
<div className="page-shell">
|
<div className="page-shell">
|
||||||
<Reveal className="section-heading section-heading-split">
|
<Reveal className="section-heading section-heading-split">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
backdrop-filter: blur(14px);
|
backdrop-filter: blur(14px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.privacy-mark-card > svg {
|
.privacy-mark-card > img {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
width: 112px;
|
width: 112px;
|
||||||
@@ -657,4 +657,3 @@
|
|||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,51 +37,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 920px) {
|
@media (max-width: 920px) {
|
||||||
.desktop-nav,
|
|
||||||
.header-github {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-inner {
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-button {
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-nav {
|
|
||||||
display: grid;
|
|
||||||
max-height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 0 12px;
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
transition: max-height 250ms ease, padding 250ms ease, opacity 180ms ease, visibility 250ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-nav.is-open {
|
|
||||||
max-height: 280px;
|
|
||||||
padding: 4px 12px 12px;
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-nav a {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 12px 10px;
|
|
||||||
border-top: 1px solid var(--line);
|
|
||||||
color: var(--ink-soft);
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 650;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-nav svg {
|
|
||||||
width: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-section {
|
.hero-section {
|
||||||
padding-top: 128px;
|
padding-top: 128px;
|
||||||
}
|
}
|
||||||
@@ -155,26 +110,6 @@
|
|||||||
width: min(calc(100% - 32px), var(--shell));
|
width: min(calc(100% - 32px), var(--shell));
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-header {
|
|
||||||
top: 10px;
|
|
||||||
width: calc(100% - 20px);
|
|
||||||
border-radius: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-inner {
|
|
||||||
height: 58px;
|
|
||||||
padding-left: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-name {
|
|
||||||
font-size: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-mark-shell {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-section {
|
.hero-section {
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
padding: 115px 0 72px;
|
padding: 115px 0 72px;
|
||||||
|
|||||||
@@ -1,64 +1,43 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
type BrandMarkProps = {
|
type BrandAssetProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function BrandMark({ className, title }: BrandMarkProps) {
|
export function BrandMark({ className, title }: BrandAssetProps) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<Image
|
||||||
className={className}
|
className={className}
|
||||||
viewBox="0 0 64 64"
|
src="/brand-mark.svg"
|
||||||
fill="none"
|
width={1024}
|
||||||
role={title ? "img" : undefined}
|
height={1024}
|
||||||
|
alt={title ?? ""}
|
||||||
aria-hidden={title ? undefined : true}
|
aria-hidden={title ? undefined : true}
|
||||||
aria-label={title}
|
unoptimized
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M11 8h10.6a4.8 4.8 0 0 1 4.8 4.8v25.4c0 8.7 6.1 15.2 14.5 15.2 8.3 0 14.1-6.5 14.1-15.2V12.8A4.8 4.8 0 0 1 59.8 8H62v30.4C62 52.5 53.3 61 40.9 61 28.3 61 19 52.5 19 38.4V23h-3.5v-6.4H11V8Z"
|
|
||||||
fill="url(#brand-mark-gradient)"
|
|
||||||
/>
|
/>
|
||||||
<path
|
);
|
||||||
d="M40.8 25.9c-3.1 4.1-8.2 10.8-8.2 15.5 0 5.1 3.6 8.9 8.2 8.9 4.8 0 8.3-3.8 8.3-8.9 0-4.7-5.2-11.4-8.3-15.5Z"
|
}
|
||||||
fill="url(#brand-drop-gradient)"
|
|
||||||
|
export function AppIcon({ className, title }: BrandAssetProps) {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
className={className}
|
||||||
|
src="/icon.svg"
|
||||||
|
width={1024}
|
||||||
|
height={1024}
|
||||||
|
alt={title ?? ""}
|
||||||
|
aria-hidden={title ? undefined : true}
|
||||||
|
unoptimized
|
||||||
/>
|
/>
|
||||||
<path d="M54.9 8h7v7l-7-7Z" fill="#E8CDFF" />
|
|
||||||
<defs>
|
|
||||||
<linearGradient
|
|
||||||
id="brand-mark-gradient"
|
|
||||||
x1="11"
|
|
||||||
y1="8"
|
|
||||||
x2="64"
|
|
||||||
y2="55"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
>
|
|
||||||
<stop stopColor="#B45CFA" />
|
|
||||||
<stop offset="0.5" stopColor="#9D4DF4" />
|
|
||||||
<stop offset="1" stopColor="#7828ED" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
id="brand-drop-gradient"
|
|
||||||
x1="32"
|
|
||||||
y1="26"
|
|
||||||
x2="51"
|
|
||||||
y2="47"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
>
|
|
||||||
<stop stopColor="#C06CFF" />
|
|
||||||
<stop offset="1" stopColor="#7828ED" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Brand({ compact = false }: { compact?: boolean }) {
|
export function Brand({ compact = false }: { compact?: boolean }) {
|
||||||
return (
|
return (
|
||||||
<Link className="brand" href="/" aria-label="VniDrop home">
|
<Link className="brand" href="/" aria-label="VniDrop home">
|
||||||
<span className="brand-mark-shell">
|
<BrandMark className="brand-mark-image" />
|
||||||
<BrandMark />
|
|
||||||
</span>
|
|
||||||
{!compact && <span className="brand-name">VniDrop</span>}
|
{!compact && <span className="brand-name">VniDrop</span>}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
|||||||
115
docs/components/header.css
Normal file
115
docs/components/header.css
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
.site-header {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 220;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 72px;
|
||||||
|
border-bottom: 1px solid rgba(224, 217, 228, 0.76);
|
||||||
|
background: rgba(251, 250, 252, 0.88);
|
||||||
|
box-shadow: 0 8px 30px rgba(42, 26, 49, 0.035);
|
||||||
|
backdrop-filter: blur(20px) saturate(1.3);
|
||||||
|
-webkit-backdrop-filter: blur(20px) saturate(1.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-inner {
|
||||||
|
display: flex;
|
||||||
|
height: 72px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 3px;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-mark-image {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
object-fit: contain;
|
||||||
|
filter: drop-shadow(0 7px 14px rgba(126, 42, 189, 0.14));
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-name {
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 19px;
|
||||||
|
font-weight: 780;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -0.045em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-github-button {
|
||||||
|
display: inline-flex;
|
||||||
|
min-height: 40px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 0 14px;
|
||||||
|
border: 1px solid #28232b;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--ink);
|
||||||
|
box-shadow: 0 8px 22px rgba(23, 20, 25, 0.13), inset 0 1px rgba(255, 255, 255, 0.1);
|
||||||
|
color: white;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 680;
|
||||||
|
line-height: 1;
|
||||||
|
transition: background 160ms ease, border-color 160ms ease, box-shadow 160ms ease,
|
||||||
|
transform 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-github-button:hover {
|
||||||
|
border-color: #403944;
|
||||||
|
background: #29242d;
|
||||||
|
box-shadow: 0 10px 26px rgba(23, 20, 25, 0.17), inset 0 1px rgba(255, 255, 255, 0.12);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-github-button svg {
|
||||||
|
width: 17px;
|
||||||
|
height: 16px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
.site-header,
|
||||||
|
.header-inner {
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-mark-image {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-name {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-github-button {
|
||||||
|
min-height: 38px;
|
||||||
|
gap: 7px;
|
||||||
|
padding-inline: 12px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 360px) {
|
||||||
|
.brand-mark-image {
|
||||||
|
width: 41px;
|
||||||
|
height: 41px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-name {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-github-button {
|
||||||
|
min-height: 36px;
|
||||||
|
padding-inline: 10px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
490
docs/components/hero-device.css
Normal file
490
docs/components/hero-device.css
Normal file
@@ -0,0 +1,490 @@
|
|||||||
|
/* Receiver hardware, status overlays, and responsive stage composition */
|
||||||
|
.receiver-phone-shell {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 5;
|
||||||
|
top: 17%;
|
||||||
|
right: 1.5%;
|
||||||
|
width: 23.5%;
|
||||||
|
aspect-ratio: 0.49;
|
||||||
|
transform: translate(
|
||||||
|
calc(var(--pointer-x) * 7px),
|
||||||
|
calc(var(--pointer-y) * 5px)
|
||||||
|
)
|
||||||
|
rotateY(calc(var(--pointer-x) * -1.6deg))
|
||||||
|
rotateX(calc(var(--pointer-y) * 1.3deg));
|
||||||
|
transform-origin: center;
|
||||||
|
transition: transform 180ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-phone-frame {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
padding: 7px;
|
||||||
|
border: 1px solid #bdb7c1;
|
||||||
|
border-radius: 38px;
|
||||||
|
background: linear-gradient(145deg, #e7e4e9, #aaa4ae 42%, #f3f1f4 72%, #aaa3ae);
|
||||||
|
box-shadow:
|
||||||
|
0 38px 85px rgba(43, 27, 51, 0.22),
|
||||||
|
0 9px 25px rgba(43, 27, 51, 0.12),
|
||||||
|
inset 0 0 0 1px rgba(255, 255, 255, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-phone-frame::before {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 3;
|
||||||
|
inset: 2px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.7);
|
||||||
|
border-radius: 35px;
|
||||||
|
content: "";
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-side-button {
|
||||||
|
position: absolute;
|
||||||
|
right: -3px;
|
||||||
|
width: 3px;
|
||||||
|
border-radius: 0 2px 2px 0;
|
||||||
|
background: #98929d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-side-button-one { top: 24%; height: 14%; }
|
||||||
|
.phone-side-button-two { top: 42%; height: 21%; }
|
||||||
|
|
||||||
|
.phone-screen {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 31px;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 80% 18%, rgba(192, 132, 252, 0.12), transparent 28%),
|
||||||
|
#faf9fb;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(26, 22, 29, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-screen::after {
|
||||||
|
position: absolute;
|
||||||
|
top: -28%;
|
||||||
|
left: -42%;
|
||||||
|
width: 82%;
|
||||||
|
height: 130%;
|
||||||
|
background: linear-gradient(110deg, transparent 35%, rgba(255, 255, 255, 0.32), transparent 66%);
|
||||||
|
content: "";
|
||||||
|
pointer-events: none;
|
||||||
|
transform: rotate(8deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-status-bar {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
align-items: center;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0 10px;
|
||||||
|
color: #2e2931;
|
||||||
|
font-size: 6px;
|
||||||
|
font-weight: 760;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-island {
|
||||||
|
width: 42px;
|
||||||
|
height: 12px;
|
||||||
|
justify-self: center;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #171419;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-signal {
|
||||||
|
justify-self: end;
|
||||||
|
font-size: 5px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-app-bar {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 26px 1fr 25px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px 11px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-brand-mark {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-app-bar strong {
|
||||||
|
color: #29242c;
|
||||||
|
font-size: 9px;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-app-bar > span {
|
||||||
|
display: grid;
|
||||||
|
width: 23px;
|
||||||
|
height: 23px;
|
||||||
|
place-items: center;
|
||||||
|
border: 1px solid #e9e3ec;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: white;
|
||||||
|
color: var(--brand-700);
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-app-bar svg { width: 11px; }
|
||||||
|
|
||||||
|
.phone-transfer-card {
|
||||||
|
display: grid;
|
||||||
|
margin: 6px 10px 0;
|
||||||
|
padding: 11px 9px 10px;
|
||||||
|
border: 1px solid #e6e0e9;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 9px 25px rgba(48, 33, 55, 0.055);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-file-art {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
margin: 0 auto 8px;
|
||||||
|
place-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 13px;
|
||||||
|
background:
|
||||||
|
linear-gradient(145deg, rgba(255, 255, 255, 0.2), transparent 48%),
|
||||||
|
linear-gradient(135deg, #c084fc, #7c2aef);
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 10px 22px rgba(132, 47, 238, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-file-art::after {
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
right: -8px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background: rgba(235, 211, 255, 0.65);
|
||||||
|
content: "";
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-file-art svg { width: 21px; }
|
||||||
|
|
||||||
|
.phone-transfer-card small {
|
||||||
|
color: #9a8fa0;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 5px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.09em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-transfer-card strong {
|
||||||
|
margin-top: 3px;
|
||||||
|
color: #29232d;
|
||||||
|
font-size: 9px;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-transfer-card > span {
|
||||||
|
color: #8d8391;
|
||||||
|
font-size: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-state-area {
|
||||||
|
position: relative;
|
||||||
|
height: 88px;
|
||||||
|
margin: 9px 10px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 13px;
|
||||||
|
background: #f2eff4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-state {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-symbol {
|
||||||
|
display: grid;
|
||||||
|
width: 31px;
|
||||||
|
height: 31px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #e5d3f3;
|
||||||
|
color: var(--brand-700);
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-symbol.is-success {
|
||||||
|
background: #d8f4e7;
|
||||||
|
color: #188457;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-symbol svg { width: 15px; }
|
||||||
|
|
||||||
|
.phone-state strong {
|
||||||
|
color: #39313d;
|
||||||
|
font-size: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-state small {
|
||||||
|
color: #8d8291;
|
||||||
|
font-size: 5.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-percentage {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
color: var(--brand-700);
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 740;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -0.08em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-percentage span {
|
||||||
|
margin-left: 1px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-home-indicator {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
left: 50%;
|
||||||
|
width: 42px;
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #27222a;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-route-card,
|
||||||
|
.hero-verified-card {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 8;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid rgba(214, 204, 220, 0.92);
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
box-shadow: 0 15px 45px rgba(49, 27, 61, 0.12);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-route-card {
|
||||||
|
top: 3%;
|
||||||
|
left: 36%;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 176px;
|
||||||
|
padding: 9px 10px;
|
||||||
|
border-radius: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-pulse {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border: 2px solid #def7eb;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #2fbc7a;
|
||||||
|
box-shadow: 0 0 0 4px rgba(47, 188, 122, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-route-card > span:nth-child(2),
|
||||||
|
.hero-verified-card > span:nth-child(2) {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-route-card small {
|
||||||
|
color: #978d9b;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 5px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-route-card strong,
|
||||||
|
.hero-verified-card strong {
|
||||||
|
color: #342d37;
|
||||||
|
font-size: 7.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-latency {
|
||||||
|
margin-left: auto;
|
||||||
|
color: var(--brand-700);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 6px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-verified-card {
|
||||||
|
right: 0;
|
||||||
|
bottom: 12%;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 9px 11px 9px 8px;
|
||||||
|
border-radius: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-verified-card > span:first-child {
|
||||||
|
display: grid;
|
||||||
|
width: 31px;
|
||||||
|
height: 31px;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #dcf6e9;
|
||||||
|
color: #1b8d5d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-verified-card svg { width: 16px; }
|
||||||
|
|
||||||
|
.hero-verified-card small {
|
||||||
|
color: #8e8492;
|
||||||
|
font-size: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-privacy-rail {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
bottom: 3.5%;
|
||||||
|
left: 8%;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 9px;
|
||||||
|
padding: 7px 10px;
|
||||||
|
border: 1px solid rgba(217, 208, 222, 0.82);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
color: #786e7c;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 5.5px;
|
||||||
|
font-weight: 750;
|
||||||
|
letter-spacing: 0.035em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-privacy-rail span {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-privacy-rail svg {
|
||||||
|
width: 9px;
|
||||||
|
color: var(--brand-700);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-privacy-rail i {
|
||||||
|
width: 3px;
|
||||||
|
height: 3px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #c4b9c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
.hero-stage {
|
||||||
|
aspect-ratio: 1.02;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-stage-grid {
|
||||||
|
inset: 2% -2% 2%;
|
||||||
|
border-radius: 30px;
|
||||||
|
background-size: 22px 22px, 22px 22px, auto, auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-product-shell {
|
||||||
|
top: 12%;
|
||||||
|
left: -2%;
|
||||||
|
width: 70%;
|
||||||
|
height: 56%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-phone-shell {
|
||||||
|
top: 22%;
|
||||||
|
right: -1%;
|
||||||
|
width: 26%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-app-layout { grid-template-columns: 42px 1fr; }
|
||||||
|
.desktop-transfer-view { padding: 11px 10px 9px; }
|
||||||
|
.desktop-sidebar { gap: 4px; padding-top: 7px; }
|
||||||
|
.product-brand-mark { width: 29px; height: 29px; }
|
||||||
|
.desktop-sidebar-item { width: 26px; height: 26px; }
|
||||||
|
.desktop-sidebar-item svg { width: 12px; }
|
||||||
|
.file-collection-card { grid-template-columns: 51px 1fr; gap: 7px; }
|
||||||
|
.file-collage { width: 51px; height: 45px; }
|
||||||
|
.collection-menu { display: none; }
|
||||||
|
.receiver-state-stack { width: 72px; }
|
||||||
|
.desktop-transfer-foot { display: none; }
|
||||||
|
|
||||||
|
.approval-knock-card {
|
||||||
|
right: -6%;
|
||||||
|
bottom: -22%;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-route-card {
|
||||||
|
top: 1%;
|
||||||
|
left: 27%;
|
||||||
|
min-width: 156px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-verified-card { right: -1%; bottom: 8%; }
|
||||||
|
.hero-privacy-rail { bottom: 0; left: 3%; }
|
||||||
|
.stage-coordinate-side { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.desktop-window-bar {
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-title { display: none; }
|
||||||
|
.desktop-app-layout { height: calc(100% - 28px); }
|
||||||
|
.desktop-view-heading { margin-bottom: 7px; }
|
||||||
|
.desktop-view-heading strong { font-size: 12px; }
|
||||||
|
.file-collection-card { padding: 7px; }
|
||||||
|
.receiver-section-heading { margin-top: 8px; }
|
||||||
|
.desktop-receiver-row { grid-template-columns: 27px 1fr; }
|
||||||
|
.receiver-avatar { width: 26px; height: 26px; }
|
||||||
|
.receiver-state-stack { display: none; }
|
||||||
|
.receiver-progress-track { left: 43px; }
|
||||||
|
.approval-knock-card { bottom: -27%; width: 184px; padding: 9px; }
|
||||||
|
.approval-knock-card p { margin: 6px 0; }
|
||||||
|
|
||||||
|
.phone-app-bar { grid-template-columns: 22px 1fr 22px; padding-inline: 7px; }
|
||||||
|
.phone-brand-mark { width: 22px; height: 22px; }
|
||||||
|
.phone-transfer-card { margin-inline: 7px; padding-inline: 7px; }
|
||||||
|
.phone-file-art { width: 38px; height: 38px; }
|
||||||
|
.phone-state-area { height: 73px; margin-inline: 7px; }
|
||||||
|
.state-symbol { width: 27px; height: 27px; margin-bottom: 3px; }
|
||||||
|
.transfer-percentage { font-size: 20px; }
|
||||||
|
|
||||||
|
.hero-route-card {
|
||||||
|
left: 20%;
|
||||||
|
min-width: 142px;
|
||||||
|
padding: 7px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-latency { display: none; }
|
||||||
|
.hero-verified-card { padding: 7px; }
|
||||||
|
.hero-verified-card > span:first-child { width: 27px; height: 27px; }
|
||||||
|
|
||||||
|
.hero-privacy-rail {
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-privacy-rail span:nth-of-type(3),
|
||||||
|
.hero-privacy-rail i:nth-of-type(2) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import type { CSSProperties, PointerEvent } from "react";
|
import type { CSSProperties, PointerEvent } from "react";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
|
import { motion, useReducedMotion } from "motion/react";
|
||||||
|
import { BrandMark } from "@/components/brand";
|
||||||
import { Icon } from "@/components/icons";
|
import { Icon } from "@/components/icons";
|
||||||
|
|
||||||
type StageStyle = CSSProperties & {
|
type StageStyle = CSSProperties & {
|
||||||
@@ -9,12 +11,16 @@ type StageStyle = CSSProperties & {
|
|||||||
"--pointer-y": string;
|
"--pointer-y": string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cycle = 10.5;
|
||||||
|
const rest = 1.2;
|
||||||
|
|
||||||
export function HeroIllustration() {
|
export function HeroIllustration() {
|
||||||
const stageRef = useRef<HTMLDivElement>(null);
|
const stageRef = useRef<HTMLDivElement>(null);
|
||||||
|
const reduceMotion = useReducedMotion();
|
||||||
|
|
||||||
const updateParallax = (event: PointerEvent<HTMLDivElement>) => {
|
const updateParallax = (event: PointerEvent<HTMLDivElement>) => {
|
||||||
const stage = stageRef.current;
|
const stage = stageRef.current;
|
||||||
if (!stage || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
if (!stage || reduceMotion) return;
|
||||||
const bounds = stage.getBoundingClientRect();
|
const bounds = stage.getBoundingClientRect();
|
||||||
const x = ((event.clientX - bounds.left) / bounds.width - 0.5) * 2;
|
const x = ((event.clientX - bounds.left) / bounds.width - 0.5) * 2;
|
||||||
const y = ((event.clientY - bounds.top) / bounds.height - 0.5) * 2;
|
const y = ((event.clientY - bounds.top) / bounds.height - 0.5) * 2;
|
||||||
@@ -27,6 +33,8 @@ export function HeroIllustration() {
|
|||||||
stageRef.current?.style.setProperty("--pointer-y", "0");
|
stageRef.current?.style.setProperty("--pointer-y", "0");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const repeating = { duration: cycle, repeat: Infinity, repeatDelay: rest };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<figure className="hero-visual">
|
<figure className="hero-visual">
|
||||||
<div
|
<div
|
||||||
@@ -37,179 +45,341 @@ export function HeroIllustration() {
|
|||||||
onPointerLeave={resetParallax}
|
onPointerLeave={resetParallax}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<div className="hero-grid" />
|
<div className="hero-stage-grid" />
|
||||||
<div className="hero-glow hero-glow-one" />
|
<div className="hero-stage-glow" />
|
||||||
<div className="hero-glow hero-glow-two" />
|
<span className="stage-coordinate stage-coordinate-top">NODE / SEND · 01</span>
|
||||||
<div className="hero-status hero-status-secure">
|
<span className="stage-coordinate stage-coordinate-side">SECURE CHANNEL</span>
|
||||||
<span className="status-icon">
|
|
||||||
<Icon name="lock" />
|
<div className="desktop-product-shell">
|
||||||
</span>
|
<div className="desktop-product-window">
|
||||||
<span>
|
<div className="desktop-window-bar">
|
||||||
<strong>End-to-end encrypted</strong>
|
<span className="window-controls"><i /><i /><i /></span>
|
||||||
<small>Authenticated connection</small>
|
<span className="window-title">VniDrop · Send</span>
|
||||||
</span>
|
<span className="window-security"><Icon name="lock" /> Encrypted</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="hero-status hero-status-route">
|
|
||||||
<span className="status-pulse" />
|
<div className="desktop-app-layout">
|
||||||
Direct route found
|
<aside className="desktop-sidebar">
|
||||||
|
<BrandMark className="product-brand-mark" />
|
||||||
|
<span className="desktop-sidebar-item is-active"><Icon name="file" /></span>
|
||||||
|
<span className="desktop-sidebar-item"><Icon name="devices" /></span>
|
||||||
|
<span className="desktop-sidebar-item"><Icon name="shield" /></span>
|
||||||
|
<span className="desktop-sidebar-spacer" />
|
||||||
|
<span className="desktop-profile">AH</span>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<div className="desktop-transfer-view">
|
||||||
|
<div className="desktop-view-heading">
|
||||||
|
<div>
|
||||||
|
<small>OUTGOING TRANSFER</small>
|
||||||
|
<strong>Summer archive</strong>
|
||||||
|
</div>
|
||||||
|
<span className="sharing-pill"><i /> Sharing</span>
|
||||||
</div>
|
</div>
|
||||||
<svg className="hero-scene" viewBox="0 0 760 620">
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="hero-purple" x1="240" y1="90" x2="620" y2="520">
|
|
||||||
<stop stopColor="#C16BFF" />
|
|
||||||
<stop offset="0.48" stopColor="#A855F7" />
|
|
||||||
<stop offset="1" stopColor="#6F27E9" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="hero-screen" x1="88" y1="118" x2="342" y2="345">
|
|
||||||
<stop stopColor="#25202C" />
|
|
||||||
<stop offset="1" stopColor="#151319" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="hero-phone" x1="540" y1="160" x2="692" y2="465">
|
|
||||||
<stop stopColor="#2A2530" />
|
|
||||||
<stop offset="1" stopColor="#141217" />
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="hero-orb">
|
|
||||||
<stop stopColor="#E3BDFF" stopOpacity="0.9" />
|
|
||||||
<stop offset="0.45" stopColor="#A855F7" stopOpacity="0.45" />
|
|
||||||
<stop offset="1" stopColor="#A855F7" stopOpacity="0" />
|
|
||||||
</radialGradient>
|
|
||||||
<filter id="hero-shadow" x="-30%" y="-30%" width="160%" height="180%">
|
|
||||||
<feDropShadow dx="0" dy="20" stdDeviation="18" floodColor="#3F2454" floodOpacity="0.16" />
|
|
||||||
</filter>
|
|
||||||
<filter id="hero-glow-filter" x="-100%" y="-100%" width="300%" height="300%">
|
|
||||||
<feGaussianBlur stdDeviation="12" />
|
|
||||||
</filter>
|
|
||||||
<clipPath id="laptop-screen-clip">
|
|
||||||
<rect x="82" y="132" width="264" height="176" rx="12" />
|
|
||||||
</clipPath>
|
|
||||||
<clipPath id="phone-screen-clip">
|
|
||||||
<rect x="548" y="171" width="136" height="279" rx="25" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
|
|
||||||
<g className="scene-orbits">
|
<div className="file-collection-card">
|
||||||
<ellipse cx="385" cy="325" rx="315" ry="216" fill="none" stroke="#B969F8" strokeOpacity="0.14" />
|
<div className="file-collage" aria-hidden="true">
|
||||||
<ellipse cx="385" cy="325" rx="245" ry="169" fill="none" stroke="#B969F8" strokeOpacity="0.12" strokeDasharray="8 14" />
|
<span /><span /><span /><span />
|
||||||
<circle cx="670" cy="215" r="5" fill="#A855F7" />
|
</div>
|
||||||
<circle cx="117" cy="455" r="4" fill="#C98AFD" />
|
<div className="file-collection-copy">
|
||||||
<path d="m704 345 4 10 10 4-10 4-4 10-4-10-10-4 10-4Z" fill="#D9AEFF" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g className="scene-laptop" filter="url(#hero-shadow)">
|
|
||||||
<rect x="69" y="117" width="290" height="207" rx="19" fill="#E8E4EB" stroke="#D6CFDA" strokeWidth="2" />
|
|
||||||
<rect x="80" y="129" width="268" height="183" rx="13" fill="url(#hero-screen)" />
|
|
||||||
<g clipPath="url(#laptop-screen-clip)">
|
|
||||||
<circle cx="208" cy="235" r="108" fill="#A855F7" opacity="0.07" />
|
|
||||||
<path d="M80 278c62-45 99-24 141-60 39-34 70-39 127-31v125H80Z" fill="#A855F7" opacity="0.09" />
|
|
||||||
<rect x="101" y="151" width="101" height="13" rx="6.5" fill="#3E3745" />
|
|
||||||
<rect x="101" y="175" width="67" height="7" rx="3.5" fill="#5E5366" />
|
|
||||||
<g className="laptop-files">
|
|
||||||
<rect x="118" y="205" width="76" height="79" rx="10" fill="#F8F2FC" stroke="#C98AFD" />
|
|
||||||
<path d="M173 205h21v21Z" fill="#E3C3FA" />
|
|
||||||
<rect x="129" y="219" width="24" height="24" rx="6" fill="#E8D0FB" />
|
|
||||||
<path d="m135 238 7-8 5 5 4-4 6 7Z" fill="#A855F7" opacity="0.75" />
|
|
||||||
<rect x="129" y="253" width="46" height="6" rx="3" fill="#C3B6CB" />
|
|
||||||
<rect x="129" y="265" width="34" height="5" rx="2.5" fill="#DDD4E2" />
|
|
||||||
<rect x="181" y="223" width="82" height="68" rx="10" fill="#2F2935" stroke="#574D5E" />
|
|
||||||
<path d="M242 223h21v21Z" fill="#4F4557" />
|
|
||||||
<circle cx="205" cy="245" r="9" fill="#A855F7" opacity="0.75" />
|
|
||||||
<rect x="195" y="264" width="49" height="6" rx="3" fill="#63586A" />
|
|
||||||
<rect x="195" y="276" width="34" height="5" rx="2.5" fill="#4D4453" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path d="M46 324h336l-20 23a20 20 0 0 1-15 6H81a20 20 0 0 1-15-7Z" fill="#D9D3DD" stroke="#CAC1CE" strokeWidth="2" />
|
|
||||||
<path d="M183 324h62l-7 12h-48Z" fill="#C1B8C6" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g className="transfer-conduit">
|
|
||||||
<path
|
|
||||||
className="conduit-glow"
|
|
||||||
d="M284 358c23 134 225 151 279 35"
|
|
||||||
fill="none"
|
|
||||||
stroke="#B65DF9"
|
|
||||||
strokeOpacity="0.2"
|
|
||||||
strokeWidth="34"
|
|
||||||
strokeLinecap="round"
|
|
||||||
filter="url(#hero-glow-filter)"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M284 358c23 134 225 151 279 35"
|
|
||||||
fill="none"
|
|
||||||
stroke="#ECE3F1"
|
|
||||||
strokeWidth="19"
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
className="conduit-energy"
|
|
||||||
d="M284 358c23 134 225 151 279 35"
|
|
||||||
fill="none"
|
|
||||||
stroke="url(#hero-purple)"
|
|
||||||
strokeWidth="7"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeDasharray="2 17"
|
|
||||||
/>
|
|
||||||
<circle cx="284" cy="358" r="25" fill="#F8F2FC" stroke="#C98AFD" strokeWidth="2" />
|
|
||||||
<circle cx="284" cy="358" r="13" fill="#A855F7" opacity="0.15" />
|
|
||||||
<path d="m276 358 7 7 11-14" fill="none" stroke="#9333EA" strokeWidth="3" strokeLinecap="round" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g className="approval-gate" filter="url(#hero-shadow)">
|
|
||||||
<rect x="365" y="414" width="151" height="58" rx="18" fill="#FEFCFF" stroke="#DFCDEB" />
|
|
||||||
<circle cx="393" cy="443" r="15" fill="#F0DDFE" />
|
|
||||||
<path d="M393 433.5 385.5 437v5.3c0 4.5 3.2 7.6 7.5 8.9 4.3-1.3 7.5-4.4 7.5-8.9V437Z" fill="#A855F7" />
|
|
||||||
<path d="m389.5 442 2.2 2.2 4.5-4.6" fill="none" stroke="white" strokeWidth="1.8" strokeLinecap="round" />
|
|
||||||
<text x="418" y="439" fill="#201B24" fontSize="12" fontWeight="700">Approved</text>
|
|
||||||
<text x="418" y="455" fill="#74697B" fontSize="10">Maya’s phone</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g className="scene-phone" filter="url(#hero-shadow)">
|
|
||||||
<rect x="536" y="157" width="160" height="309" rx="36" fill="#E4DFE7" stroke="#CFC6D3" strokeWidth="2" />
|
|
||||||
<rect x="546" y="168" width="140" height="285" rx="28" fill="url(#hero-phone)" />
|
|
||||||
<rect x="587" y="177" width="58" height="8" rx="4" fill="#0B090D" />
|
|
||||||
<g clipPath="url(#phone-screen-clip)">
|
|
||||||
<circle cx="616" cy="271" r="76" fill="#A855F7" opacity="0.1" />
|
|
||||||
<circle cx="616" cy="275" r="49" fill="url(#hero-orb)" opacity="0.55" />
|
|
||||||
<g className="received-file">
|
|
||||||
<rect x="579" y="224" width="74" height="92" rx="12" fill="#FCF9FD" stroke="#C98AFD" strokeWidth="1.5" />
|
|
||||||
<path d="M630 224h23v23Z" fill="#DEC0F6" />
|
|
||||||
<rect x="590" y="239" width="26" height="26" rx="7" fill="#E9D2FA" />
|
|
||||||
<path d="m595 259 8-9 5 5 5-5 6 9Z" fill="#9E47EF" />
|
|
||||||
<rect x="590" y="278" width="46" height="6" rx="3" fill="#C6BACD" />
|
|
||||||
<rect x="590" y="291" width="34" height="5" rx="2.5" fill="#DFD6E4" />
|
|
||||||
</g>
|
|
||||||
<rect x="564" y="337" width="104" height="42" rx="12" fill="#2F2935" stroke="#4B4251" />
|
|
||||||
<circle cx="581" cy="358" r="8" fill="#A855F7" />
|
|
||||||
<path d="m577.5 358 2.2 2.2 4.5-4.6" fill="none" stroke="white" strokeWidth="1.5" />
|
|
||||||
<text x="595" y="355" fill="#FCF9FD" fontSize="10" fontWeight="700">Received</text>
|
|
||||||
<text x="595" y="368" fill="#A89EAF" fontSize="8">Verified safely</text>
|
|
||||||
<rect x="564" y="393" width="104" height="5" rx="2.5" fill="#3F3745" />
|
|
||||||
<rect x="564" y="393" width="104" height="5" rx="2.5" fill="#A855F7" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g className="transfer-packets">
|
|
||||||
<g className="packet packet-one">
|
|
||||||
<rect x="0" y="0" width="28" height="34" rx="6" fill="#FCF9FE" stroke="#A855F7" />
|
|
||||||
<path d="M19 0h9v9Z" fill="#DDBCF7" />
|
|
||||||
</g>
|
|
||||||
<g className="packet packet-two">
|
|
||||||
<rect x="0" y="0" width="22" height="27" rx="5" fill="#EEE0F9" stroke="#B869F4" />
|
|
||||||
<path d="M14 0h8v8Z" fill="#CAA0E9" />
|
|
||||||
</g>
|
|
||||||
<circle className="packet-spark packet-spark-one" cx="0" cy="0" r="5" fill="#D795FF" />
|
|
||||||
<circle className="packet-spark packet-spark-two" cx="0" cy="0" r="3" fill="#A855F7" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
<div className="hero-file-label">
|
|
||||||
<span className="file-type-icon">JPG</span>
|
|
||||||
<span>
|
|
||||||
<strong>summer-photos</strong>
|
<strong>summer-photos</strong>
|
||||||
<small>42 files · structure preserved</small>
|
<span>42 files · 486 MB</span>
|
||||||
|
<small><Icon name="folder" /> Structure preserved</small>
|
||||||
|
</div>
|
||||||
|
<span className="collection-menu">•••</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="receiver-section-heading">
|
||||||
|
<span>Receivers</span>
|
||||||
|
<small>1 connected</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="desktop-receiver-row">
|
||||||
|
<span className="receiver-avatar">M</span>
|
||||||
|
<span className="receiver-identity">
|
||||||
|
<strong>Maya's iPhone</strong>
|
||||||
|
<small>iOS · nearby device</small>
|
||||||
</span>
|
</span>
|
||||||
|
<span className="receiver-state-stack">
|
||||||
|
<motion.span
|
||||||
|
className="receiver-row-state is-waiting"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 0 }
|
||||||
|
: { opacity: [1, 1, 0, 0] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.4, 0.48, 1] }}
|
||||||
|
>
|
||||||
|
Approval required
|
||||||
|
</motion.span>
|
||||||
|
<motion.span
|
||||||
|
className="receiver-row-state is-sending"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 0 }
|
||||||
|
: { opacity: [0, 0, 1, 1, 0, 0] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.43, 0.5, 0.71, 0.78, 1] }}
|
||||||
|
>
|
||||||
|
Sending securely
|
||||||
|
</motion.span>
|
||||||
|
<motion.span
|
||||||
|
className="receiver-row-state is-complete"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 1 }
|
||||||
|
: { opacity: [0, 0, 1, 1] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.72, 0.79, 1] }}
|
||||||
|
>
|
||||||
|
<Icon name="verified" /> Verified
|
||||||
|
</motion.span>
|
||||||
|
</span>
|
||||||
|
<div className="receiver-progress-track">
|
||||||
|
<motion.span
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { scaleX: 1 }
|
||||||
|
: { scaleX: [0, 0, 0.04, 0.72, 1, 1] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.46, 0.51, 0.67, 0.76, 1] }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="desktop-transfer-foot">
|
||||||
|
<span><Icon name="shield" /> Approval by default</span>
|
||||||
|
<span><Icon name="lock" /> End-to-end encrypted</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
className="approval-knock-card"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 0, y: 8, scale: 0.98 }
|
||||||
|
: {
|
||||||
|
opacity: [0, 0, 1, 1, 0, 0],
|
||||||
|
y: [12, 12, 0, 0, -5, -5],
|
||||||
|
scale: [0.97, 0.97, 1, 1, 0.985, 0.985],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.24, 0.3, 0.42, 0.49, 1], ease: "easeInOut" }}
|
||||||
|
>
|
||||||
|
<div className="approval-knock-top">
|
||||||
|
<span className="receiver-avatar">M</span>
|
||||||
|
<span>
|
||||||
|
<small>NEW RECEIVER</small>
|
||||||
|
<strong>Maya's iPhone</strong>
|
||||||
|
</span>
|
||||||
|
<span className="approval-lock"><Icon name="lock" /></span>
|
||||||
|
</div>
|
||||||
|
<p>Wants to receive <strong>summer-photos</strong></p>
|
||||||
|
<div className="approval-knock-actions">
|
||||||
|
<span>Refuse</span>
|
||||||
|
<motion.span
|
||||||
|
className="approval-accept"
|
||||||
|
animate={reduceMotion ? undefined : { scale: [1, 1, 1.055, 1, 1] }}
|
||||||
|
transition={{ ...repeating, times: [0, 0.38, 0.42, 0.46, 1] }}
|
||||||
|
>
|
||||||
|
<Icon name="check" /> Approve
|
||||||
|
</motion.span>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<svg className="hero-conduit" viewBox="0 0 760 620" fill="none">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="conduit-gradient" x1="410" y1="340" x2="650" y2="390" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stopColor="#C084FC" />
|
||||||
|
<stop offset="1" stopColor="#7C2AEF" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter id="conduit-blur" x="-30%" y="-80%" width="160%" height="260%">
|
||||||
|
<feGaussianBlur stdDeviation="8" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<path
|
||||||
|
d="M414 342C480 344 508 392 571 390C606 389 624 373 646 351"
|
||||||
|
stroke="#D9D0DE"
|
||||||
|
strokeWidth="14"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
<motion.path
|
||||||
|
d="M414 342C480 344 508 392 571 390C606 389 624 373 646 351"
|
||||||
|
stroke="#A855F7"
|
||||||
|
strokeOpacity="0.24"
|
||||||
|
strokeWidth="28"
|
||||||
|
strokeLinecap="round"
|
||||||
|
filter="url(#conduit-blur)"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 0.55, pathLength: 1 }
|
||||||
|
: { opacity: [0.05, 0.05, 0.55, 0.55, 0.15], pathLength: [0, 0, 1, 1, 1] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.46, 0.7, 0.82, 1], ease: "easeInOut" }}
|
||||||
|
/>
|
||||||
|
<motion.path
|
||||||
|
d="M414 342C480 344 508 392 571 390C606 389 624 373 646 351"
|
||||||
|
stroke="url(#conduit-gradient)"
|
||||||
|
strokeWidth="6"
|
||||||
|
strokeLinecap="round"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { pathLength: 1, opacity: 0.85 }
|
||||||
|
: { pathLength: [0, 0, 1, 1, 1], opacity: [0.25, 0.25, 1, 1, 0.45] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.46, 0.7, 0.82, 1], ease: "easeInOut" }}
|
||||||
|
/>
|
||||||
|
<motion.circle
|
||||||
|
r="8"
|
||||||
|
fill="#FCF9FF"
|
||||||
|
stroke="#A855F7"
|
||||||
|
strokeWidth="3"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { cx: 646, cy: 351, opacity: 0 }
|
||||||
|
: {
|
||||||
|
cx: [414, 414, 448, 505, 570, 620, 646, 646],
|
||||||
|
cy: [342, 342, 348, 382, 390, 372, 351, 351],
|
||||||
|
opacity: [0, 0, 1, 1, 1, 1, 0, 0],
|
||||||
|
scale: [0.7, 0.7, 1, 1, 1, 1, 0.7, 0.7],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.49, 0.53, 0.59, 0.65, 0.7, 0.74, 1], ease: "easeInOut" }}
|
||||||
|
/>
|
||||||
|
<motion.circle
|
||||||
|
r="5"
|
||||||
|
fill="#D8B4FE"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { cx: 646, cy: 351, opacity: 0 }
|
||||||
|
: {
|
||||||
|
cx: [414, 414, 448, 505, 570, 620, 646, 646],
|
||||||
|
cy: [342, 342, 348, 382, 390, 372, 351, 351],
|
||||||
|
opacity: [0, 0, 1, 1, 1, 1, 0, 0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.56, 0.6, 0.66, 0.72, 0.77, 0.81, 1], ease: "easeInOut" }}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<div className="receiver-phone-shell">
|
||||||
|
<span className="phone-side-button phone-side-button-one" />
|
||||||
|
<span className="phone-side-button phone-side-button-two" />
|
||||||
|
<div className="receiver-phone-frame">
|
||||||
|
<div className="phone-screen">
|
||||||
|
<div className="phone-status-bar">
|
||||||
|
<span>9:41</span>
|
||||||
|
<span className="phone-island" />
|
||||||
|
<span className="phone-signal">● ◒</span>
|
||||||
|
</div>
|
||||||
|
<div className="phone-app-bar">
|
||||||
|
<BrandMark className="phone-brand-mark" />
|
||||||
|
<strong>Receive</strong>
|
||||||
|
<span><Icon name="shield" /></span>
|
||||||
|
</div>
|
||||||
|
<div className="phone-transfer-card">
|
||||||
|
<div className="phone-file-art"><Icon name="folder" /></div>
|
||||||
|
<small>INCOMING FROM ALEX</small>
|
||||||
|
<strong>summer-photos</strong>
|
||||||
|
<span>42 files · 486 MB</span>
|
||||||
|
</div>
|
||||||
|
<div className="phone-state-area">
|
||||||
|
<motion.div
|
||||||
|
className="phone-state is-waiting"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 0 }
|
||||||
|
: { opacity: [1, 1, 0, 0] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.43, 0.5, 1] }}
|
||||||
|
>
|
||||||
|
<span className="state-symbol"><Icon name="lock" /></span>
|
||||||
|
<strong>Waiting for approval</strong>
|
||||||
|
<small>The sender stays in control.</small>
|
||||||
|
</motion.div>
|
||||||
|
<motion.div
|
||||||
|
className="phone-state is-transferring"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 0 }
|
||||||
|
: { opacity: [0, 0, 1, 1, 0, 0] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.45, 0.51, 0.71, 0.78, 1] }}
|
||||||
|
>
|
||||||
|
<span className="transfer-percentage">68<span>%</span></span>
|
||||||
|
<strong>Receiving securely</strong>
|
||||||
|
<small>Direct path · 38 MB/s</small>
|
||||||
|
</motion.div>
|
||||||
|
<motion.div
|
||||||
|
className="phone-state is-verified"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 1, scale: 1 }
|
||||||
|
: { opacity: [0, 0, 1, 1], scale: [0.92, 0.92, 1, 1] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.72, 0.79, 1], ease: "easeOut" }}
|
||||||
|
>
|
||||||
|
<span className="state-symbol is-success"><Icon name="verified" /></span>
|
||||||
|
<strong>Received & verified</strong>
|
||||||
|
<small>Saved to Downloads</small>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
<div className="phone-home-indicator" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
className="hero-route-card"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 1, y: 0 }
|
||||||
|
: { opacity: [0, 1, 1, 1], y: [-8, 0, 0, 0] }
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.08, 0.92, 1], ease: "easeOut" }}
|
||||||
|
>
|
||||||
|
<span className="route-pulse" />
|
||||||
|
<span>
|
||||||
|
<small>ROUTE</small>
|
||||||
|
<strong>Direct path established</strong>
|
||||||
|
</span>
|
||||||
|
<span className="route-latency">18 ms</span>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
className="hero-verified-card"
|
||||||
|
animate={
|
||||||
|
reduceMotion
|
||||||
|
? { opacity: 1, y: 0, scale: 1 }
|
||||||
|
: {
|
||||||
|
opacity: [0, 0, 1, 1],
|
||||||
|
y: [8, 8, 0, 0],
|
||||||
|
scale: [0.96, 0.96, 1, 1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transition={{ ...repeating, times: [0, 0.74, 0.81, 1], ease: "easeOut" }}
|
||||||
|
>
|
||||||
|
<span><Icon name="verified" /></span>
|
||||||
|
<span>
|
||||||
|
<strong>Content verified</strong>
|
||||||
|
<small>42 / 42 files match</small>
|
||||||
|
</span>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<div className="hero-privacy-rail">
|
||||||
|
<span><Icon name="lock" /> E2E encrypted</span>
|
||||||
|
<i />
|
||||||
|
<span>No hosted copy</span>
|
||||||
|
<i />
|
||||||
|
<span>Approval required</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<figcaption className="sr-only">
|
<figcaption className="sr-only">
|
||||||
An illustration of encrypted files moving from a laptop to a phone after receiver approval.
|
A VniDrop transfer moves from a desktop sender to a phone after receiver approval, then is
|
||||||
|
verified on arrival.
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Hero transfer scene */
|
/* Coordinated product transfer stage */
|
||||||
.hero-visual {
|
.hero-visual {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: min(100%, 730px);
|
width: min(100%, 760px);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,238 +10,597 @@
|
|||||||
--pointer-y: 0;
|
--pointer-y: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 1.13;
|
aspect-ratio: 1.17;
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
perspective: 1200px;
|
perspective: 1400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-grid {
|
.hero-stage-grid {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -3;
|
z-index: -3;
|
||||||
inset: 9% 2% 4% 7%;
|
inset: 3% 0 4% 1%;
|
||||||
border: 1px solid rgba(168, 85, 247, 0.14);
|
overflow: hidden;
|
||||||
border-radius: 50%;
|
border: 1px solid rgba(159, 132, 173, 0.15);
|
||||||
background-image:
|
border-radius: 44px;
|
||||||
linear-gradient(rgba(121, 82, 138, 0.07) 1px, transparent 1px),
|
background:
|
||||||
linear-gradient(90deg, rgba(121, 82, 138, 0.07) 1px, transparent 1px);
|
linear-gradient(rgba(110, 86, 122, 0.055) 1px, transparent 1px),
|
||||||
background-size: 32px 32px;
|
linear-gradient(90deg, rgba(110, 86, 122, 0.055) 1px, transparent 1px),
|
||||||
transform: rotateX(64deg) rotateZ(-8deg) translateZ(-70px);
|
radial-gradient(circle at 72% 35%, rgba(192, 132, 252, 0.13), transparent 38%),
|
||||||
mask-image: radial-gradient(circle, black 10%, transparent 70%);
|
rgba(255, 255, 255, 0.2);
|
||||||
|
background-size: 28px 28px, 28px 28px, auto, auto;
|
||||||
|
mask-image: linear-gradient(to bottom, transparent 0, black 9%, black 88%, transparent 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-glow {
|
.hero-stage-grid::before,
|
||||||
|
.hero-stage-grid::after {
|
||||||
|
position: absolute;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: rgba(168, 85, 247, 0.35);
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-stage-grid::before {
|
||||||
|
top: 18px;
|
||||||
|
left: 18px;
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-stage-grid::after {
|
||||||
|
right: 18px;
|
||||||
|
bottom: 18px;
|
||||||
|
border-width: 0 1px 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-stage-glow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -2;
|
z-index: -2;
|
||||||
|
top: 18%;
|
||||||
|
right: 9%;
|
||||||
|
width: 45%;
|
||||||
|
aspect-ratio: 1;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
filter: blur(60px);
|
background: rgba(168, 85, 247, 0.16);
|
||||||
|
filter: blur(70px);
|
||||||
|
transform: translate(
|
||||||
|
calc(var(--pointer-x) * 9px),
|
||||||
|
calc(var(--pointer-y) * 9px)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-coordinate {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
color: rgba(87, 70, 95, 0.48);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 7px;
|
||||||
|
font-weight: 750;
|
||||||
|
letter-spacing: 0.13em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-coordinate-top {
|
||||||
|
top: 1.5%;
|
||||||
|
left: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-coordinate-side {
|
||||||
|
top: 27%;
|
||||||
|
right: -3%;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-product-shell {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 3;
|
||||||
|
top: 11%;
|
||||||
|
left: 1.5%;
|
||||||
|
width: 64%;
|
||||||
|
height: 55%;
|
||||||
|
transform: translate(
|
||||||
|
calc(var(--pointer-x) * -5px),
|
||||||
|
calc(var(--pointer-y) * -4px)
|
||||||
|
)
|
||||||
|
rotateY(calc(var(--pointer-x) * 1.4deg))
|
||||||
|
rotateX(calc(var(--pointer-y) * -1.2deg));
|
||||||
|
transform-origin: center;
|
||||||
|
transition: transform 180ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-product-window {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: visible;
|
||||||
|
border: 1px solid rgba(195, 186, 200, 0.95);
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #fcfbfc;
|
||||||
|
box-shadow:
|
||||||
|
0 38px 90px rgba(52, 34, 62, 0.16),
|
||||||
|
0 8px 24px rgba(52, 34, 62, 0.08),
|
||||||
|
inset 0 1px white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-product-window::after {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: inherit;
|
||||||
|
background: linear-gradient(118deg, rgba(255, 255, 255, 0.5), transparent 24%, transparent 72%, rgba(168, 85, 247, 0.025));
|
||||||
|
content: "";
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-glow-one {
|
.desktop-window-bar {
|
||||||
top: 22%;
|
position: relative;
|
||||||
right: 8%;
|
z-index: 2;
|
||||||
width: 37%;
|
|
||||||
aspect-ratio: 1;
|
|
||||||
background: rgba(168, 85, 247, 0.23);
|
|
||||||
transform: translate(calc(var(--pointer-x) * 12px), calc(var(--pointer-y) * 12px));
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-glow-two {
|
|
||||||
bottom: 8%;
|
|
||||||
left: 28%;
|
|
||||||
width: 30%;
|
|
||||||
aspect-ratio: 1;
|
|
||||||
background: rgba(126, 58, 236, 0.16);
|
|
||||||
transform: translate(calc(var(--pointer-x) * -9px), calc(var(--pointer-y) * -9px));
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-scene {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
inset: 1% -3% auto -1%;
|
|
||||||
width: 105%;
|
|
||||||
overflow: visible;
|
|
||||||
transform: rotateY(calc(var(--pointer-x) * 1.7deg)) rotateX(calc(var(--pointer-y) * -1.7deg));
|
|
||||||
transform-origin: center;
|
|
||||||
transition: transform 180ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-laptop {
|
|
||||||
transform: translate(calc(var(--pointer-x) * -4px), calc(var(--pointer-y) * -4px));
|
|
||||||
transition: transform 200ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-phone {
|
|
||||||
transform: translate(calc(var(--pointer-x) * 7px), calc(var(--pointer-y) * 5px));
|
|
||||||
transition: transform 200ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-orbits {
|
|
||||||
transform-origin: 385px 325px;
|
|
||||||
animation: scene-orbits 30s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.laptop-files {
|
|
||||||
transform-origin: 190px 245px;
|
|
||||||
animation: laptop-files 6s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conduit-energy {
|
|
||||||
animation: conduit-energy 2s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.approval-gate {
|
|
||||||
transform-origin: 440px 443px;
|
|
||||||
animation: gate-hover 5s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.received-file {
|
|
||||||
transform-origin: 616px 270px;
|
|
||||||
animation: received-file 7s cubic-bezier(0.34, 1.2, 0.55, 1) infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet,
|
|
||||||
.packet-spark {
|
|
||||||
opacity: 0;
|
|
||||||
transform-box: fill-box;
|
|
||||||
transform-origin: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-one {
|
|
||||||
animation: hero-packet-one 7s cubic-bezier(0.45, 0.05, 0.35, 1) 0.6s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-two {
|
|
||||||
animation: hero-packet-two 7s cubic-bezier(0.45, 0.05, 0.35, 1) 3s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-spark-one {
|
|
||||||
animation: hero-spark-one 7s ease 0.6s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.packet-spark-two {
|
|
||||||
animation: hero-spark-two 7s ease 3s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-status {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 5;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border: 1px solid rgba(222, 211, 228, 0.95);
|
|
||||||
background: rgba(255, 255, 255, 0.9);
|
|
||||||
box-shadow: 0 15px 45px rgba(49, 27, 61, 0.11);
|
|
||||||
backdrop-filter: blur(12px);
|
|
||||||
transition: transform 180ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-status-secure {
|
|
||||||
top: 2%;
|
|
||||||
right: 5%;
|
|
||||||
gap: 10px;
|
|
||||||
padding: 10px 13px 10px 10px;
|
|
||||||
border-radius: 14px;
|
|
||||||
transform: translate(calc(var(--pointer-x) * 12px), calc(var(--pointer-y) * 8px)) rotate(2deg);
|
|
||||||
animation: status-hover 6s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-icon {
|
|
||||||
display: grid;
|
display: grid;
|
||||||
width: 34px;
|
grid-template-columns: 1fr auto 1fr;
|
||||||
|
align-items: center;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
place-items: center;
|
padding: 0 11px;
|
||||||
border-radius: 10px;
|
border-bottom: 1px solid #e9e5eb;
|
||||||
background: var(--brand-100);
|
border-radius: 20px 20px 0 0;
|
||||||
color: var(--brand-600);
|
background: rgba(248, 247, 249, 0.92);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-icon svg {
|
.window-controls {
|
||||||
width: 17px;
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-status strong,
|
.window-controls i {
|
||||||
.hero-status small {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-status strong {
|
|
||||||
color: #2b2530;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-status small {
|
|
||||||
color: #897f8e;
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-status-route {
|
|
||||||
top: 18%;
|
|
||||||
left: 9%;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 7px 11px;
|
|
||||||
border-radius: 999px;
|
|
||||||
color: #534b57;
|
|
||||||
font-family: var(--font-mono);
|
|
||||||
font-size: 8px;
|
|
||||||
font-weight: 700;
|
|
||||||
letter-spacing: 0.04em;
|
|
||||||
transform: translate(calc(var(--pointer-x) * -8px), calc(var(--pointer-y) * -6px)) rotate(-3deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-pulse,
|
|
||||||
.live-dot {
|
|
||||||
display: inline-block;
|
|
||||||
width: 7px;
|
width: 7px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #2bc477;
|
background: #d8d2dc;
|
||||||
box-shadow: 0 0 0 4px rgba(43, 196, 119, 0.13);
|
|
||||||
animation: status-pulse 2.4s ease-in-out infinite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-file-label {
|
.window-controls i:first-child { background: #c084fc; }
|
||||||
position: absolute;
|
|
||||||
z-index: 4;
|
.window-title {
|
||||||
bottom: 7%;
|
color: #777078;
|
||||||
left: 7%;
|
font-size: 8px;
|
||||||
|
font-weight: 650;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-security {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-self: end;
|
||||||
|
gap: 4px;
|
||||||
|
color: #7b707f;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 6px;
|
||||||
|
font-weight: 750;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-security svg {
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
color: var(--brand-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-app-layout {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 50px 1fr;
|
||||||
|
height: calc(100% - 34px);
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 0 0 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-sidebar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
padding: 9px 0 10px;
|
||||||
|
border-right: 1px solid #ebe7ed;
|
||||||
|
background: #f7f6f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-brand-mark {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-sidebar-item {
|
||||||
|
display: grid;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 9px;
|
||||||
|
color: #8c848f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-sidebar-item.is-active {
|
||||||
|
background: linear-gradient(135deg, #ead5fe, #f5eafe);
|
||||||
|
color: var(--brand-700);
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(168, 85, 247, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-sidebar-item svg {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-sidebar-spacer { flex: 1; }
|
||||||
|
|
||||||
|
.desktop-profile {
|
||||||
|
display: grid;
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: #232027;
|
||||||
|
color: white;
|
||||||
|
font-size: 7px;
|
||||||
|
font-weight: 780;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-transfer-view {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 14px 16px 12px;
|
||||||
|
background: #fdfcfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-view-heading {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-view-heading div {
|
||||||
|
display: grid;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-view-heading small {
|
||||||
|
color: #9a919e;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 6px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.11em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-view-heading strong {
|
||||||
|
color: #211d24;
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.2;
|
||||||
|
letter-spacing: -0.035em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sharing-pill {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 4px 7px;
|
||||||
|
border: 1px solid #e2d2ee;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f6edfe;
|
||||||
|
color: #6f27e9;
|
||||||
|
font-size: 7px;
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sharing-pill i {
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--brand-500);
|
||||||
|
box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collection-card {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 64px 1fr auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 11px;
|
gap: 11px;
|
||||||
padding: 10px 13px;
|
padding: 9px;
|
||||||
border: 1px solid rgba(222, 211, 228, 0.95);
|
border: 1px solid #e9e5eb;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
background: rgba(255, 255, 255, 0.9);
|
background: #f7f6f8;
|
||||||
box-shadow: 0 15px 45px rgba(49, 27, 61, 0.11);
|
|
||||||
backdrop-filter: blur(12px);
|
|
||||||
transform: translate(calc(var(--pointer-x) * -10px), calc(var(--pointer-y) * -7px)) rotate(-2deg);
|
|
||||||
transition: transform 180ms ease-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-type-icon {
|
.file-collage {
|
||||||
display: grid;
|
display: grid;
|
||||||
width: 37px;
|
width: 64px;
|
||||||
height: 37px;
|
height: 52px;
|
||||||
|
grid-template-columns: 1.15fr 0.85fr;
|
||||||
|
grid-template-rows: repeat(2, 1fr);
|
||||||
|
gap: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: #e9e5eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collage span:first-child {
|
||||||
|
grid-row: 1 / 3;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 35% 23%, #ffe6b6 0 8%, transparent 9%),
|
||||||
|
linear-gradient(145deg, #94b8d5 0 38%, #5a8b8f 39% 57%, #efbc7b 58%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collage span:nth-child(2) {
|
||||||
|
background: linear-gradient(150deg, #8a76a8 0 35%, #d4a985 36% 68%, #5c4356 69%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collage span:nth-child(3) {
|
||||||
|
background: linear-gradient(140deg, #ceddca 0 38%, #6d9b77 39% 61%, #d7bd92 62%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collage span:nth-child(4) { display: none; }
|
||||||
|
|
||||||
|
.file-collection-copy {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collection-copy strong {
|
||||||
|
overflow: hidden;
|
||||||
|
color: #27222a;
|
||||||
|
font-size: 10px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collection-copy > span {
|
||||||
|
color: #7f7683;
|
||||||
|
font-size: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collection-copy small {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
margin-top: 5px;
|
||||||
|
color: #85798a;
|
||||||
|
font-size: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-collection-copy svg {
|
||||||
|
width: 9px;
|
||||||
|
color: var(--brand-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
.collection-menu {
|
||||||
|
align-self: start;
|
||||||
|
padding: 0 2px;
|
||||||
|
color: #9c929f;
|
||||||
|
font-size: 9px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-section-heading {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 11px 2px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-section-heading span {
|
||||||
|
color: #373039;
|
||||||
|
font-size: 8px;
|
||||||
|
font-weight: 750;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-section-heading small {
|
||||||
|
color: #938a96;
|
||||||
|
font-size: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-receiver-row {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 31px 1fr auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
min-height: 48px;
|
||||||
|
padding: 8px 9px 10px;
|
||||||
|
border: 1px solid #e8e3ea;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 5px 15px rgba(49, 36, 55, 0.035);
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-avatar {
|
||||||
|
display: grid;
|
||||||
|
width: 29px;
|
||||||
|
height: 29px;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: linear-gradient(135deg, var(--brand-400), var(--brand-600));
|
background: linear-gradient(135deg, #ead2fe, #c084fc);
|
||||||
color: white;
|
color: #5c1bb8;
|
||||||
font-family: var(--font-mono);
|
font-size: 9px;
|
||||||
font-size: 8px;
|
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-file-label strong,
|
.receiver-identity {
|
||||||
.hero-file-label small {
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-identity strong {
|
||||||
|
overflow: hidden;
|
||||||
|
color: #302a33;
|
||||||
|
font-size: 8px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-identity small {
|
||||||
|
color: #938a96;
|
||||||
|
font-size: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-state-stack {
|
||||||
|
position: relative;
|
||||||
|
width: 86px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-row-state {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 3px;
|
||||||
|
font-size: 6px;
|
||||||
|
font-weight: 720;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-row-state.is-waiting { color: #9a6716; }
|
||||||
|
.receiver-row-state.is-sending { color: var(--brand-700); }
|
||||||
|
.receiver-row-state.is-complete { color: #23855a; }
|
||||||
|
.receiver-row-state svg { width: 9px; }
|
||||||
|
|
||||||
|
.receiver-progress-track {
|
||||||
|
position: absolute;
|
||||||
|
right: 9px;
|
||||||
|
bottom: 5px;
|
||||||
|
left: 48px;
|
||||||
|
height: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #ede8ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.receiver-progress-track span {
|
||||||
display: block;
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: inherit;
|
||||||
|
background: linear-gradient(90deg, var(--brand-400), var(--brand-700));
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-file-label strong {
|
.desktop-transfer-foot {
|
||||||
font-size: 10px;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 8px 2px 0;
|
||||||
|
color: #8e8492;
|
||||||
|
font-size: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-file-label small {
|
.desktop-transfer-foot span {
|
||||||
color: var(--ink-muted);
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desktop-transfer-foot svg {
|
||||||
|
width: 9px;
|
||||||
|
color: var(--brand-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-card {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 8;
|
||||||
|
right: -8%;
|
||||||
|
bottom: -19%;
|
||||||
|
width: 238px;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid rgba(215, 202, 222, 0.95);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: rgba(255, 255, 255, 0.96);
|
||||||
|
box-shadow: 0 24px 65px rgba(55, 31, 66, 0.2);
|
||||||
|
backdrop-filter: blur(18px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-top {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 30px 1fr 27px;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-top > span:nth-child(2) {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-top small {
|
||||||
|
color: #9a8da0;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 5.5px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.09em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-top strong {
|
||||||
|
color: #27212b;
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.approval-lock {
|
||||||
|
display: grid;
|
||||||
|
width: 27px;
|
||||||
|
height: 27px;
|
||||||
|
place-items: center;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: var(--brand-100);
|
||||||
|
color: var(--brand-700);
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-lock svg { width: 13px; }
|
||||||
|
|
||||||
|
.approval-knock-card p {
|
||||||
|
margin: 9px 0;
|
||||||
|
color: #756c79;
|
||||||
|
font-size: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-card p strong { color: #3b323e; }
|
||||||
|
|
||||||
|
.approval-knock-actions {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1.2fr;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-actions > span {
|
||||||
|
display: inline-flex;
|
||||||
|
min-height: 28px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
border: 1px solid #e6e0e9;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: #685f6c;
|
||||||
|
font-size: 7px;
|
||||||
|
font-weight: 720;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-knock-actions .approval-accept {
|
||||||
|
border-color: transparent;
|
||||||
|
background: linear-gradient(135deg, var(--brand-500), var(--brand-700));
|
||||||
|
box-shadow: 0 8px 18px rgba(132, 47, 238, 0.22);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-accept svg { width: 10px; }
|
||||||
|
|
||||||
|
.hero-conduit {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: visible;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,12 @@ export function Icon({ name, ...props }: IconProps) {
|
|||||||
<path d="M3 7.5A2.5 2.5 0 0 1 5.5 5H10l2 2h6.5A2.5 2.5 0 0 1 21 9.5v7a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 16.5z" />
|
<path d="M3 7.5A2.5 2.5 0 0 1 5.5 5H10l2 2h6.5A2.5 2.5 0 0 1 21 9.5v7a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 16.5z" />
|
||||||
),
|
),
|
||||||
github: (
|
github: (
|
||||||
<path d="M12 2a10 10 0 0 0-3.2 19.5c.5.1.7-.2.7-.5v-1.9c-2.8.6-3.4-1.2-3.4-1.2-.5-1.1-1.1-1.4-1.1-1.4-.9-.6.1-.6.1-.6 1 0 1.5 1 1.5 1 .9 1.5 2.3 1.1 2.9.8.1-.6.3-1.1.6-1.3-2.2-.3-4.6-1.1-4.6-5a3.9 3.9 0 0 1 1-2.7c-.1-.3-.4-1.3.1-2.7 0 0 .9-.3 2.8 1a9.6 9.6 0 0 1 5.1 0c2-1.3 2.8-1 2.8-1 .6 1.4.2 2.4.1 2.7a3.9 3.9 0 0 1 1 2.7c0 3.9-2.4 4.7-4.6 5 .4.3.7.9.7 1.8V21c0 .3.2.6.7.5A10 10 0 0 0 12 2Z" />
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M8.5 2.22168C5.23312 2.22168 2.58496 4.87398 2.58496 8.14677C2.58496 10.7642 4.27962 12.9853 6.63026 13.7684C6.92601 13.8228 7.03366 13.6401 7.03366 13.4827C7.03366 13.3425 7.02893 12.9693 7.02597 12.4754C5.38041 12.8333 5.0332 11.681 5.0332 11.681C4.76465 10.996 4.37663 10.8139 4.37663 10.8139C3.83954 10.4471 4.41744 10.4542 4.41744 10.4542C5.01072 10.4956 5.32303 11.0647 5.32303 11.0647C5.85065 11.9697 6.70774 11.7082 7.04431 11.5568C7.09873 11.1741 7.25134 10.9132 7.42051 10.7654C6.10737 10.6157 4.72621 10.107 4.72621 7.83683C4.72621 7.19031 4.95689 6.66092 5.33486 6.24686C5.27394 6.09721 5.07105 5.49447 5.39283 4.67938C5.39283 4.67938 5.88969 4.51967 7.01947 5.28626C7.502 5.15466 7.99985 5.08763 8.5 5.08692C9.00278 5.08929 9.50851 5.15495 9.98113 5.28626C11.1103 4.51967 11.606 4.67879 11.606 4.67879C11.9289 5.49447 11.7255 6.09721 11.6651 6.24686C12.0437 6.66092 12.2732 7.19031 12.2732 7.83683C12.2732 10.1129 10.8897 10.6139 9.5724 10.7606C9.78475 10.9434 9.97344 11.3048 9.97344 11.8579C9.97344 12.6493 9.96634 13.2887 9.96634 13.4827C9.96634 13.6413 10.0728 13.8258 10.3733 13.7678C11.5512 13.3728 12.5751 12.6175 13.3003 11.6089C14.0256 10.6002 14.4155 9.38912 14.415 8.14677C14.415 4.87398 11.7663 2.22168 8.5 2.22168Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
globe: (
|
globe: (
|
||||||
<>
|
<>
|
||||||
@@ -125,9 +130,9 @@ export function Icon({ name, ...props }: IconProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
viewBox="0 0 24 24"
|
viewBox={name === "github" ? "0 0 17 16" : "0 0 24 24"}
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke={name === "github" ? "none" : "currentColor"}
|
||||||
strokeWidth="1.8"
|
strokeWidth="1.8"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
transform: translate(-50%, -50%) rotate(-3deg);
|
transform: translate(-50%, -50%) rotate(-3deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.platform-center svg { position: relative; z-index: 2; width: 87px; height: 87px; }
|
.platform-center img { position: relative; z-index: 2; width: 87px; height: 87px; }
|
||||||
|
|
||||||
.platform-center-glow {
|
.platform-center-glow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -100,4 +100,3 @@
|
|||||||
.platform-chip-3 { right: 1%; bottom: 22%; animation-delay: -4s; }
|
.platform-chip-3 { right: 1%; bottom: 22%; animation-delay: -4s; }
|
||||||
.platform-chip-4 { bottom: 7%; left: 24%; animation-delay: -0.5s; }
|
.platform-chip-4 { bottom: 7%; left: 24%; animation-delay: -0.5s; }
|
||||||
.platform-chip-5 { top: 45%; left: 0; animation-delay: -3.2s; }
|
.platform-chip-5 { top: 45%; left: 0; animation-delay: -3.2s; }
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function SiteFooter() {
|
|||||||
<div>
|
<div>
|
||||||
<p className="footer-label">Project</p>
|
<p className="footer-label">Project</p>
|
||||||
<a href="https://github.com/vnidrop/vnidrop" target="_blank" rel="noreferrer">
|
<a href="https://github.com/vnidrop/vnidrop" target="_blank" rel="noreferrer">
|
||||||
GitHub <Icon name="arrow" />
|
GitHub <Icon name="github" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/vnidrop/vnidrop/blob/master/LICENSE"
|
href="https://github.com/vnidrop/vnidrop/blob/master/LICENSE"
|
||||||
|
|||||||
@@ -1,71 +1,22 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useState } from "react";
|
|
||||||
import { Brand } from "@/components/brand";
|
import { Brand } from "@/components/brand";
|
||||||
import { Icon } from "@/components/icons";
|
import { Icon } from "@/components/icons";
|
||||||
|
|
||||||
const navigation = [
|
|
||||||
{ href: "/#how-it-works", label: "How it works" },
|
|
||||||
{ href: "/#privacy", label: "Privacy" },
|
|
||||||
{ href: "/#platforms", label: "Platforms" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export function SiteHeader() {
|
export function SiteHeader() {
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="site-header">
|
<header className="site-header">
|
||||||
<div className="header-inner">
|
<div className="header-inner page-shell">
|
||||||
<Brand />
|
<Brand />
|
||||||
<nav className="desktop-nav" aria-label="Main navigation">
|
<Link
|
||||||
{navigation.map((item) => (
|
className="header-github-button"
|
||||||
<Link key={item.href} href={item.href}>
|
|
||||||
{item.label}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</nav>
|
|
||||||
<a
|
|
||||||
className="button button-small button-dark header-github"
|
|
||||||
href="https://github.com/vnidrop/vnidrop"
|
href="https://github.com/vnidrop/vnidrop"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
<Icon name="github" />
|
<Icon name="github" />
|
||||||
GitHub
|
View on GitHub
|
||||||
</a>
|
</Link>
|
||||||
<button
|
|
||||||
className="menu-button"
|
|
||||||
type="button"
|
|
||||||
aria-expanded={open}
|
|
||||||
aria-controls="mobile-navigation"
|
|
||||||
aria-label={open ? "Close navigation" : "Open navigation"}
|
|
||||||
onClick={() => setOpen((value) => !value)}
|
|
||||||
>
|
|
||||||
<Icon name={open ? "close" : "menu"} />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<nav
|
|
||||||
id="mobile-navigation"
|
|
||||||
className={`mobile-nav${open ? " is-open" : ""}`}
|
|
||||||
aria-label="Mobile navigation"
|
|
||||||
>
|
|
||||||
{navigation.map((item) => (
|
|
||||||
<Link key={item.href} href={item.href} onClick={() => setOpen(false)}>
|
|
||||||
{item.label}
|
|
||||||
<Icon name="arrow" />
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
<a
|
|
||||||
href="https://github.com/vnidrop/vnidrop"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
onClick={() => setOpen(false)}
|
|
||||||
>
|
|
||||||
Explore on GitHub
|
|
||||||
<Icon name="github" />
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
69
docs/package-lock.json
generated
69
docs/package-lock.json
generated
@@ -8,6 +8,7 @@
|
|||||||
"name": "vnidrop-site",
|
"name": "vnidrop-site",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"motion": "^12.42.2",
|
||||||
"next": "16.2.10",
|
"next": "16.2.10",
|
||||||
"react": "19.2.7",
|
"react": "19.2.7",
|
||||||
"react-dom": "19.2.7"
|
"react-dom": "19.2.7"
|
||||||
@@ -3433,6 +3434,33 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.42.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.42.2.tgz",
|
||||||
|
"integrity": "sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.42.2",
|
||||||
|
"motion-utils": "^12.39.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
@@ -4489,6 +4517,47 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion": {
|
||||||
|
"version": "12.42.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion/-/motion-12.42.2.tgz",
|
||||||
|
"integrity": "sha512-Atvv11yUKIid41cVrRBDVX5m8tF8kNpExRSlbpt6APClhDjtwQssgFHhQzejxw7/7YYbjHSPKBVbHo05BuJT5Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.42.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.42.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.42.2.tgz",
|
||||||
|
"integrity": "sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.39.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.39.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz",
|
||||||
|
"integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"motion": "^12.42.2",
|
||||||
"next": "16.2.10",
|
"next": "16.2.10",
|
||||||
"react": "19.2.7",
|
"react": "19.2.7",
|
||||||
"react-dom": "19.2.7"
|
"react-dom": "19.2.7"
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M236.68 148H338.36C366.24 148 387.56 170.96 387.56 198.84V564.56C387.56 597.36 372.8 620.32 372.8 646.56C372.8 725.28 436.76 787.6 522.04 787.6C607.32 787.6 668 725.28 668 646.56C668 620.32 656.52 597.36 656.52 564.56V198.84C656.52 170.96 677.84 148 705.72 148H781.16C817.24 148 846.76 177.52 846.76 213.6V564.56C846.76 738.4 704.08 879.44 522.04 879.44C340 879.44 194.04 738.4 194.04 564.56V374.32H220.28V305.44C195.68 305.44 176 297.24 176 280.84V246.4C176 231.64 187.48 220.16 202.24 220.16H236.68V148ZM256.36 239.84C251.44 239.84 248.16 244.76 248.16 249.68V275.92C248.16 282.48 253.08 285.76 259.64 285.76H282.6C289.16 285.76 292.44 280.84 292.44 274.28V251.32C292.44 244.76 287.52 239.84 280.96 239.84H256.36Z" fill="url(#paint0)"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M236.68 148H338.36C366.24 148 387.56 170.96 387.56 198.84V564.56C387.56 597.36 372.8 620.32 372.8 646.56C372.8 725.28 436.76 787.6 522.04 787.6C607.32 787.6 668 725.28 668 646.56C668 620.32 656.52 597.36 656.52 564.56V198.84C656.52 170.96 677.84 148 705.72 148H781.16C817.24 148 846.76 177.52 846.76 213.6V564.56C846.76 738.4 704.08 879.44 522.04 879.44C340 879.44 194.04 738.4 194.04 564.56V374.32H220.28V305.44C195.68 305.44 176 297.24 176 280.84V246.4C176 231.64 187.48 220.16 202.24 220.16H236.68V148ZM256.36 239.84C251.44 239.84 248.16 244.76 248.16 249.68V275.92C248.16 282.48 253.08 285.76 259.64 285.76H282.6C289.16 285.76 292.44 280.84 292.44 274.28V251.32C292.44 244.76 287.52 239.84 280.96 239.84H256.36Z" fill="url(#paint0_linear_11_12)"/>
|
||||||
<path d="M520.4 431.72C495.8 464.52 443.32 530.12 420.36 577.68C390.84 636.72 403.96 699.04 446.6 731.84C487.6 758.08 549.92 758.08 592.56 730.2C633.56 700.68 646.68 636.72 620.44 577.68C597.48 530.12 546.64 464.52 520.4 431.72Z" fill="url(#paint1)"/>
|
<path d="M520.4 431.72C495.8 464.52 443.32 530.12 420.36 577.68C390.84 636.72 403.96 699.04 446.6 731.84C487.6 758.08 549.92 758.08 592.56 730.2C633.56 700.68 646.68 636.72 620.44 577.68C597.48 530.12 546.64 464.52 520.4 431.72Z" fill="url(#paint1_linear_11_12)"/>
|
||||||
<mask id="fold" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="176" y="148" width="671" height="732">
|
<mask id="mask0_11_12" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="176" y="148" width="671" height="732">
|
||||||
<path d="M236.68 148H338.36C366.24 148 387.56 170.96 387.56 198.84V564.56C387.56 597.36 372.8 620.32 372.8 646.56C372.8 725.28 436.76 787.6 522.04 787.6C607.32 787.6 668 725.28 668 646.56C668 620.32 656.52 597.36 656.52 564.56V198.84C656.52 170.96 677.84 148 705.72 148H781.16C817.24 148 846.76 177.52 846.76 213.6V564.56C846.76 738.4 704.08 879.44 522.04 879.44C340 879.44 194.04 738.4 194.04 564.56V374.32H220.28V305.44C195.68 305.44 176 297.24 176 280.84V246.4C176 231.64 187.48 220.16 202.24 220.16H236.68V148Z" fill="white"/>
|
<path d="M236.68 148H338.36C366.24 148 387.56 170.96 387.56 198.84V564.56C387.56 597.36 372.8 620.32 372.8 646.56C372.8 725.28 436.76 787.6 522.04 787.6C607.32 787.6 668 725.28 668 646.56C668 620.32 656.52 597.36 656.52 564.56V198.84C656.52 170.96 677.84 148 705.72 148H781.16C817.24 148 846.76 177.52 846.76 213.6V564.56C846.76 738.4 704.08 879.44 522.04 879.44C340 879.44 194.04 738.4 194.04 564.56V374.32H220.28V305.44C195.68 305.44 176 297.24 176 280.84V246.4C176 231.64 187.48 220.16 202.24 220.16H236.68V148ZM256.36 239.84C251.44 239.84 248.16 244.76 248.16 249.68V275.92C248.16 282.48 253.08 285.76 259.64 285.76H282.6C289.16 285.76 292.44 280.84 292.44 274.28V251.32C292.44 244.76 287.52 239.84 280.96 239.84H256.36Z" fill="white"/>
|
||||||
</mask>
|
</mask>
|
||||||
<g mask="url(#fold)">
|
<g mask="url(#mask0_11_12)">
|
||||||
<path d="M688 148H782C832 148 842 171.8 847.48 210V303.68L688 148Z" fill="url(#paint2)"/>
|
<path d="M688 148H782C832 148 842 171.8 847.48 210V303.68L688 148Z" fill="url(#paint2_linear_11_12)"/>
|
||||||
</g>
|
</g>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="paint0" x1="176" y1="148" x2="904.706" y2="816.252" gradientUnits="userSpaceOnUse">
|
<linearGradient id="paint0_linear_11_12" x1="176" y1="148" x2="904.706" y2="816.252" gradientUnits="userSpaceOnUse">
|
||||||
<stop stop-color="#A855F7"/><stop offset="0.48" stop-color="#9D4DF4"/><stop offset="1" stop-color="#7C2AEF"/>
|
<stop stop-color="#A855F7"/>
|
||||||
</linearGradient>
|
<stop offset="0.48" stop-color="#9D4DF4"/>
|
||||||
<linearGradient id="paint1" x1="404.439" y1="431.72" x2="707.314" y2="649.286" gradientUnits="userSpaceOnUse">
|
<stop offset="1" stop-color="#7C2AEF"/>
|
||||||
<stop stop-color="#A855F7"/><stop offset="0.48" stop-color="#9D4DF4"/><stop offset="1" stop-color="#7C2AEF"/>
|
</linearGradient>
|
||||||
</linearGradient>
|
<linearGradient id="paint1_linear_11_12" x1="404.439" y1="431.72" x2="707.314" y2="649.286" gradientUnits="userSpaceOnUse">
|
||||||
<linearGradient id="paint2" x1="683.48" y1="144.6" x2="793.636" y2="306.833" gradientUnits="userSpaceOnUse">
|
<stop stop-color="#A855F7"/>
|
||||||
<stop stop-color="#F2DDFF"/><stop offset="1" stop-color="#C084FC"/>
|
<stop offset="0.48" stop-color="#9D4DF4"/>
|
||||||
</linearGradient>
|
<stop offset="1" stop-color="#7C2AEF"/>
|
||||||
</defs>
|
</linearGradient>
|
||||||
|
<linearGradient id="paint2_linear_11_12" x1="683.48" y1="144.6" x2="793.636" y2="306.833" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#F2DDFF"/>
|
||||||
|
<stop offset="1" stop-color="#C084FC"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -8,7 +8,7 @@
|
|||||||
"theme_color": "#a855f7",
|
"theme_color": "#a855f7",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/brand-mark.svg",
|
"src": "/icon.svg",
|
||||||
"sizes": "any",
|
"sizes": "any",
|
||||||
"type": "image/svg+xml"
|
"type": "image/svg+xml"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user