From 0a185077af7f80f3f06346bf61b9de2e36be7c70 Mon Sep 17 00:00:00 2001 From: Hammed Abass Date: Thu, 16 Jul 2026 18:11:06 +0200 Subject: [PATCH] feat(docs): refine product showcase and branding --- docs/app/base.css | 102 ---- docs/app/footer.css | 3 +- docs/app/icon.svg | 37 +- docs/app/layout.tsx | 2 + docs/app/page.tsx | 2 +- docs/app/privacy/privacy-document.css | 3 +- docs/app/responsive.css | 65 --- docs/components/brand.tsx | 71 +-- docs/components/header.css | 115 ++++ docs/components/hero-device.css | 490 +++++++++++++++++ docs/components/hero-illustration.tsx | 496 +++++++++++------ docs/components/hero-scene.css | 745 +++++++++++++++++++------- docs/components/icons.tsx | 11 +- docs/components/platform-scene.css | 3 +- docs/components/site-footer.tsx | 2 +- docs/components/site-header.tsx | 59 +- docs/package-lock.json | 69 +++ docs/package.json | 1 + docs/public/brand-mark.svg | 43 +- docs/public/site.webmanifest | 2 +- 20 files changed, 1658 insertions(+), 663 deletions(-) create mode 100644 docs/components/header.css create mode 100644 docs/components/hero-device.css diff --git a/docs/app/base.css b/docs/app/base.css index f47fd3f..b678efb 100644 --- a/docs/app/base.css +++ b/docs/app/base.css @@ -137,107 +137,6 @@ p { 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 { display: inline-flex; min-height: 52px; @@ -322,4 +221,3 @@ p { opacity: 1; transform: translateY(0); } - diff --git a/docs/app/footer.css b/docs/app/footer.css index e52838a..074edb6 100644 --- a/docs/app/footer.css +++ b/docs/app/footer.css @@ -27,7 +27,7 @@ background: white; } -.footer-mark svg { +.footer-mark img { width: 32px; height: 32px; } @@ -100,4 +100,3 @@ .footer-bottom p { margin: 0; } - diff --git a/docs/app/icon.svg b/docs/app/icon.svg index eaf36b9..f8eb118 100644 --- a/docs/app/icon.svg +++ b/docs/app/icon.svg @@ -1,10 +1,29 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/app/layout.tsx b/docs/app/layout.tsx index 1ce3158..443c678 100644 --- a/docs/app/layout.tsx +++ b/docs/app/layout.tsx @@ -3,10 +3,12 @@ import type { ReactNode } from "react"; import { SiteFooter } from "@/components/site-footer"; import { SiteHeader } from "@/components/site-header"; import "./base.css"; +import "../components/header.css"; import "./home.css"; import "./footer.css"; import "./privacy/privacy-document.css"; import "../components/hero-scene.css"; +import "../components/hero-device.css"; import "../components/transfer-flow.css"; import "../components/invitation-scene.css"; import "../components/approval-scene.css"; diff --git a/docs/app/page.tsx b/docs/app/page.tsx index 98d936b..a5eb2ef 100644 --- a/docs/app/page.tsx +++ b/docs/app/page.tsx @@ -140,7 +140,7 @@ export default function HomePage() { -
+
diff --git a/docs/app/privacy/privacy-document.css b/docs/app/privacy/privacy-document.css index c722f99..1b9dfb2 100644 --- a/docs/app/privacy/privacy-document.css +++ b/docs/app/privacy/privacy-document.css @@ -175,7 +175,7 @@ backdrop-filter: blur(14px); } -.privacy-mark-card > svg { +.privacy-mark-card > img { position: relative; z-index: 2; width: 112px; @@ -657,4 +657,3 @@ color: white; text-decoration: none; } - diff --git a/docs/app/responsive.css b/docs/app/responsive.css index 95b1ca1..463fb84 100644 --- a/docs/app/responsive.css +++ b/docs/app/responsive.css @@ -37,51 +37,6 @@ } @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 { padding-top: 128px; } @@ -155,26 +110,6 @@ 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 { min-height: auto; padding: 115px 0 72px; diff --git a/docs/components/brand.tsx b/docs/components/brand.tsx index ffcb2ad..1c15db2 100644 --- a/docs/components/brand.tsx +++ b/docs/components/brand.tsx @@ -1,64 +1,43 @@ import Link from "next/link"; +import Image from "next/image"; -type BrandMarkProps = { +type BrandAssetProps = { className?: string; title?: string; }; -export function BrandMark({ className, title }: BrandMarkProps) { +export function BrandMark({ className, title }: BrandAssetProps) { return ( - - - - - - - - - - - - - - - - + unoptimized + /> + ); +} + +export function AppIcon({ className, title }: BrandAssetProps) { + return ( + {title ); } export function Brand({ compact = false }: { compact?: boolean }) { return ( - - - + {!compact && VniDrop} ); diff --git a/docs/components/header.css b/docs/components/header.css new file mode 100644 index 0000000..62a714a --- /dev/null +++ b/docs/components/header.css @@ -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; + } +} diff --git a/docs/components/hero-device.css b/docs/components/hero-device.css new file mode 100644 index 0000000..66a75e8 --- /dev/null +++ b/docs/components/hero-device.css @@ -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; + } +} diff --git a/docs/components/hero-illustration.tsx b/docs/components/hero-illustration.tsx index 37fbfd1..270328e 100644 --- a/docs/components/hero-illustration.tsx +++ b/docs/components/hero-illustration.tsx @@ -2,6 +2,8 @@ import type { CSSProperties, PointerEvent } from "react"; import { useRef } from "react"; +import { motion, useReducedMotion } from "motion/react"; +import { BrandMark } from "@/components/brand"; import { Icon } from "@/components/icons"; type StageStyle = CSSProperties & { @@ -9,12 +11,16 @@ type StageStyle = CSSProperties & { "--pointer-y": string; }; +const cycle = 10.5; +const rest = 1.2; + export function HeroIllustration() { const stageRef = useRef(null); + const reduceMotion = useReducedMotion(); const updateParallax = (event: PointerEvent) => { const stage = stageRef.current; - if (!stage || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return; + if (!stage || reduceMotion) return; const bounds = stage.getBoundingClientRect(); const x = ((event.clientX - bounds.left) / bounds.width - 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"); }; + const repeating = { duration: cycle, repeat: Infinity, repeatDelay: rest }; + return (
); diff --git a/docs/components/hero-scene.css b/docs/components/hero-scene.css index d46f06a..f0beacf 100644 --- a/docs/components/hero-scene.css +++ b/docs/components/hero-scene.css @@ -1,7 +1,7 @@ -/* Hero transfer scene */ +/* Coordinated product transfer stage */ .hero-visual { position: relative; - width: min(100%, 730px); + width: min(100%, 760px); margin: 0; } @@ -10,238 +10,597 @@ --pointer-y: 0; position: relative; width: 100%; - aspect-ratio: 1.13; + aspect-ratio: 1.17; isolation: isolate; - perspective: 1200px; + perspective: 1400px; } -.hero-grid { +.hero-stage-grid { position: absolute; z-index: -3; - inset: 9% 2% 4% 7%; - border: 1px solid rgba(168, 85, 247, 0.14); - border-radius: 50%; - background-image: - linear-gradient(rgba(121, 82, 138, 0.07) 1px, transparent 1px), - linear-gradient(90deg, rgba(121, 82, 138, 0.07) 1px, transparent 1px); - background-size: 32px 32px; - transform: rotateX(64deg) rotateZ(-8deg) translateZ(-70px); - mask-image: radial-gradient(circle, black 10%, transparent 70%); + inset: 3% 0 4% 1%; + overflow: hidden; + border: 1px solid rgba(159, 132, 173, 0.15); + border-radius: 44px; + background: + linear-gradient(rgba(110, 86, 122, 0.055) 1px, transparent 1px), + linear-gradient(90deg, rgba(110, 86, 122, 0.055) 1px, transparent 1px), + radial-gradient(circle at 72% 35%, rgba(192, 132, 252, 0.13), transparent 38%), + 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; z-index: -2; + top: 18%; + right: 9%; + width: 45%; + aspect-ratio: 1; 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; } -.hero-glow-one { - top: 22%; - right: 8%; - 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 { +.desktop-window-bar { + position: relative; + z-index: 2; display: grid; - width: 34px; + grid-template-columns: 1fr auto 1fr; + align-items: center; height: 34px; - place-items: center; - border-radius: 10px; - background: var(--brand-100); - color: var(--brand-600); + padding: 0 11px; + border-bottom: 1px solid #e9e5eb; + border-radius: 20px 20px 0 0; + background: rgba(248, 247, 249, 0.92); } -.status-icon svg { - width: 17px; +.window-controls { + display: flex; + gap: 5px; } -.hero-status strong, -.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; +.window-controls i { width: 7px; height: 7px; border-radius: 50%; - background: #2bc477; - box-shadow: 0 0 0 4px rgba(43, 196, 119, 0.13); - animation: status-pulse 2.4s ease-in-out infinite; + background: #d8d2dc; } -.hero-file-label { - position: absolute; - z-index: 4; - bottom: 7%; - left: 7%; +.window-controls i:first-child { background: #c084fc; } + +.window-title { + color: #777078; + 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; + 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; gap: 11px; - padding: 10px 13px; - border: 1px solid rgba(222, 211, 228, 0.95); + padding: 9px; + border: 1px solid #e9e5eb; border-radius: 14px; - background: rgba(255, 255, 255, 0.9); - 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; + background: #f7f6f8; } -.file-type-icon { +.file-collage { display: grid; - width: 37px; - height: 37px; + width: 64px; + 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; border-radius: 10px; - background: linear-gradient(135deg, var(--brand-400), var(--brand-600)); - color: white; - font-family: var(--font-mono); - font-size: 8px; + background: linear-gradient(135deg, #ead2fe, #c084fc); + color: #5c1bb8; + font-size: 9px; font-weight: 800; } -.hero-file-label strong, -.hero-file-label small { +.receiver-identity { + 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; + 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 { - font-size: 10px; +.desktop-transfer-foot { + 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 { - color: var(--ink-muted); +.desktop-transfer-foot span { + 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; } +.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; +} + diff --git a/docs/components/icons.tsx b/docs/components/icons.tsx index 905d4c1..9979320 100644 --- a/docs/components/icons.tsx +++ b/docs/components/icons.tsx @@ -65,7 +65,12 @@ export function Icon({ name, ...props }: IconProps) { ), github: ( - + ), globe: ( <> @@ -125,9 +130,9 @@ export function Icon({ name, ...props }: IconProps) { return (

Project

- GitHub + GitHub -
+
- - - GitHub - - + View on GitHub +
- ); } diff --git a/docs/package-lock.json b/docs/package-lock.json index 7548bbf..602efcb 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,6 +8,7 @@ "name": "vnidrop-site", "version": "0.1.0", "dependencies": { + "motion": "^12.42.2", "next": "16.2.10", "react": "19.2.7", "react-dom": "19.2.7" @@ -3433,6 +3434,33 @@ "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": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4489,6 +4517,47 @@ "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": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", diff --git a/docs/package.json b/docs/package.json index 23a84f9..94278a6 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,6 +12,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { + "motion": "^12.42.2", "next": "16.2.10", "react": "19.2.7", "react-dom": "19.2.7" diff --git a/docs/public/brand-mark.svg b/docs/public/brand-mark.svg index ed04cc6..5598da1 100644 --- a/docs/public/brand-mark.svg +++ b/docs/public/brand-mark.svg @@ -1,21 +1,26 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/public/site.webmanifest b/docs/public/site.webmanifest index 8ec7d42..1e96ea1 100644 --- a/docs/public/site.webmanifest +++ b/docs/public/site.webmanifest @@ -8,7 +8,7 @@ "theme_color": "#a855f7", "icons": [ { - "src": "/brand-mark.svg", + "src": "/icon.svg", "sizes": "any", "type": "image/svg+xml" }