14 Commits

Author SHA1 Message Date
e7b053bd76 fix: improve About section positioning with sticky background and relative content 2025-10-22 14:18:11 +02:00
d197ca74ad refactor: extract feature cards data and add overflow styles to animations 2025-10-22 14:09:19 +02:00
0ca6a563b1 style: add consistent leading and tracking properties to text components 2025-10-22 13:42:26 +02:00
f6841df98f docs: add documentation for download page, 404 page, typography and button components 2025-10-22 13:24:58 +02:00
8aa5309e36 refactor: remove unnecessary relative positioning from components 2025-10-22 13:21:14 +02:00
076207c192 Merge branch 'development' 2025-10-22 13:17:38 +02:00
fad531667e fix: update button outline style to use rem units and add font weight 2025-10-22 13:09:56 +02:00
d03b67df7d refactor: replace hardcoded text styles with reusable Text components 2025-10-22 13:07:51 +02:00
bca730681e refactor: replace hardcoded text elements with reusable Text components in Hero section 2025-10-22 13:01:08 +02:00
02da6bb5ed fix: update 404 page HTML with latest build assets 2025-10-22 12:49:26 +02:00
08a309abea Merge branch 'development' 2025-10-21 17:32:10 +03:00
d344652a2f add crisp 2025-10-21 17:28:07 +03:00
bdbec5fd49 fix: update 404 page HTML with new static assets 2025-10-21 15:01:58 +02:00
4d89745a57 fix download link 2025-10-20 18:31:29 +03:00
71 changed files with 552 additions and 556 deletions

2
.gitignore vendored
View File

@@ -53,7 +53,7 @@ node_modules/
public
# Storybook build outputs
.out
out/
.storybook-out
# Temporary folders

View File

@@ -148,3 +148,84 @@ To create a new page, follow these steps:
```
The new page will be accessible at `http://localhost:3000/new-page`.
### Download Page
The download page, located at `src/app/(main)/download/page.tsx`, provides users with download links for the Mycelium application across various operating systems. The page is composed of the following components:
- **DownloadHero**: Displays the main header and a grid of download cards for each supported platform (iOS, macOS, Windows, Android, and Linux).
- **DevHub**: Provides links to developer resources, including documentation, support channels, forums, and community groups.
- **Faqs**: A frequently asked questions section to address common user queries.
### Not Found Page
The `not-found.tsx` file at `src/app/not-found.tsx` defines a custom 404 error page. This page is displayed whenever a user navigates to a non-existent route. It features a clean and simple layout with a 404 message and a button that directs the user back to the homepage.
### Typography with `Texts.tsx`
The `src/components/Texts.tsx` file implements a flexible and consistent typography system using a factory pattern. It exports a set of reusable text components, such as `H1`, `P`, and `SectionHeader`, each with predefined styles and color variants.
This approach ensures that the visual hierarchy and design language remain consistent throughout the application. To use a text component, simply import it and use it like any other React component:
```tsx
import { H1, P } from '@/components/Texts';
function MyComponent() {
return (
<div>
<H1 color="accent">This is a heading</H1>
<P color="secondary">This is a paragraph.</P>
</div>
);
}
```
### Button Components
The `src/components/Button.tsx` file provides a polymorphic button component that can be rendered as either a `<button>` or a Next.js `<Link>`. It supports two main variants (`solid` and `outline`) and multiple color schemes.
This component is used throughout the application to ensure that all buttons and links have a consistent look and feel. Example usage:
```tsx
import { Button } from '@/components/Button';
function MyComponent() {
return (
<div>
<Button variant="solid" color="cyan">Submit</Button>
<Button href="/about" variant="outline">Learn More</Button>
</div>
);
}
```
### Adding Images
To add images to the project while ensuring they are optimized, use the Next.js `Image` component. Follow these steps:
1. **Place Your Image**: Add your image file to the `src/images/` directory.
2. **Import the Image**: In the component where you want to display the image, import it at the top of the file:
```tsx
import myImage from '@/images/my-image.png';
```
3. **Use the `Image` Component**: Use the `Image` component from `next/image` to render your image. Provide the `src`, `alt`, `width`, and `height` props for proper rendering and accessibility.
```tsx
import Image from 'next/image';
import myImage from '@/images/my-image.png';
export function MyComponent() {
return (
<Image
src={myImage}
alt="A descriptive alt text for accessibility"
width={500}
height={300}
priority // Optional: Add this if the image is critical for the initial page load
/>
);
}
```

View File

@@ -1,9 +1,12 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
trailingSlash: true,
images: {
unoptimized: true,
},
}
module.exports = nextConfig

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-1be831200e60c5c0.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();

View File

@@ -1 +0,0 @@
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[698],{4631:function(e,t,i){Promise.resolve().then(i.bind(i,264)),Promise.resolve().then(i.bind(i,6365))},264:function(e,t,i){"use strict";i.d(t,{AnimatedSection:function(){return s}});var n=i(7437),r=i(2265),o=i(8733),a=i(4915);function s(e){let{children:t}=e,i=(0,r.useRef)(null),s=(0,o.Y)(i,{once:!0,margin:"-20% 0px -20% 0px"});return(0,n.jsx)(a.E.section,{ref:i,initial:{opacity:0,y:50},animate:{opacity:s?1:0,y:s?0:50},transition:{duration:.5},children:t})}},6365:function(e,t,i){"use strict";i.d(t,{default:function(){return s}});var n=i(7437),r=i(6648),o=i(4915);let a=[{name:"Download for iOS & MacOS",description:"Download Mycelium App from the Apple Store.",href:"https://apps.apple.com/us/app/mycelium-network/id6504277565",icon:{src:"/_next/static/media/apple.2d4c25bd.svg",height:80,width:80,blurWidth:0,blurHeight:0}},{name:"Download for Windows",description:"Download the Mycelium App for Windows directly from its Github repository.",href:"https://github.com/threefoldtech/myceliumflut/releases",icon:{src:"/_next/static/media/windows.6f805c4f.svg",height:80,width:80,blurWidth:0,blurHeight:0}},{name:"Download for Android",description:"Download Mycelium from the Google Play Store.",href:"https://play.google.com/store/apps/details?id=tech.threefold.mycelium&pli=1",icon:{src:"/_next/static/media/android.de815da5.svg",height:80,width:80,blurWidth:0,blurHeight:0}},{name:"Download for Linux",description:"Download the Mycelium binary for Linux directly from its Github repository.",href:"https://github.com/threefoldtech/mycelium/releases",icon:{src:"/_next/static/media/linux.2d41869b.svg",height:312,width:266,blurWidth:0,blurHeight:0}}];function s(){return(0,n.jsx)("div",{className:" py-16 sm:py-32",children:(0,n.jsxs)("div",{className:"mx-auto max-w-7xl px-6 lg:px-8",children:[(0,n.jsxs)("div",{className:"mx-auto max-w-2xl lg:mx-0",children:[(0,n.jsx)(o.E.h2,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{duration:.5},className:"text-5xl lg:text-6xl font-medium tracking-tight text-gray-900",children:"Download Mycelium"}),(0,n.jsxs)(o.E.p,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{duration:.5,delay:.2},className:"mt-6 text-lg/8 text-gray-600",children:["Get Mycelium for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized network—seamlessly and efficiently. Not sure how it works?"," ",(0,n.jsx)("a",{href:"https://threefold.info/mycelium_network/docs/",className:"text-gray-900 hover:text-cyan-500 transition-colors font-semibold underline",children:"Read the manual."})]})]}),(0,n.jsx)("div",{className:"mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-none",children:(0,n.jsx)("dl",{className:"grid max-w-xl grid-cols-1 gap-x-8 gap-y-16 lg:max-w-none md:grid-cols-2 lg:grid-cols-4",children:a.map(e=>(0,n.jsxs)("div",{className:"flex flex-col rounded-lg border border-gray-200 p-8 shadow-sm transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20",children:[(0,n.jsxs)("dt",{className:"text-base/7 font-semibold text-gray-900",children:[(0,n.jsx)("div",{className:"mb-6 flex h-10 w-10 items-center justify-center",children:(0,n.jsx)(r.default,{src:e.icon,alt:"",className:"h-10 w-10"})}),e.name]}),(0,n.jsxs)("dd",{className:"mt-1 flex flex-auto flex-col text-base/7 text-gray-600",children:[(0,n.jsx)("p",{className:"flex-auto",children:e.description}),(0,n.jsx)("p",{className:"mt-6",children:(0,n.jsxs)("a",{href:e.href,className:"text-sm/6 font-semibold text-cyan-500 hover:text-cyan-500",children:["Download Now ",(0,n.jsx)("span",{"aria-hidden":"true",children:"→"})]})})]})]},e.name))})})]})})}},8733:function(e,t,i){"use strict";i.d(t,{Y:function(){return o}});var n=i(2265);i(9047);let r={some:0,all:1};function o(e,{root:t,margin:i,amount:o,once:a=!1}={}){let[s,l]=(0,n.useState)(!1);return(0,n.useEffect)(()=>{if(!e.current||a&&s)return;let n={root:t&&t.current||void 0,margin:i,amount:o};return function(e,t,{root:i,margin:n,amount:o="some"}={}){var a;let s=("string"==typeof(a=e)?a=document.querySelectorAll(a):a instanceof Element&&(a=[a]),Array.from(a||[])),l=new WeakMap,c=new IntersectionObserver(e=>{e.forEach(e=>{let i=l.get(e.target);if(!!i!==e.isIntersecting){if(e.isIntersecting){let i=t(e);"function"==typeof i?l.set(e.target,i):c.unobserve(e.target)}else i&&(i(e),l.delete(e.target))}})},{root:i,rootMargin:n,threshold:"number"==typeof o?o:r[o]});return s.forEach(e=>c.observe(e)),()=>c.disconnect()}(e.current,()=>(l(!0),a?void 0:()=>l(!1)),n)},[t,e,i,a,o]),s}}},function(e){e.O(0,[184,971,23,744],function(){return e(e.s=4631)}),_N_E=e.O()}]);

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[95],{5352:function(e,n,s){Promise.resolve().then(s.bind(s,7582)),Promise.resolve().then(s.bind(s,2664))}},function(e){e.O(0,[501,184,480,39,557,971,23,744],function(){return e(e.s=5352)}),_N_E=e.O()}]);

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[409],{3521:function(){}},function(n){n.O(0,[971,23,744],function(){return n(n.s=3521)}),_N_E=n.O()}]);

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{7499:function(e,n,_){Promise.resolve().then(_.t.bind(_,7856,23)),Promise.resolve().then(_.t.bind(_,1983,23))},1983:function(){},7856:function(e){e.exports={style:{fontFamily:"'__Inter_f367f3', '__Inter_Fallback_f367f3'",fontStyle:"normal"},className:"__className_f367f3",variable:"__variable_f367f3"}}},function(e){e.O(0,[348,971,23,744],function(){return e(e.s=7499)}),_N_E=e.O()}]);

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[160],{49:function(e,n,s){Promise.resolve().then(s.t.bind(s,231,23)),Promise.resolve().then(s.bind(s,7582)),Promise.resolve().then(s.bind(s,2664))}},function(e){e.O(0,[501,184,480,39,557,971,23,744],function(){return e(e.s=49)}),_N_E=e.O()}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{4025:function(e,n,t){Promise.resolve().then(t.t.bind(t,5751,23)),Promise.resolve().then(t.t.bind(t,6513,23)),Promise.resolve().then(t.t.bind(t,6130,23)),Promise.resolve().then(t.t.bind(t,9275,23)),Promise.resolve().then(t.t.bind(t,5324,23)),Promise.resolve().then(t.t.bind(t,1343,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,23],function(){return n(1028),n(4025)}),_N_E=e.O()}]);

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[888],{1597:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return u(2239)}])}},function(n){var _=function(_){return n(n.s=_)};n.O(0,[774,179],function(){return _(1597),_(6036)}),_N_E=n.O()}]);

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[820],{1981:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return u(3387)}])}},function(n){n.O(0,[888,774,179],function(){return n(n.s=1981)}),_N_E=n.O()}]);

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
!function(){"use strict";var e,t,n,r,o,u,i,c,f,a={},l={};function d(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={exports:{}},r=!0;try{a[e](n,n.exports,d),r=!1}finally{r&&delete l[e]}return n.exports}d.m=a,e=[],d.O=function(t,n,r,o){if(n){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u<e.length;u++){for(var n=e[u][0],r=e[u][1],o=e[u][2],c=!0,f=0;f<n.length;f++)i>=o&&Object.keys(d.O).every(function(e){return d.O[e](n[f])})?n.splice(f--,1):(c=!1,o<i&&(i=o));if(c){e.splice(u--,1);var a=r();void 0!==a&&(t=a)}}return t},d.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,r){if(1&r&&(e=this(e)),8&r||"object"==typeof e&&e&&(4&r&&e.__esModule||16&r&&"function"==typeof e.then))return e;var o=Object.create(null);d.r(o);var u={};t=t||[null,n({}),n([]),n(n)];for(var i=2&r&&e;"object"==typeof i&&!~t.indexOf(i);i=n(i))Object.getOwnPropertyNames(i).forEach(function(t){u[t]=function(){return e[t]}});return u.default=function(){return e},d.d(o,u),o},d.d=function(e,t){for(var n in t)d.o(t,n)&&!d.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce(function(t,n){return d.f[n](e,t),t},[]))},d.u=function(e){},d.miniCssF=function(e){},d.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r={},o="_N_E:",d.l=function(e,t,n,u){if(r[e]){r[e].push(t);return}if(void 0!==n)for(var i,c,f=document.getElementsByTagName("script"),a=0;a<f.length;a++){var l=f[a];if(l.getAttribute("src")==e||l.getAttribute("data-webpack")==o+n){i=l;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,d.nc&&i.setAttribute("nonce",d.nc),i.setAttribute("data-webpack",o+n),i.src=d.tu(e)),r[e]=[t];var s=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=s.bind(null,i.onerror),i.onload=s.bind(null,i.onload),c&&document.head.appendChild(i)},d.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.tt=function(){return void 0===u&&(u={createScriptURL:function(e){return e}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(u=trustedTypes.createPolicy("nextjs#bundler",u))),u},d.tu=function(e){return d.tt().createScriptURL(e)},d.p="/_next/",i={272:0,348:0},d.f.j=function(e,t){var n=d.o(i,e)?i[e]:void 0;if(0!==n){if(n)t.push(n[2]);else if(/^(272|348)$/.test(e))i[e]=0;else{var r=new Promise(function(t,r){n=i[e]=[t,r]});t.push(n[2]=r);var o=d.p+d.u(e),u=Error();d.l(o,function(t){if(d.o(i,e)&&(0!==(n=i[e])&&(i[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",u.name="ChunkLoadError",u.type=r,u.request=o,n[1](u)}},"chunk-"+e,e)}}},d.O.j=function(e){return 0===i[e]},c=function(e,t){var n,r,o=t[0],u=t[1],c=t[2],f=0;if(o.some(function(e){return 0!==i[e]})){for(n in u)d.o(u,n)&&(d.m[n]=u[n]);if(c)var a=c(d)}for(e&&e(t);f<o.length;f++)r=o[f],d.o(i,r)&&i[r]&&i[r][0](),i[r]=0;return d.O(a)},(f=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(c.bind(null,0)),f.push=c.bind(null,f.push.bind(f))}();

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><defs><clipPath clipPathUnits="userSpaceOnUse" id="cp1"><path d="m2.09 33.33h8.58v24h-8.58z"/></clipPath><clipPath clipPathUnits="userSpaceOnUse" id="cp2"><path d="m13.33 33.33h32v38.19h-32z"/></clipPath></defs><style>.a{fill:#00b8db}</style><g clip-path="url(#cp1)"><path class="a" d="m5.9 33.7c-2.1 0-3.8 1.7-3.8 3.9v15.2c0 2.2 1.7 3.9 3.8 3.9 2.1 0 3.9-1.7 3.9-3.9v-15.2c0-2.2-1.8-3.9-3.9-3.9z"/></g><path class="a" d="m52 33.7c-2.1 0-3.8 1.7-3.8 3.9v15.2c0 2.2 1.7 3.9 3.8 3.9 2.1 0 3.9-1.7 3.9-3.9v-15.2c0-2.2-1.8-3.9-3.9-3.9z"/><g clip-path="url(#cp2)"><path class="a" d="m13.6 56.9c0 2.1 1.7 3.8 3.8 3.8v7.4c0 2.2 1.8 3.9 3.9 3.9 2.1 0 3.8-1.7 3.8-3.9v-7.4h7.7v7.4c0 2.2 1.7 3.9 3.9 3.9 2.1 0 3.8-1.7 3.8-3.9v-7.4c2.1 0 3.8-1.7 3.8-3.8v-22.9h-30.7z"/></g><path class="a" d="m38.6 18l3.4-4.1c0.7-0.8 0.5-2-0.3-2.7-0.8-0.6-2-0.5-2.7 0.3l-3.7 4.5c-1.9-0.9-4.1-1.4-6.3-1.4-2.3 0-4.5 0.5-6.4 1.4l-3.6-4.5c-0.7-0.8-1.9-1-2.8-0.3-0.8 0.7-0.9 1.9-0.2 2.7l3.3 4.2c-3.4 2.8-5.7 7-5.7 11.8h30.7c0-4.8-2.2-9.1-5.7-11.9zm-13.5 6.2c-1 0-1.9-0.9-1.9-1.9 0-1.1 0.9-2 1.9-2 1.1 0 2 0.9 2 2 0 1-0.9 1.9-2 1.9zm7.7 0c-1 0-1.9-0.9-1.9-1.9 0-1.1 0.9-2 1.9-2 1.1 0 1.9 0.9 1.9 2 0 1-0.8 1.9-1.9 1.9z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1 +0,0 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><defs><clipPath clipPathUnits="userSpaceOnUse" id="cp1"><path d="m1.33 25.33h50.59v46.27h-50.59z"/></clipPath><clipPath clipPathUnits="userSpaceOnUse" id="cp2"><path d="m28 7.6h13.33v13.73h-13.33z"/></clipPath></defs><style>.a{fill:#00b8db}</style><g clip-path="url(#cp1)"><path fill-rule="evenodd" class="a" d="m12.8 27c-4.8 1.5-8.5 5.4-10 10.3-1.1 3.8-1.9 10.2 1.3 18.8 0 0.1 3.1 8.6 10.8 13.2 3.7 2.2 8.5 2.1 12-0.3l0.1-0.1q0.2-0.1 0.4-0.3 0.3-0.2 0.7-0.2 0.3 0 0.6 0.2 0.3 0.2 0.5 0.4h0.1c3.5 2.4 8.2 2.5 11.9 0.2 6.9-4.1 10.1-11.2 10.7-12.8q-0.2 0-0.4 0c-3.7 0-7.1-1.4-9.7-3.9-2.6-2.6-4-6-4-9.6 0-6.4 4.5-11.8 10.6-13.2-1.5-1.2-3.2-2.2-5-2.8-8.1-2.6-13.9 3-14.6 3.6v0.1c-0.4 0.4-1 0.4-1.4 0l-0.1-0.1c-0.6-0.6-6.4-6.2-14.5-3.5z"/></g><g clip-path="url(#cp2)"><path fill-rule="evenodd" class="a" d="m31.3 10.9c-2.2 2.2-3.3 5.4-3.1 9.1 3.8 0.2 7.1-0.9 9.2-3.1 2.2-2.1 3.3-5.3 3.1-9-3.8-0.2-7 0.8-9.2 3z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" aria-label="GitHub" viewBox="0 0 512 512" id="github">
<rect width="512" height="512" fill="#1B1817" rx="15%"></rect>
<path fill="#fff" d="M335 499c14 0 12 17 12 17H165s-2-17 12-17c13 0 16-6 16-12l-1-50c-71 16-86-28-86-28-12-30-28-37-28-37-24-16 1-16 1-16 26 2 40 26 40 26 22 39 59 28 74 22 2-17 9-28 16-35-57-6-116-28-116-126 0-28 10-51 26-69-3-6-11-32 3-67 0 0 21-7 70 26 42-12 86-12 128 0 49-33 70-26 70-26 14 35 6 61 3 67 16 18 26 41 26 69 0 98-60 120-117 126 10 8 18 24 18 48l-1 70c0 6 3 12 16 12z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 563 B

View File

@@ -1 +0,0 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 266 312" width="266" height="312"><style>.a{fill:#00b8db}</style><path class="a" d="m132.6 291.6q-19.5 0-30 5.3v-0.3c-5 6-10.6 9.1-18.4 9.1-4.9 0-12.6-1.9-23-5.7-10.5-3.6-19.8-6.4-27.9-8.2-0.8-0.2-2.6-0.6-5.5-1-2.8-0.5-5.4-0.9-7.7-1.4-2.1-0.5-4.5-1.1-7.1-2.1q-3.8-1.1-6-3-2.1-1.9-2.1-4.3 0-2.4 1-5.1c0.7-1.1 1.4-2.2 2.1-3.2 0.7-1.1 1.3-2.1 1.7-3.1 0.6-0.9 1-1.8 1.4-2.8 0.4-0.9 0.8-1.8 1-2.9 0.2-1 0.4-2 0.4-3 0-1-0.4-4-1.2-9.3q-1.2-7.8-1.2-9.9c0-4.4 1-7.9 3.2-10.4 2.2-2.5 4.3-3.8 6.5-3.8h11.5c0.9 0 2.3-0.5 4.4-1.7 0.7-1.6 1.3-2.9 1.7-4.1 0.5-1.2 0.7-2.1 0.9-2.5 0.2-0.6 0.4-1.2 0.6-1.7 0.4-0.7 0.9-1.5 1.6-2.3q-1.2-1.5-1.2-3.9c0-1.1 0-2.1 0.2-2.7 0-3.6 1.7-8.7 5.3-15.4l3.5-6.3c2.9-5.4 5.1-9.4 6.7-13.4 1.7-4 3.5-10 5.5-18q2.4-10.5 11.4-21l7.5-9c5.2-6 8.6-11 10.5-15 1.9-4 2.9-9 2.9-13 0-2-0.5-8-1.6-18-1-10-1.5-20-1.5-29 0-7 0.6-12 1.9-17 1.3-5 3.6-10 7-14 3-4 7-8 13-10q9-3 21-3c3 0 6 0 9 1q4.5 0 12 3c4 2 8 4 11 7 4 3 7 8 10 13 2 6 4 12 5 20 1 5 1 10 2 17 0 6 1 10 1 13 1 3 1 7 2 12 1 4 2 8 4 11 2 4 4 8 7 12 3 5 7 10 11 16 9 10 16 21 20 32 5 10 8 23 8 36.9q0 10.3-3 20.1c2 0 3 0.8 4 2.2 1 1.4 2 4.4 3 9.1l1 7.4c1 2.2 2 4.3 5 6.1 2 1.8 4 3.3 7 4.5 2 1 5 2.4 7 4.2q3 3 3 6.3c0 3.4-1 5.9-3 7.7-2 2-4 3.4-7 4.3-2 1-6 3-12 5.8q-7.5 4.4-15 10.8l-10 8.5c-4 3.9-8 6.7-11 8.4-3 1.8-7 2.7-11 2.7l-7-0.8c-8-2.1-13-6.1-16-12.2-16-1.9-29-2.9-37-2.9m-27.9-212.3c-4-2-5-5-5-10 0-3 0-5 2-7 1-2 3-3 5-3 2 0 3 1 5 3 1 3 2 6 2 9v2h1v-1c1 0 1-2 1-6 0-3 0-6-2-9-2-3-4-5-8-5-3 0-6 2-7 5-2 4-2.4 7-2.4 12 0 4 1.4 8 5.4 12 1-1 2-1 3-2zm33-4c-1-1-1-3-1-5 0-4 0-6 2-9q3-3 6-3c3 0 5 2 7 4 1 3 2 5 2 8q0 7.5-6 9c0 0 1 1 2 1 2 0 3 1 5 2 1-6 2-10 2-15 0-6-1-10-3-13-3-3-6-4-10-4q-4.5 0-9 3c-2 3-3 5-3 8 0 5 1 9 3 13 1 0 2 1 3 1zm12 16c-13 9-23 13-31 13-7 0-14-3-20-8 1 2 2 4 3 5l6 6c4 4 9 6 14 6 7 0 15-4 25-11l9-6c2-2 4-4 4-7 0-1 0-2-1-2-1-2-6-5-16-8-9-4-16-6-20-6q-4.5 0-15 6c-6 4-10 8-10 12 0 0 1 1 2 3 6 5 12 8 18 8 8 0 18-4 31-14v2c1 0 1 1 1 1zm-39-22c0-5-2-8-5-8 0 0 0 1-1 1v2h3c0 2 1 3 1 5zm119 151c1 0 1-0.4 1-1.3 0-2.2-1-4.8-4-7.7-3-3-8-4.9-14-5.7-1-0.1-2-0.1-2-0.1-1-0.2-1-0.2-2-0.2-1-0.1-3-0.3-4-0.5 3-9.3 4-17.5 4-24.7 0-10-2-17-6-23-4-6-8-9-13-10-1 1-1 1-1 2 5 2 10 6 13 12 3 7 4 13 4 20 0 5.6-1 13.9-5 24.5-4 1.6-8 5.3-11 11.1 0 0.9 0 1.4 1 1.4 0 0 1-0.9 2-2.6 2-1.7 3-3.4 5-5.1 3-1.7 5-2.6 8-2.6 5 0 10 0.7 13 2.1 4 1.3 6 2.7 7 4.3q1.5 2.2 3 4.2c0 1.3 1 1.9 1 1.9zm-84-156c2 0 3 2 4 5h2c-1-1-1-2-1-3 0-1 0-2-1-3-1-1-2-2-3-2 0 0-1 1-2 1 0 1 1 1 1 2zm-17 15c0 1-1 1-1 1h-1c-1 0-1-1-2-2 0 0-1-1-1-2 0-1 0-1 1-1l2 1c1 1 2 2 2 3zm44 214c4 7.5 11 11.3 19 11.3q3 0 6-0.9c2-0.4 4-1.1 5-1.9 1-0.7 2-1.4 3-2.2 2-0.7 2-1.2 3-1.7l17-14.7c4-3.2 8-6 13-8.4 4-2.4 8-4 10-4.9 3-0.8 5-2 7-3.6 1-1.5 2-3.4 2-5.8 0-2.9-2-5.1-4-6.7-2-1.6-4-2.7-6-3.4-2-0.7-4-2.3-7-5-2-2.6-4-6.2-5-10.9l-1-5.8c-1-2.7-1-4.7-2-5.8 0-0.3 0-0.4-1-0.4-1 0-3 0.9-4 2.6-2 1.7-4 3.6-6 5.6-1 2-4 3.8-6 5.5-3 1.7-6 2.6-8 2.6-8 0-12-2.2-15-6.5-2-3.2-3-6.9-4-11.1-2-1.7-3-2.6-5-2.6-5 0-7 5.2-7 15.7v31.1c0 0.9-1 2.9-1 6-1 3.1-1 6.6-1 10.6l-2 11.1v0.1m-145-5.2q13.9 2 32.1 8.7c12.1 4.4 19.5 6.7 22.2 6.7 7 0 12.8-3.1 17.6-9.1 1-2 1-4.2 1-6.9q0-14.1-17.1-35.9l-6.8-9.1c-1.4-1.9-3.1-4.8-5.3-8.7-2.1-3.9-4-6.9-5.5-9-1.3-2.3-3.4-4.6-6.1-6.9-2.6-2.3-5.6-3.8-8.9-4.6-4.2 0.8-7.1 2.2-8.5 4.1-1.4 1.9-2.2 4-2.4 6.2-0.3 2.1-0.9 3.5-1.9 4.2-1 0.6-2.7 1.1-5 1.6-0.5 0-1.4 0-2.7 0.1h-2.7c-5.3 0-8.9 0.6-10.8 1.6-2.5 2.9-3.8 6.2-3.8 9.7q0 2.4 1.2 8.1c0.8 3.7 1.2 6.7 1.2 8.8 0 4.1-1.2 8.2-3.7 12.3-2.5 4.3-3.8 7.5-3.8 9.8 1 3.9 7.6 6.6 19.7 8.2m33.3-90.9c0-6.9 1.8-14.5 5.5-23.5 3.6-9 7.2-15 10.7-19-0.2-1-0.7-1-1.5-1l-1-1c-2.9 3-6.4 10-10.6 20-4.2 9-6.4 17.3-6.4 23.4 0 4.5 1.1 8.4 3.1 11.8 2.2 3.3 7.5 8.1 15.9 14.2l10.6 6.9c11.3 9.8 17.3 16.6 17.3 20.6 0 2.1-1 4.2-4 6.5-2 2.4-4.7 3.6-7 3.6-0.2 0-0.3 0.2-0.3 0.7 0 0.1 1 2.1 3.1 6 4.2 5.7 13.2 8.5 25.2 8.5 22 0 39-9 52-27 0-5 0-8.1-1-9.4v-3.7c0-6.5 1-11.4 3-14.6 2-3.2 4-4.7 7-4.7 2 0 4 0.7 6 2.2 1-7.7 1-14.4 1-20.4 0-9.1 0-16.6-2-23.6-1-6-3-11-5-15l-6-9c-2-3-3-6-5-9-1-4-2-7-2-12-3-5-5-10-8-15-2-5-4-10-6-14l-9 7c-10 7-18 10-25 10-6 0-11-1-14-5l-6-5c0 3-1 7-3 11l-6.3 12c-2.8 7-4.3 11-4.6 14-0.4 2-0.7 4-0.9 4l-7.5 15c-8.1 15-12.2 28.9-12.2 40.4 0 2.3 0.2 4.7 0.6 7.1-4.5-3.1-6.7-7.4-6.7-13zm54.7-116.7c-1 0-1 0-1-1 0-1 0-2 1-3 2 0 3-1 3-1 1 0 1 1 1 1 0 1-1 2-3 4z"/></svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

View File

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

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

View File

@@ -1 +0,0 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80"><defs><clipPath clipPathUnits="userSpaceOnUse" id="cp1"><path d="m2.92 11.31h25.08v26.02h-25.08z"/></clipPath><clipPath clipPathUnits="userSpaceOnUse" id="cp2"><path d="m34.67 11.31h25.25v26.02h-25.25z"/></clipPath><clipPath clipPathUnits="userSpaceOnUse" id="cp3"><path d="m2.92 42.67h25.08v25.64h-25.08z"/></clipPath><clipPath clipPathUnits="userSpaceOnUse" id="cp4"><path d="m34.67 42.67h25.25v25.64h-25.25z"/></clipPath></defs><style>.a{fill:#00b8db}</style><g clip-path="url(#cp1)"><path class="a" d="m26.9 11.3h-22.8c-0.7 0-1.2 0.5-1.2 1.2v22.8c0 0.6 0.5 1.1 1.2 1.1h22.8c0.6 0 1.1-0.5 1.1-1.1v-22.8c0-0.7-0.5-1.2-1.1-1.2z"/></g><g clip-path="url(#cp2)"><path class="a" d="m58.8 11.3h-22.8c-0.6 0-1.2 0.5-1.2 1.2v22.8c0 0.6 0.6 1.1 1.2 1.1h22.8c0.6 0 1.1-0.5 1.1-1.1v-22.8c0-0.7-0.5-1.2-1.1-1.2z"/></g><g clip-path="url(#cp3)"><path class="a" d="m26.9 43.2h-22.8c-0.7 0-1.2 0.5-1.2 1.2v22.8c0 0.6 0.5 1.1 1.2 1.1h22.8c0.6 0 1.1-0.5 1.1-1.1v-22.8c0-0.7-0.5-1.2-1.1-1.2z"/></g><g clip-path="url(#cp4)"><path class="a" d="m58.8 43.2h-22.8c-0.6 0-1.2 0.5-1.2 1.2v22.8c0 0.6 0.6 1.1 1.2 1.1h22.8c0.6 0 1.1-0.5 1.1-1.1v-22.8c0-0.7-0.5-1.2-1.1-1.2z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

20
package-lock.json generated
View File

@@ -14,11 +14,12 @@
"@types/node": "^20.10.8",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"clsx": "^2.1.0",
"clsx": "^2.1.1",
"framer-motion": "^10.15.0",
"next": "^14.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.7",
"typescript": "^5.3.3",
"use-debounce": "^10.0.0"
@@ -1881,9 +1882,10 @@
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
"node_modules/clsx": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
"integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
@@ -4942,6 +4944,16 @@
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
},
"node_modules/tailwind-merge": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
"integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwindcss": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz",

View File

@@ -16,11 +16,12 @@
"@types/node": "^20.10.8",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"clsx": "^2.1.0",
"clsx": "^2.1.1",
"framer-motion": "^10.15.0",
"next": "^14.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.7",
"typescript": "^5.3.3",
"use-debounce": "^10.0.0"

View File

@@ -1,5 +1,6 @@
import { type Metadata } from 'next'
import { Inter } from 'next/font/google'
import Script from 'next/script'
import clsx from 'clsx'
import '@/styles/tailwind.css'
@@ -29,7 +30,28 @@ export default function RootLayout({
}) {
return (
<html lang="en" className={clsx('bg-gray-50 antialiased', inter.variable)}>
<body>{children}</body>
<body>
{children}
{/* Crisp Chat */}
<Script
id="crisp-init"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.$crisp = [];
window.CRISP_WEBSITE_ID = "1a5a5241-91cb-4a41-8323-5ba5ec574da0";
(function () {
d = document;
s = d.createElement("script");
s.src = "https://client.crisp.chat/l.js";
s.async = 1;
d.getElementsByTagName("head")[0].appendChild(s);
})();
`,
}}
/>
</body>
</html>
)
}

View File

@@ -1,4 +1,5 @@
import { Button } from '@/components/Button'
import { P, SectionHeader, Small } from '@/components/Texts'
import { CirclesBackground } from '@/components/CirclesBackground'
import { Container } from '@/components/Container'
import { Layout } from '@/components/Layout'
@@ -8,13 +9,13 @@ export default function NotFound() {
<Layout>
<Container className="relative isolate flex h-full flex-col items-center justify-center py-20 text-center sm:py-32">
<CirclesBackground className="absolute top-1/2 left-1/2 -z-10 mt-44 w-272.5 -translate-x-1/2 -translate-y-1/2 mask-[linear-gradient(to_bottom,white_20%,transparent_75%)] stroke-gray-300/30" />
<p className="text-sm font-semibold text-gray-900">404</p>
<h1 className="mt-2 text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
<Small as="p" color="primary">404</Small>
<SectionHeader as="h1" className="mt-2">
Page not found
</h1>
<p className="mt-2 text-lg text-gray-600">
</SectionHeader>
<P color="secondary" className="mt-2">
Sorry, we couldnt find the page youre looking for.
</p>
</P>
<Button href="/" variant="outline" className="mt-8">
Go back home
</Button>

View File

@@ -1,4 +1,5 @@
import { AppStoreLink } from '@/components/AppStoreLink'
import { Eyebrow, P, SectionHeader } from '@/components/Texts'
import { Button } from '@/components/Button'
import { CircleBackground } from '@/components/CircleBackground'
import { Container } from '@/components/Container'
@@ -7,35 +8,41 @@ export function About() {
return (
<section
id="about"
className="relative overflow-hidden bg-gray-900 py-20 lg:py-32 lg:top-0 top-0"
className="relative bg-gray-900 py-20 lg:py-32"
>
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<div className="sticky top-0 flex h-screen items-center justify-center">
<CircleBackground color="#06b6d4" className="animate-spin-slower" />
</div>
<Container className="relative">
<div className="mx-auto max-w-3xl text-center">
<h2 className="text-base/7 font-semibold text-cyan-500">Our Mission</h2>
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl">
Discover Mycelium
</p>
<p className="mt-6 text-lg text-gray-300">
Mycelium is an unbreakable network, always finding the shortest path and providing 100% secure, peer-to-peer communication. But this is just the beginning.
</p>
<p className="mt-6 text-lg text-gray-300">
Our mission is to create a sustainable digital ecosystem where communication is seamless, data is secure, and scalability knows no bounds.
</p>
<div className="mt-8 flex justify-center">
<Button
href="https://threefold.info/mycelium_network/docs/"
target="_blank"
variant="outline"
color="white"
>
Learn More
</Button>
<div className="relative -mt-[100vh]">
<Container>
<div className="mx-auto max-w-3xl text-center">
<Eyebrow color="accent">Our Mission</Eyebrow>
<SectionHeader color="white" className="mt-2">
Discover Mycelium
</SectionHeader>
<P color="light" className="mt-6">
Mycelium is an unbreakable network, always finding the shortest path and
providing 100% secure, peer-to-peer communication. But this is just
the beginning.
</P>
<P color="light" className="mt-6">
Our mission is to create a sustainable digital ecosystem where
communication is seamless, data is secure, and scalability knows no
bounds.
</P>
<div className="mt-8 flex justify-center">
<Button
href="https://threefold.info/mycelium_network/docs/"
target="_blank"
variant="outline"
color="white"
>
Learn More
</Button>
</div>
</div>
</div>
</Container>
</Container>
</div>
</section>
)
}

View File

@@ -5,7 +5,7 @@ const baseStyles = {
solid:
'inline-flex justify-center rounded-lg py-2 px-3 text-sm font-semibold transition-colors',
outline:
'inline-flex justify-center rounded-lg border py-[calc(--spacing(2)-1px)] px-[calc(--spacing(3)-1px)] text-sm transition-colors',
'inline-flex justify-center rounded-lg border py-[calc(0.5rem-1px)] px-[calc(0.75rem-1px)] text-sm font-semibold transition-colors',
}
const variantStyles = {
@@ -17,7 +17,7 @@ const variantStyles = {
green: 'bg-green-500 text-white hover:bg-green-600',
},
outline: {
gray: 'border-gray-300 text-gray-700 hover:border-cyan-500 active:border-cyan-500',
gray: 'border-gray-300 text-gray-600 hover:border-cyan-500 active:border-cyan-500',
white: 'border-gray-300 text-white hover:border-cyan-500 active:border-cyan-500',
},
}

View File

@@ -1,4 +1,5 @@
import { AppStoreLink } from '@/components/AppStoreLink'
import { P, SectionHeader } from '@/components/Texts'
import { WindowsLink } from '@/components/WindowsLink'
import { AndroidLink } from './AndroidLink'
import { LinuxLink } from '@/components/LinuxLink'
@@ -14,14 +15,15 @@ export function CallToAction() {
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<CircleBackground color="#06b6d4" className="animate-spin-slower" />
</div>
<Container className="relative">
<Container>
<div className="mx-auto max-w-2xl text-center">
<h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl">
<SectionHeader as="h2" color="white">
Get Started Today
</h2>
<p className="mt-6 text-lg text-gray-300">
Download the Mycelium app and step into the future of secure, peer-to-peer networking; fast, private, and decentralized.
</p>
</SectionHeader>
<P color="lightSecondary" className="mt-6">
Download the Mycelium app and step into the future of secure,
peer-to-peer networking; fast, private, and decentralized.
</P>
<div className="mt-10 flex flex-wrap justify-center gap-x-6 gap-y-4">
<AppStoreLink color="white" />
<WindowsLink color="white" />

View File

@@ -2,6 +2,7 @@
import * as React from 'react';
import { motion, useReducedMotion } from 'framer-motion';
import clsx from 'clsx';
type Props = {
className?: string; // e.g. "w-full h-80"
@@ -135,7 +136,12 @@ export default function ContentDistribution({ className, bg = '#ffffff' }: Props
const prefersReduced = useReducedMotion();
return (
<div className={className} aria-hidden="true" role="img" style={{ background: bg }}>
<div
className={clsx('relative overflow-hidden', className)}
aria-hidden="true"
role="img"
style={{ background: bg }}
>
<svg viewBox={`0 0 ${W} ${H}`} width="100%" height="100%">
{/* subtle radial background + rings */}
<defs>

View File

@@ -1,3 +1,10 @@
import {
Eyebrow,
FeatureDescription,
P,
SectionHeader,
SecondaryFeatureTitle,
} from './Texts'
import {
BookOpenIcon,
LifebuoyIcon,
@@ -38,13 +45,15 @@ export function DevHub() {
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-5">
<div className="col-span-2">
<h2 className="text-base/7 font-semibold text-cyan-500 mb-2">Get Started</h2>
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-white">
<Eyebrow color="accent" className="mb-2">Get Started</Eyebrow>
<SectionHeader as="h2" color="white">
Developer Hub
</p>
<p className="mt-6 text-lg text-gray-300">
Our Developer Hub is a resource center for developers looking to build on top of Mycelium. Join our Developers community on telegram to get started.
</p>
</SectionHeader>
<P color="lightSecondary" className="mt-6">
Our Developer Hub is a resource center for developers looking to build
on top of Mycelium. Join our Developers community on telegram to get
started.
</P>
</div>
<dl className="col-span-3 grid grid-cols-1 gap-8 sm:grid-cols-2">
{features.map((feature) => (
@@ -59,10 +68,12 @@ export function DevHub() {
aria-hidden="true"
className="h-6 w-6 flex-none text-cyan-500 mb-4"
/>
<dt className="font-semibold text-white">
<SecondaryFeatureTitle as="dt" color="white">
{feature.name}
</dt>
<dd className="mt-2 text-gray-400">{feature.description}</dd>
</SecondaryFeatureTitle>
<FeatureDescription as="dd" color="secondary" className="mt-2">
{feature.description}
</FeatureDescription>
</a>
))}
</dl>

View File

@@ -1,6 +1,12 @@
'use client'
import Image from 'next/image';
import {
DownloadCardDescription,
DownloadCardTitle,
P,
PageHeader,
} from './Texts'
import { motion } from 'framer-motion';
import appleIcon from '@/images/apple.svg';
import windowsIcon from '@/images/windows.svg';
@@ -39,25 +45,30 @@ export default function DownloadHero() {
<div className=" py-16 sm:py-32">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl lg:mx-0">
<motion.h2
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className="text-5xl lg:text-6xl font-medium tracking-tight text-gray-900"
>
Download Mycelium
</motion.h2>
<motion.p
<PageHeader>Download Mycelium</PageHeader>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
className="mt-6 text-lg/8 text-gray-600"
>
Get Mycelium for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized networkseamlessly and efficiently. Not sure how it works?{' '}
<a href="https://threefold.info/mycelium_network/docs/" className="text-gray-900 hover:text-cyan-500 transition-colors font-semibold underline">
Read the manual.
</a>
</motion.p>
<P color="secondary" className="mt-6 text-lg/8">
Get Mycelium for Android, Windows, macOS, and iOS to securely
connect, store, and interact with the decentralized
networkseamlessly and efficiently. Not sure how it works?{' '}
<a
href="https://threefold.info/mycelium_network/docs/"
className="text-gray-900 hover:text-cyan-500 transition-colors font-semibold underline"
>
Read the manual.
</a>
</P>
</motion.div>
</div>
<div className="mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-none">
<dl className="grid max-w-xl grid-cols-1 gap-x-8 gap-y-16 lg:max-w-none md:grid-cols-2 lg:grid-cols-4">
@@ -66,20 +77,27 @@ export default function DownloadHero() {
key={feature.name}
className="flex flex-col rounded-lg border border-gray-200 p-8 shadow-sm transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
>
<dt className="text-base/7 font-semibold text-gray-900">
<DownloadCardTitle color="primary">
<div className="mb-6 flex h-10 w-10 items-center justify-center">
<Image src={feature.icon} alt="" className="h-10 w-10" />
</div>
{feature.name}
</dt>
<dd className="mt-1 flex flex-auto flex-col text-base/7 text-gray-600">
</DownloadCardTitle>
<DownloadCardDescription
as="dd"
color="secondary"
className="mt-1 flex flex-auto flex-col"
>
<p className="flex-auto">{feature.description}</p>
<p className="mt-6">
<a href={feature.href} className="text-sm/6 font-semibold text-cyan-500 hover:text-cyan-500">
<a
href={feature.href}
className="text-sm/6 font-semibold text-cyan-500 hover:text-cyan-500"
>
Download Now <span aria-hidden="true"></span>
</a>
</p>
</dd>
</DownloadCardDescription>
</div>
))}
</dl>

View File

@@ -1,4 +1,5 @@
import { Container } from '@/components/Container'
import { Answer, P, Question, SectionHeader } from './Texts'
const faqs = [
[
@@ -58,13 +59,10 @@ export function Faqs() {
>
<Container>
<div className="mx-auto max-w-2xl lg:mx-0">
<h2
id="faqs-title"
className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900"
>
<SectionHeader id="faqs-title" as="h2">
Frequently asked questions
</h2>
<p className="mt-2 text-lg text-gray-600">
</SectionHeader>
<P color="secondary" className="mt-2">
If you have anything else you want to ask,{' '}
<a
href="https://threefoldfaq.crisp.help/en/"
@@ -73,7 +71,7 @@ export function Faqs() {
reach out to us
</a>
.
</p>
</P>
</div>
<ul
role="list"
@@ -84,10 +82,8 @@ export function Faqs() {
<ul role="list" className="space-y-10">
{column.map((faq, faqIndex) => (
<li key={faqIndex}>
<h3 className="text-lg/6 font-semibold text-gray-900">
{faq.question}
</h3>
<p className="mt-4 text-sm text-gray-700">{faq.answer}</p>
<Question color="primary">{faq.question}</Question>
<Answer color="tertiary">{faq.answer}</Answer>
</li>
))}
</ul>

View File

@@ -1,109 +1,96 @@
import { CardDescription, CardEyebrow, CardTitle, Eyebrow, P, SectionHeader } from '@/components/Texts'
import Pathfinding from '@/components/Pathfinding'
import MessageBus from '@/components/MessageBus'
import ProxyDetection from '@/components/ProxyDetection'
import ProxyForwarding from '@/components/ProxyForwarding'
import ContentDistribution from '@/components/ContentDistribution'
const eyebrow = 'Core Components'
const sectionHeader = 'Network Capabilities'
const description1 = 'Built for resilience and autonomy, the Mycelium Network dynamically connects nodes through intelligent routing, proxy discovery, and decentralized delivery.'
const description2 = 'Each component — from message passing to content distribution — works in harmony to create a fully self-healing, self-optimizing data mesh.'
const cards = [
{
eyebrow: 'Routing',
title: 'Automatic pathfinding',
description: 'The Mycelium Network automatically discovers the shortest and fastest routes between nodes, ensuring optimal data flow and network efficiency without manual configuration.',
component: <Pathfinding />,
className: 'lg:col-span-3',
roundedClassName: 'max-lg:rounded-t-4xl lg:rounded-tl-4xl',
roundedInnerClassName: 'max-lg:rounded-t-[calc(2rem+1px)] lg:rounded-tl-[calc(2rem+1px)]'
},
{
eyebrow: 'Communication',
title: 'Distributed message bus',
description: 'Acts as a global message layer that lets nodes exchange information seamlessly. Enables resilient, asynchronous communication across the entire decentralized mesh.',
component: <MessageBus />,
className: 'lg:col-span-3',
roundedClassName: 'lg:rounded-tr-4xl',
roundedInnerClassName: 'lg:rounded-tr-[calc(2rem+1px)]'
},
{
eyebrow: 'Discovery',
title: 'Automatic proxy detection',
description: 'The system continuously scans for open SOCKS5 proxies within the network, making it effortless to find available connection points without manual setup.',
component: <ProxyDetection className="h-80" />,
className: 'lg:col-span-2',
roundedClassName: 'lg:rounded-bl-4xl',
roundedInnerClassName: 'lg:rounded-bl-[calc(2rem+1px)]'
},
{
eyebrow: 'Connectivity',
title: 'Seamless proxy forwarding',
description: 'Local SOCKS5 connections can be forwarded through nearby nodes or remote proxies. When browsers use the local proxy, traffic moves securely through the mesh—like a built-in VPN.',
component: <ProxyForwarding className="h-80" />,
className: 'lg:col-span-2',
roundedClassName: '',
roundedInnerClassName: ''
},
{
eyebrow: 'Delivery',
title: 'Decentralized content distribution',
description: 'Mycelium can serve data from distributed 0-DBs, creating a CDN-like layer that delivers content faster and more reliably—without relying on centralized servers.',
component: <ContentDistribution className="h-80" />,
className: 'lg:col-span-2',
roundedClassName: 'max-lg:rounded-b-4xl lg:rounded-br-4xl',
roundedInnerClassName: 'max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-br-[calc(2rem+1px)]'
}
]
export function Features() {
return (
<section id="features" className=" py-24">
<section id="features" className="py-24">
<div className="mx-auto max-w-2xl px-6 lg:max-w-7xl lg:px-8">
<h2 className="text-base/7 font-semibold text-cyan-500">Core Components</h2>
<p className="mt-2 max-w-2xl text-3xl lg:text-4xl font-medium tracking-tight text-pretty text-gray-950">
Network Capabilities
</p>
<p className="mt-4 max-w-4xl text-lg text-gray-600">
Built for resilience and autonomy, the Mycelium Network dynamically connects nodes through intelligent routing, proxy discovery, and decentralized delivery.
</p>
<p className="mt-2 max-w-4xl text-lg text-gray-600">
Each component from message passing to content distribution works in harmony to create a fully self-healing, self-optimizing data mesh.
</p>
<Eyebrow color="accent">{eyebrow}</Eyebrow>
<SectionHeader color="dark" className="mt-2 max-w-2xl text-pretty">
{sectionHeader}
</SectionHeader>
<P color="secondary" className="mt-4 max-w-4xl text-black">
{description1}
</P>
<P color="secondary" className="mt-2 max-w-4xl">
{description2}
</P>
<div className="mt-10 grid grid-cols-1 gap-x-4 gap-y-8 sm:mt-16 lg:grid-cols-6 lg:grid-rows-2">
<div className="group relative lg:col-span-3 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-t-4xl lg:rounded-tl-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-t-[calc(2rem+1px)] lg:rounded-tl-[calc(2rem+1px)]">
<Pathfinding />
<div className="p-10 pt-4">
<h3 className="text-sm/4 font-semibold text-cyan-500">Routing</h3>
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
Automatic pathfinding
</p>
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
The Mycelium Network automatically discovers the shortest and fastest routes between nodes,
ensuring optimal data flow and network efficiency without manual configuration.
</p>
{cards.map((card, index) => (
<div key={index} className={`group relative ${card.className} transition-all duration-300 ease-in-out hover:scale-105`}>
<div className={`absolute inset-0 rounded-lg bg-transparent ${card.roundedClassName}`} />
<div className={`flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] ${card.roundedInnerClassName}`}>
{card.component}
<div className="p-10 pt-4">
<CardEyebrow color="accent">{card.eyebrow}</CardEyebrow>
<CardTitle color="dark" className="mt-2">
{card.title}
</CardTitle>
<CardDescription color="secondary" className="mt-2 max-w-lg">
{card.description}
</CardDescription>
</div>
</div>
<div className={`pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20 ${card.roundedClassName}`} />
</div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-t-4xl lg:rounded-tl-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div>
<div className="group relative lg:col-span-3 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white lg:rounded-tr-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-tr-[calc(2rem+1px)]">
<MessageBus />
<div className="p-10 pt-4">
<h3 className="text-sm/4 font-semibold text-cyan-500">Communication</h3>
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
Distributed message bus
</p>
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
Acts as a global message layer that lets nodes exchange information seamlessly.
Enables resilient, asynchronous communication across the entire decentralized mesh.
</p>
</div>
</div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-tr-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div>
<div className="group relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white lg:rounded-bl-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-bl-[calc(2rem+1px)]">
<ProxyDetection className="h-80" />
<div className="p-10 pt-4">
<h3 className="text-sm/4 font-semibold text-cyan-500">Discovery</h3>
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
Automatic proxy detection
</p>
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
The system continuously scans for open SOCKS5 proxies within the network,
making it effortless to find available connection points without manual setup.
</p>
</div>
</div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 lg:rounded-bl-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div>
<div className="group relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)]">
<ProxyForwarding className="h-80" />
<div className="p-10 pt-4">
<h3 className="text-sm/4 font-semibold text-cyan-500">Connectivity</h3>
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
Seamless proxy forwarding
</p>
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
Local SOCKS5 connections can be forwarded through nearby nodes or remote proxies.
When browsers use the local proxy, traffic moves securely through the meshlike a built-in VPN.
</p>
</div>
</div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div>
<div className="group relative lg:col-span-2 transition-all duration-300 ease-in-out hover:scale-105">
<div className="absolute inset-0 rounded-lg bg-white max-lg:rounded-b-4xl lg:rounded-br-4xl" />
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-br-[calc(2rem+1px)]">
<ContentDistribution className="h-80" />
<div className="p-10 pt-4">
<h3 className="text-sm/4 font-semibold text-cyan-500">Delivery</h3>
<p className="mt-2 text-lg font-medium tracking-tight text-gray-950">
Decentralized content distribution
</p>
<p className="mt-2 max-w-lg text-sm/6 text-gray-600">
Mycelium can serve data from distributed 0-DBs, creating a CDN-like layer that delivers
content faster and more reliablywithout relying on centralized servers.
</p>
</div>
</div>
<div className="pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-b-4xl lg:rounded-br-4xl group-hover:outline-cyan-500 group-hover:shadow-lg group-hover:shadow-cyan-500/20" />
</div>
))}
</div>
</div>
</section>

View File

@@ -3,6 +3,7 @@ import Image from 'next/image'
import clsx from 'clsx'
import { DownloadLink } from '@/components/DownloadLink'
import { H1, H2, H3, H4, H5, P } from '@/components/Texts'
import { Button } from '@/components/Button'
import phoneFrame from '@/images/phoneframe.png'
import { Container } from '@/components/Container'
@@ -103,18 +104,17 @@ export function Hero() {
<Container>
<div className="flex flex-col-reverse gap-y-16 lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20">
<div className="relative z-10 mx-auto max-w-2xl lg:col-span-7 lg:max-w-none lg:pt-6 xl:col-span-6">
<h1 className="text-4xl lg:text-6xl font-medium tracking-tight text-gray-900">
Mycelium
</h1>
<h2 className="mt-6 lg:text-2xl text-xl tracking-tight leading-normal text-gray-600">
Unleashing the Power of Decentralized Networks
</h2>
<p className="mt-6 lg:text-xl text-lg text-gray-600 lg:leading-normal leading-tight">
Discover Mycelium, an end-to-end encrypted IPv6 overlay network. The future of secure, efficient, and scalable networking.
</p>
<p className="mt-6 text-lg text-gray-600 ">
<H1>Mycelium</H1>
<H5 color="secondary" className="mt-6">
Unleashing the Power of Decentralized Networks
</H5>
<P color="secondary" className="mt-6">
Discover Mycelium, an end-to-end encrypted IPv6 overlay network. The
future of secure, efficient, and scalable networking.
</P>
<P color="secondary" className="mt-6">
Coming Soon: New Decentralized Features
</p>
</P>
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-4">
<DownloadLink />
{/* <Button

View File

@@ -2,6 +2,7 @@
import * as React from 'react';
import { motion, useReducedMotion } from 'framer-motion';
import clsx from 'clsx';
type Props = {
className?: string; // e.g. "w-full h-72"
@@ -72,7 +73,12 @@ export default function MessageBus({ className, bg = '#ffffff' }: Props) {
const H = 460;
return (
<div className={className} aria-hidden="true" role="img" style={{ background: bg }}>
<div
className={clsx('relative overflow-hidden', className)}
aria-hidden="true"
role="img"
style={{ background: bg }}
>
<svg viewBox={`0 0 ${W} ${H}`} width="100%" height="100%">
{/* subtle grid */}

View File

@@ -13,6 +13,14 @@ import {
import { useDebouncedCallback } from 'use-debounce'
import { AppScreen } from '@/components/AppScreen'
import {
Eyebrow,
FeatureDescription,
FeatureTitle,
MobileFeatureTitle,
P,
SectionHeader,
} from '@/components/Texts'
import { CircleBackground } from '@/components/CircleBackground'
import { Container } from '@/components/Container'
import Image from 'next/image'
@@ -251,7 +259,7 @@ function FeaturesDesktop() {
onChange={onChange}
vertical
>
<TabList className="relative z-10 order-last col-span-6 space-y-6">
<TabList className="z-10 order-last col-span-6 space-y-6">
{features.map((feature, featureIndex) => (
<div
key={feature.name}
@@ -271,20 +279,20 @@ function FeaturesDesktop() {
)}
<div className="relative z-10 p-8">
<feature.icon className="h-8 w-8" />
<h3 className="mt-6 text-lg font-semibold text-white">
<FeatureTitle as="h3" color="white" className="mt-6">
<Tab className="text-left data-selected:not-data-focus:outline-hidden">
<span className="absolute inset-0 rounded-2xl" />
{feature.name}
</Tab>
</h3>
<p className="mt-2 text-sm text-gray-400">
</FeatureTitle>
<FeatureDescription color="secondary" className="mt-2">
{feature.description}
</p>
</FeatureDescription>
</div>
</div>
))}
</TabList>
<div className="relative col-span-6">
<div className="col-span-6">
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
<CircleBackground color="#13B5C8" className="animate-spin-slower" />
</div>
@@ -362,7 +370,7 @@ function FeaturesMobile() {
>
<div
className={clsx(
'relative transform overflow-hidden rounded-2xl bg-gray-800 px-5 py-6 outline-2 transition-colors',
'transform overflow-hidden rounded-2xl bg-gray-800 px-5 py-6 outline-2 transition-colors',
activeIndex === featureIndex
? 'outline-transparent' // Remove outline for active mobile slide
: 'outline-transparent hover:outline-cyan-500',
@@ -379,12 +387,12 @@ function FeaturesMobile() {
</PhoneFrame>
<div className="absolute inset-x-0 bottom-0 bg-gray-800/95 p-6 backdrop-blur-sm sm:p-10">
<feature.icon className="h-8 w-8" />
<h3 className="mt-6 text-sm font-semibold text-white sm:text-lg">
<MobileFeatureTitle color="white" className="mt-6">
{feature.name}
</h3>
<p className="mt-2 text-sm text-gray-400">
</MobileFeatureTitle>
<FeatureDescription color="secondary" className="mt-2">
{feature.description}
</p>
</FeatureDescription>
</div>
</div>
</div>
@@ -424,13 +432,15 @@ export function PrimaryFeatures() {
>
<Container>
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-3xl">
<h2 className="text-base/7 font-semibold text-cyan-500">How It Works</h2>
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-white">
<Eyebrow color="accent">How It Works</Eyebrow>
<SectionHeader color="white" className="mt-2">
How Mycelium Operates
</p>
<p className="mt-6 text-lg text-gray-300">
Mycelium, like its natural namesake, thrives on decentralization, efficiency, and security, making it a truly powerful force in the world of decentralized networks.
</p>
</SectionHeader>
<P color="light" className="mt-6">
Mycelium, like its natural namesake, thrives on decentralization,
efficiency, and security, making it a truly powerful force in the world
of decentralized networks.
</P>
</div>
</Container>
<div className="mt-16 md:hidden">

View File

@@ -2,6 +2,7 @@
import * as React from 'react';
import { motion, useReducedMotion } from 'framer-motion';
import clsx from 'clsx';
type Props = {
className?: string; // e.g. "w-full h-64"
@@ -160,8 +161,8 @@ export default function ProxyDetection({ className, bg = '#ffffff' }: Props) {
const delays = [0.8, 0.6, 0.4, 0.2, 0.0];
return (
<div
className={className}
<div
className={clsx('relative overflow-hidden', className)}
aria-hidden="true"
role="img"
style={{ background: bg }}

View File

@@ -2,6 +2,7 @@
import * as React from 'react';
import { motion, useReducedMotion } from 'framer-motion';
import clsx from 'clsx';
type Props = {
className?: string; // e.g. "w-full h-72"
@@ -124,7 +125,12 @@ export default function ProxyForwarding({ className, bg = '#ffffff' }: Props) {
const DEST = { x: 860, y: 210 };
return (
<div className={className} aria-hidden="true" role="img" style={{ background: bg }}>
<div
className={clsx('relative overflow-hidden', className)}
aria-hidden="true"
role="img"
style={{ background: bg }}
>
<svg viewBox={`0 0 ${W} ${H}`} width="100%" height="100%">
{/* subtle grid bg */}
<defs>

View File

@@ -1,4 +1,11 @@
import { useId } from 'react'
import {
Eyebrow,
FeatureDescription,
P,
SectionHeader,
SecondaryFeatureTitle,
} from './Texts'
import { Container } from '@/components/Container'
@@ -195,13 +202,16 @@ export function SecondaryFeatures() {
>
<Container>
<div className="mx-auto max-w-4xl sm:text-center">
<h2 className="text-base/7 font-semibold text-cyan-500">Roadmap</h2>
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
<Eyebrow color="accent">Roadmap</Eyebrow>
<SectionHeader as="h2" className="mt-2">
Coming Soon: The Future of Mycelium
</p>
<p className="mt-6 text-lg text-gray-600">
Mycelium is evolving to bring even more powerful decentralized features, designed to enhance your experience and expand possibilities. Be the first to explore what's coming next by staying connected with our latest updates.
</p>
</SectionHeader>
<P color="secondary" className="mt-6">
Mycelium is evolving to bring even more powerful decentralized
features, designed to enhance your experience and expand possibilities.
Be the first to explore what's coming next by staying connected with
our latest updates.
</P>
</div>
<ul
role="list"
@@ -213,10 +223,12 @@ export function SecondaryFeatures() {
className="rounded-2xl border border-gray-200 p-8 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
>
<feature.icon className="h-8 w-8" />
<h3 className="mt-6 font-semibold text-gray-900">
<SecondaryFeatureTitle color="primary" className="mt-6">
{feature.name}
</h3>
<p className="mt-2 text-gray-700">{feature.description}</p>
</SecondaryFeatureTitle>
<FeatureDescription color="tertiary" className="mt-2">
{feature.description}
</FeatureDescription>
</li>
))}
</ul>

147
src/components/Texts.tsx Normal file
View File

@@ -0,0 +1,147 @@
'use client'
import React from 'react'
import { cn } from '@/lib/utils'
const colorVariants = {
primary: 'text-gray-900',
secondary: 'text-gray-600',
light: 'text-gray-50',
accent: 'text-cyan-500',
white: 'text-white',
dark: 'text-gray-950',
tertiary: 'text-gray-700',
lightSecondary: 'text-gray-300',
} as const
type TextOwnProps = {
color?: keyof typeof colorVariants
className?: string
}
// Polymorphic helpers
type PolymorphicProps<E extends React.ElementType, P> = P & {
as?: E
} & Omit<React.ComponentPropsWithoutRef<E>, keyof P | 'as'>
const createTextComponent = <DefaultElement extends React.ElementType>(
defaultElement: DefaultElement,
defaultClassName: string
) => {
type Props<E extends React.ElementType = DefaultElement> = PolymorphicProps<
E,
TextOwnProps
>
function Text<E extends React.ElementType = DefaultElement>({
as,
color = 'primary',
className,
children,
...props
}: Props<E>) {
const Tag = (as || defaultElement) as React.ElementType
return (
<Tag
className={cn(defaultClassName, colorVariants[color], className)}
{...props}
>
{children}
</Tag>
)
}
;(Text as any).displayName = `Text(${typeof defaultElement === 'string' ? defaultElement : 'Component'
})`
return Text
}
// Exports based on your tailwind.css and the example
export const H1 = createTextComponent(
'h1',
'text-5xl lg:text-8xl font-medium leading-tight tracking-tight'
)
export const H2 = createTextComponent(
'h2',
'text-4xl lg:text-6xl font-medium leading-tight tracking-tight'
)
export const H3 = createTextComponent(
'h3',
'text-3xl lg:text-5xl font-medium leading-tight tracking-tight'
)
export const H4 = createTextComponent(
'h4',
'text-2xl lg:text-4xl font-medium leading-snug tracking-tight'
)
export const P = createTextComponent(
'p',
'text-base lg:text-lg leading-relaxed'
)
export const Small = createTextComponent(
'small',
'text-sm font-medium leading-normal tracking-normal'
)
export const Subtle = createTextComponent(
'p',
'text-sm leading-normal tracking-normal text-gray-500'
)
export const H5 = createTextComponent(
'h5',
'text-xl lg:text-2xl font-semibold leading-snug tracking-tight'
)
export const Eyebrow = createTextComponent(
'h2',
'text-base/7 font-semibold tracking-wide'
)
export const SectionHeader = createTextComponent(
'p',
'text-3xl lg:text-4xl font-medium leading-tight tracking-tight'
)
export const CardEyebrow = createTextComponent(
'h3',
'text-sm/4 font-semibold tracking-wide'
)
export const CardTitle = createTextComponent(
'p',
'text-lg font-medium leading-snug tracking-tight'
)
export const CardDescription = createTextComponent(
'p',
'text-sm/6 leading-normal tracking-normal'
)
export const FeatureTitle = createTextComponent(
'h3',
'text-lg font-semibold leading-snug tracking-tight'
)
export const FeatureDescription = createTextComponent(
'p',
'text-sm leading-normal tracking-normal'
)
export const MobileFeatureTitle = createTextComponent(
'h3',
'text-sm font-semibold sm:text-lg leading-snug tracking-tight'
)
export const SecondaryFeatureTitle = createTextComponent(
'h3',
'text-base font-semibold leading-snug tracking-tight'
)
export const Question = createTextComponent(
'h3',
'text-lg/6 font-semibold tracking-tight'
)
export const Answer = createTextComponent(
'p',
'mt-4 text-sm leading-normal tracking-normal'
)
export const PageHeader = createTextComponent(
'h2',
'text-5xl lg:text-6xl font-medium leading-tight tracking-tight'
)
export const DownloadCardTitle = createTextComponent(
'dt',
'text-base/7 font-semibold tracking-wide'
)
export const DownloadCardDescription = createTextComponent(
'dd',
'text-base/7 leading-normal tracking-normal'
)

6
src/lib/utils.ts Normal file
View File

@@ -0,0 +1,6 @@
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}