From 3ce544fe1468b619e4d1c3790bbd8d351e68c69c Mon Sep 17 00:00:00 2001 From: Evyatar Date: Sat, 6 Dec 2025 10:10:23 -0500 Subject: [PATCH] Refine hero CTAs and feature motion --- website/docusaurus.config.js | 41 +-- website/src/components/HomepageFeatures.js | 116 +++--- .../components/HomepageFeatures.module.css | 144 ++++++-- website/src/css/custom.css | 124 +++---- website/src/pages/index.js | 108 ++++-- website/src/pages/index.module.css | 333 ++++++++++++++---- 6 files changed, 568 insertions(+), 298 deletions(-) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 735585071..3699f4316 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -1,18 +1,25 @@ // @ts-check // Note: type annotations allow type checking and IDEs autocompletion -import { Highlight, themes } from 'prism-react-renderer'; +import path from 'path'; +import { themes } from 'prism-react-renderer'; +import { fileURLToPath } from 'url'; -// const darkCodeTheme = require('prism-react-renderer/themes/dracula'); -// const lightCodeTheme = require('prism-react-renderer/themes/github'); +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +function badgeLink(url, badge, name) { + return ` + ${name} + `; +} /** @type {import('@docusaurus/types').Config} */ const config = { baseUrl: '/', favicon: 'favicon.ico', title: 'Vest', - tagline: - 'Declarative validations framework inspired by unit testing libraries', + tagline: 'Declarative validations framework inspired by unit testing libraries', url: 'https://vestjs.dev', onBrokenLinks: 'throw', markdown: { @@ -23,12 +30,6 @@ const config = { }, organizationName: 'ealush', // Usually your GitHub org/user name. plugins: [ - // [ - // require.resolve('@easyops-cn/docusaurus-search-local'), - // { - // indexBlog: false, - // }, - // ], [ '@docusaurus/plugin-google-gtag', { @@ -43,7 +44,7 @@ const config = { /** @type {import('@docusaurus/preset-classic').Options} */ ({ docs: { - sidebarPath: require.resolve('./sidebars.js'), + sidebarPath: path.resolve(__dirname, './sidebars.js'), // Please change this to your repo. editUrl: 'https://github.com/ealush/vest/edit/latest/website/', lastVersion: 'current', @@ -76,7 +77,7 @@ const config = { beforeDefaultRehypePlugins: [], }, theme: { - customCss: require.resolve('./src/css/custom.css'), + customCss: path.resolve(__dirname, './src/css/custom.css'), }, }), ], @@ -195,10 +196,6 @@ const config = { { title: 'More', items: [ - // { - // label: "Blog", - // to: "/blog", - // }, { label: 'GitHub', href: 'https://github.com/ealush/vest', @@ -210,7 +207,7 @@ const config = { }, prism: { theme: themes.github, - darkTheme: themes.dracula, + darkTheme: themes.vsDark, }, announcementBar: { id: 'announcementBar-vest-6', @@ -232,10 +229,4 @@ const config = { }), }; -module.exports = config; - -function badgeLink(url, badge, name) { - return ` - ${name} - `; -} +export default config; diff --git a/website/src/components/HomepageFeatures.js b/website/src/components/HomepageFeatures.js index dba6e308a..5ca137730 100644 --- a/website/src/components/HomepageFeatures.js +++ b/website/src/components/HomepageFeatures.js @@ -5,97 +5,75 @@ import styles from './HomepageFeatures.module.css'; const FeatureList = [ { - title: 'Easy to learn', - emoji: '💡', - description: ( - <> - Vest adopts the syntax and style of unit testing frameworks, so you can - leverage the knowledge you already have to write your form validations. - - ), + title: 'Declarative by design', + emoji: '🧾', + category: 'DX', + description: + 'Author validations like unit tests with suites, hooks, and familiar assertions.', }, { - title: 'Framework Agnostic', - emoji: '🎨', - description: ( - <> - Bring your own UI. Vest is framework agnostic, so you can use it with - any UI framework you have. - - ), + title: 'Framework agnostic', + emoji: '🌐', + category: 'Flexible', + description: 'Use Vest anywhere—React, Vue, Svelte, vanilla JS, or your favorite stack.', }, { - title: 'Really smart', - emoji: '🧠', - description: ( - <> - Vest takes care of all the annoying parts for you. It manages its own - state, handles async validations and much more. - - ), + title: 'Async ready', + emoji: '⚡️', + category: 'Performance', + description: 'Handle async flows out of the box with deterministic state management.', }, { - title: 'Extendable', + title: 'Extendable core', emoji: '🧩', - description: ( - <> - You can easily add new custom types of validations to Vest according to - your needs. - - ), + category: 'Composable', + description: 'Add custom validation rules and share suites across teams with ease.', }, { - title: 'Reusable', - emoji: '♻️', - description: ( - <> - Validation logic in Vest can be shared across multiple features in your - app. - - ), + title: 'Tiny footprint', + emoji: '🎯', + category: 'Shipping', + description: 'Zero dependencies and a few KBs—perfect for modern, lean bundles.', }, { - title: 'Tiny', - emoji: '🐜', - description: ( - <> - Packed with features, but optimized for size. Vest brings no - dependencies, and only takes a few KBs. - - ), + title: 'Test-like ergonomics', + emoji: '✅', + category: 'Productivity', + description: 'Readable error messages, deterministic runs, and intuitive APIs.', }, ]; -function Feature({ emoji, title, description }) { +function Feature({ emoji, title, category, description }) { return ( -
-
-
- {emoji} -
-
-

{title}

-

{description}

-
+
+
+ {emoji} + {category}
+

{title}

+

{description}

); } export default function HomepageFeatures() { return ( - <> -
-
-
- {FeatureList.map((props, idx) => ( - - ))} -
+
+
+
+

Built for modern DX

+

Everything you need to trust your forms

+

+ Vest pairs a lightweight core with a familiar testing-inspired API, so you can ship + confident experiences without fighting your validation layer. +

-
- +
+ {FeatureList.map((feature) => ( + + ))} +
+
+
); } diff --git a/website/src/components/HomepageFeatures.module.css b/website/src/components/HomepageFeatures.module.css index 3418ceb2e..762ccf835 100644 --- a/website/src/components/HomepageFeatures.module.css +++ b/website/src/components/HomepageFeatures.module.css @@ -1,62 +1,130 @@ .features { - display: flex; - align-items: center; - padding: 6rem 0; + padding: 5rem 0; width: 100%; } +.sectionHeader { + max-width: 760px; + margin: 0 auto 3rem; + text-align: center; + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.sectionEyebrow { + text-transform: uppercase; + letter-spacing: 0.12em; + font-weight: 700; + color: var(--ifm-color-primary); + margin: 0; + font-size: 0.9rem; +} + +.sectionTitle { + font-size: 2.25rem; + margin: 0; +} + +.sectionDescription { + margin: 0; + color: var(--ifm-color-emphasis-700); + line-height: 1.7; +} + +.featuresGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: 1.5rem; +} + .featureCard { + background: var(--ifm-card-background-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 16px; + padding: 1.5rem; height: 100%; - padding: 2rem; - border-radius: 24px; - transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); - background: transparent; - border: 1px solid transparent; - margin-bottom: 2rem; /* Add vertical gap */ + transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease; + position: relative; + overflow: hidden; + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.04); +} + +.featureCard::before { + content: ''; + position: absolute; + inset: 0; + background: radial-gradient(circle at 20% 20%, rgba(99, 102, 241, 0.08), transparent 50%); + opacity: 0; + transition: opacity 0.25s ease; } .featureCard:hover { - background: rgba(255, 255, 255, 0.5); - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.05); - backdrop-filter: blur(4px); + transform: translateY(-3px); + border-color: var(--ifm-color-primary); + box-shadow: 0 14px 26px rgba(0, 0, 0, 0.06), 0 10px 20px rgba(99, 102, 241, 0.06); +} + +.featureCard:hover::before { + opacity: 1; +} + +html[data-theme='dark'] .featureCard { + background: rgba(30, 41, 59, 0.6); + border-color: rgba(255, 255, 255, 0.08); + box-shadow: 0 15px 30px rgba(0, 0, 0, 0.35); } html[data-theme='dark'] .featureCard:hover { - background: rgba(255, 255, 255, 0.05); + border-color: var(--ifm-color-primary); + box-shadow: 0 16px 34px rgba(0, 0, 0, 0.4), 0 0 30px rgba(99, 102, 241, 0.12); } -.emoji { - font-size: 3rem; - margin-bottom: 1.5rem; +.featureHeader { display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.emoji { + font-size: 1.9rem; + background: rgba(99, 102, 241, 0.12); + width: 54px; + height: 54px; + border-radius: 14px; + display: inline-flex; align-items: center; justify-content: center; - width: 80px; - height: 80px; - border-radius: 24px; - background: var(--ifm-color-emphasis-100); /* Simple background */ - margin-left: auto; - margin-right: auto; - transition: transform 0.3s ease; +} + +.category { + padding: 0.35rem 0.75rem; + border-radius: 999px; + background: rgba(99, 102, 241, 0.1); + color: var(--ifm-color-primary-darkest); + font-weight: 700; + letter-spacing: 0.04em; + font-size: 0.8rem; } .featureTitle { - font-size: 1.5rem; - font-weight: 800; - margin-bottom: 1rem; - background: linear-gradient( - 90deg, - var(--ifm-color-primary) 0%, - var(--ifm-color-primary-dark) 100% - ); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; + font-size: 1.3rem; + margin: 0 0 0.5rem; } .featureDescription { - color: var(--ifm-color-emphasis-600); - line-height: 1.8; - font-size: 1.1rem; - font-weight: 500; + margin: 0; + color: var(--ifm-color-emphasis-700); + line-height: 1.6; +} + +html[data-theme='dark'] .sectionDescription, +html[data-theme='dark'] .featureDescription { + color: #cbd5e1; +} + +html[data-theme='dark'] .category { + background: rgba(129, 140, 248, 0.16); + color: var(--ifm-color-primary-lightest); } diff --git a/website/src/css/custom.css b/website/src/css/custom.css index 4d26596dc..62138b350 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -1,88 +1,80 @@ -@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap'); -/** - * Any CSS included here will be global. The classic template - * bundles Infima by default. Infima is a CSS framework designed to - * work well for content-centric websites. - */ - -/* You can override the default Infima variables here. */ :root { - --ifm-color-primary-lightest: #fdfdfd; - --ifm-color-primary-lighter: #4b6889; - --ifm-color-primary-light: #486383; - --ifm-color-primary: #697098; - --ifm-color-primary-dark: #3b516b; - --ifm-color-primary-darker: #374d65; - --ifm-color-primary-darkest: #212432; - --ifm-font-family-base: 'Rubik', sans-serif; + --ifm-font-family-base: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + --ifm-font-family-monospace: 'JetBrains Mono', SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; --ifm-code-font-size: 95%; - --ifm-heading-color: var(--ifm-font-color-base); - --main-content-background-color: none; - --darkest-alt: #171819; - --announcement-bar-background: var(--ifm-color-primary-lightest); - --announcement-bar-color: var(--darkest-alt); + --ifm-border-radius-base: 12px; + + /* Midnight & Neon palette (light mode) */ + --ifm-color-primary: #6366f1; + --ifm-color-primary-dark: #4f46e5; + --ifm-color-primary-darker: #4338ca; + --ifm-color-primary-darkest: #3730a3; + --ifm-color-primary-light: #818cf8; + --ifm-color-primary-lighter: #a5b4fc; + --ifm-color-primary-lightest: #c7d2fe; + + --ifm-background-color: #ffffff; + --ifm-navbar-background-color: rgba(255, 255, 255, 0.82); + --ifm-navbar-shadow: none; + --ifm-heading-color: #0f172a; + --ifm-font-color-base: #111827; + --ifm-card-background-color: #f8fafc; + --docusaurus-highlighted-code-line-bg: rgba(99, 102, 241, 0.08); } html[data-theme='dark'] { - --ifm-background-color: var(--darkest-alt); - --announcement-bar-background: var(--ifm-color-primary-light); - --announcement-bar-color: var(--ifm-color-primary-lightest); + --ifm-background-color: #0f172a; + --ifm-font-color-base: #e2e8f0; + --ifm-heading-color: #f8fafc; + --ifm-navbar-background-color: rgba(15, 23, 42, 0.78); + --ifm-card-background-color: rgba(30, 41, 59, 0.5); + --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.08); +} + +body { + background: radial-gradient(circle at 20% 20%, rgba(99, 102, 241, 0.06), transparent 25%), + radial-gradient(circle at 80% 0%, rgba(79, 70, 229, 0.05), transparent 20%), + var(--ifm-background-color); + color: var(--ifm-font-color-base); } main { - background-color: var(--main-content-background-color); + background-color: transparent; } -.aa-DetachedSearchButton { - color: blue; +.navbar { + backdrop-filter: blur(12px); + border-bottom: 1px solid var(--ifm-color-emphasis-200); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.04); } -h1 { - padding-bottom: 1rem; +html[data-theme='dark'] .navbar { + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + box-shadow: 0 20px 50px rgba(0, 0, 0, 0.35); } .docusaurus-highlight-code-line { - background-color: rgba(0, 0, 0, 0.1); display: block; margin: 0 calc(-1 * var(--ifm-pre-padding)); padding: 0 var(--ifm-pre-padding); + background-color: var(--docusaurus-highlighted-code-line-bg); } .footer { - background-color: #272a36; -} - -html[data-theme='dark'] .docusaurus-highlight-code-line { - background-color: rgba(0, 0, 0, 0.3); -} - -html[data-theme='dark'] .navbar { - background-color: var(--ifm-background-color); - border-bottom: 1px solid var(--ifm-color-primary-darker); -} - -html[data-theme='light'] .hero__primary.hero { - background-color: var(--ifm-color-primary-lightest); - color: var(--ifm-color-primary-darkest); -} - -html[data-theme='dark'] .hero__primary.hero { - background-color: var(--ifm-background-color); - color: var(--ifm-color-primary-darkest); + background: linear-gradient(180deg, rgba(79, 70, 229, 0.12), rgba(15, 23, 42, 0.92)); + color: #e2e8f0; } -html[data-theme='dark'] .hero__title { - color: var(--ifm-color-primary-lightest); -} - -.hero__title { - text-transform: uppercase; +.hero__title, +.hero__subtitle { color: var(--ifm-heading-color); } -.hero__subtitle { - color: var(--ifm-heading-color); +html[data-theme='dark'] .hero__title, +html[data-theme='dark'] .hero__subtitle { + color: var(--ifm-color-primary-lightest); } .header-badge { @@ -91,7 +83,7 @@ html[data-theme='dark'] .hero__title { .header-github-link { content: ''; - background-color: var(--ifm-color-primary-darkest); + background-color: var(--ifm-font-color-base); mask-image: url('/img/github.svg'); mask-size: contain; mask-repeat: no-repeat; @@ -99,8 +91,22 @@ html[data-theme='dark'] .hero__title { width: 1.5rem; height: 1.5rem; margin-right: 0.5rem; + transition: background-color 0.2s ease, transform 0.2s ease; +} + +.header-github-link:hover { + background-color: var(--ifm-color-primary); + transform: translateY(-1px); } html[data-theme='dark'] .header-github-link { background-color: var(--ifm-color-primary-lightest); } + +.aa-DetachedSearchButton { + color: var(--ifm-color-primary); +} + +h1 { + padding-bottom: 1rem; +} diff --git a/website/src/pages/index.js b/website/src/pages/index.js index ddd02eff5..736bdf638 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -2,10 +2,8 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; import clsx from 'clsx'; -import React from 'react'; +import React, { useState } from 'react'; -import GithubLogo from '../../static/img/github.svg'; -import LogoSvg from '../../static/img/logo.svg'; import Demo from '../components/Demo'; import HomepageFeatures from '../components/HomepageFeatures'; import RawExample from '../components/RawExample'; @@ -14,39 +12,81 @@ import styles from './index.module.css'; function HomepageHeader() { const { siteConfig } = useDocusaurusContext(); + const [copied, setCopied] = useState(false); + const installCommand = 'npm i vest'; + + const handleCopy = () => { + if (typeof navigator !== 'undefined' && navigator.clipboard) { + navigator.clipboard.writeText(installCommand); + setCopied(true); + setTimeout(() => setCopied(false), 1800); + } + }; + return (
-
- -
-
-

{siteConfig.title}

-

- {siteConfig.tagline} -

-
-
- - Quick Start Guide - - - - Github - - - Try V6 instead - +
+
+
+

Modern validations for ambitious teams

+

+ Declarative validations +
+ inspired by unit testing +

+

+ {siteConfig.tagline} +

+
+ + Get started + + + Explore the API + + + Try Vest v6 + +
+
+ {installCommand} + +
+
+
+
Confidence without ceremony
+
+
Zero deps
+
+              
+                {`suite('signup', () => {
+  test('username', async () => {
+    await enforce(username).isNotBlank();
+  });
+
+  test('password', () => {
+    enforce(password).longerThan(8);
+  });
+});`}
+              
+            
+
+ Framework agnostic + + Async ready +
+
+
); diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css index ffe17e712..b71206937 100644 --- a/website/src/pages/index.module.css +++ b/website/src/pages/index.module.css @@ -1,131 +1,318 @@ -/** - * CSS files with the .module.css suffix will be treated as CSS modules - * and scoped locally. - */ - .heroBanner { - text-align: center; position: relative; overflow: hidden; - padding: 4rem 2rem; - display: flex; - flex-direction: column; - align-items: center; - background: linear-gradient( - 180deg, - var(--ifm-color-primary-lightest) 0%, - #ffffff 100% - ); + padding: 6rem 1.5rem 4.5rem; + background: radial-gradient(circle at 10% 20%, rgba(99, 102, 241, 0.15), transparent 30%), + radial-gradient(circle at 80% 10%, rgba(79, 70, 229, 0.12), transparent 25%), + linear-gradient(180deg, rgba(255, 255, 255, 0.92) 0%, rgba(247, 248, 252, 0.75) 100%); } html[data-theme='dark'] .heroBanner { - background: linear-gradient(180deg, #1b1b1d 0%, #000000 100%); + background: radial-gradient(circle at 15% 20%, rgba(129, 140, 248, 0.28), transparent 28%), + radial-gradient(circle at 80% 0%, rgba(99, 102, 241, 0.2), transparent 20%), + linear-gradient(180deg, rgba(15, 23, 42, 0.9) 0%, rgba(15, 23, 42, 0.7) 100%); +} + +.heroGlow { + position: absolute; + inset: 0; + background: radial-gradient(circle at 40% 30%, rgba(99, 102, 241, 0.25), transparent 35%), + radial-gradient(circle at 70% 70%, rgba(52, 211, 153, 0.2), transparent 30%); + filter: blur(40px); + opacity: 0.9; + pointer-events: none; } -.logoContainer { - margin-bottom: 2rem; +.heroGrid { position: relative; - z-index: 10; + z-index: 1; + display: grid; + gap: clamp(1.75rem, 2vw, 2.5rem); + grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); + align-items: center; + max-width: 1200px; + margin: 0 auto; +} + +.heroContent { + display: flex; + flex-direction: column; + gap: 1.25rem; + max-width: 640px; } -.vestLogo { - width: 150px; - height: 150px; - filter: drop-shadow(0 10px 20px rgba(0, 0, 0, 0.15)); +.heroOverline { + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--ifm-color-primary); + font-size: 0.9rem; + margin: 0; } -.titleContainer { - max-width: 800px; - margin: 0 auto 2rem; +.heroHighlight { + color: var(--ifm-color-primary); } .heroTagline { - font-size: 1.5rem; - line-height: 1.5; + font-size: 1.2rem; + line-height: 1.7; color: var(--ifm-color-emphasis-700); - margin-top: 1rem; - font-weight: 400; + max-width: 640px; } -.buttons { +.ctaGroup { display: flex; + flex-wrap: wrap; + gap: 0.75rem; align-items: center; - justify-content: center; - gap: 1.5rem; - margin-top: 2rem; } -.btn { - display: inline-flex; - align-items: center; - justify-content: center; +.primaryCta, +.secondaryCta, +.tertiaryCta { + border-radius: 999px; font-weight: 700; - font-size: 1.1rem; - padding: 0.8rem 2rem; - border-radius: 50px; - transition: all 0.2s ease; - text-decoration: none !important; - box-shadow: 0 4px 14px 0 rgba(0, 0, 0, 0.1); + padding: 0.85rem 1.5rem; + border: 1px solid transparent; + transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; } -.btn:hover { +.primaryCta { + box-shadow: 0 15px 30px rgba(99, 102, 241, 0.25); +} + +.primaryCta:hover { transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15); + box-shadow: 0 20px 35px rgba(99, 102, 241, 0.35); } -.btnQuickStart { - background-color: var(--ifm-color-primary); - color: #fff; - border: 2px solid var(--ifm-color-primary); +.secondaryCta { + background: linear-gradient(120deg, rgba(99, 102, 241, 0.14), rgba(129, 140, 248, 0.2)); + color: #1f2937; + border-color: rgba(99, 102, 241, 0.35); } -.btnQuickStart:hover { - background-color: var(--ifm-color-primary-dark); - border-color: var(--ifm-color-primary-dark); - color: #fff; +.secondaryCta:hover { + border-color: var(--ifm-color-primary); + transform: translateY(-2px); } -.btnGit { - background-color: var(--ifm-color-emphasis-200); +.tertiaryCta { + background: transparent; color: var(--ifm-color-emphasis-900); - border: 2px solid transparent; + border-color: rgba(99, 102, 241, 0.24); + box-shadow: 0 10px 18px rgba(0, 0, 0, 0.04); } -.btnGit:hover { - background-color: var(--ifm-color-emphasis-300); - border-color: transparent; - color: var(--ifm-color-emphasis-900); +.tertiaryCta:hover { + border-color: var(--ifm-color-primary); + transform: translateY(-2px); + color: var(--ifm-color-primary-dark); +} + +html[data-theme='dark'] .secondaryCta { + background: linear-gradient(120deg, rgba(129, 140, 248, 0.18), rgba(99, 102, 241, 0.3)); + color: #eef2ff; + border-color: rgba(129, 140, 248, 0.35); +} + +html[data-theme='dark'] .secondaryCta:hover { + border-color: var(--ifm-color-primary-light); + color: #f8fafc; +} + +html[data-theme='dark'] .tertiaryCta { + color: #e2e8f0; + border-color: rgba(226, 232, 240, 0.14); +} + +.installBar { + display: inline-flex; + align-items: center; + gap: 0.9rem; + padding: 0.95rem 1.1rem; + border-radius: 12px; + background: rgba(99, 102, 241, 0.06); + border: 1px solid rgba(99, 102, 241, 0.15); + font-family: var(--ifm-font-family-monospace); + color: var(--ifm-color-primary-darkest); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6); + flex-wrap: wrap; +} + +html[data-theme='dark'] .installBar { + background: rgba(129, 140, 248, 0.08); + border-color: rgba(129, 140, 248, 0.25); + color: var(--ifm-color-primary-lightest); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); +} + +.copyInlineButton { + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.4rem 0.75rem; + border-radius: 999px; + border: 1px solid rgba(99, 102, 241, 0.2); + background: rgba(255, 255, 255, 0.8); + color: #1f2937; + font-weight: 700; + transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; +} + +.copyInlineButton:hover { + border-color: var(--ifm-color-primary); + transform: translateY(-1px); + box-shadow: 0 10px 18px rgba(99, 102, 241, 0.15); +} + +.copyIcon { + font-size: 1rem; +} + +html[data-theme='dark'] .copyInlineButton { + background: rgba(30, 41, 59, 0.8); + color: #e2e8f0; + border-color: rgba(255, 255, 255, 0.18); } -html[data-theme='dark'] .btnGit { - background-color: rgba(255, 255, 255, 0.1); - color: #fff; +.heroPanel { + background: linear-gradient(135deg, rgba(99, 102, 241, 0.28), rgba(15, 23, 42, 0.8)); + border: 1px solid rgba(99, 102, 241, 0.3); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.12), 0 15px 30px rgba(99, 102, 241, 0.12); + border-radius: 20px; + overflow: hidden; + position: relative; } -html[data-theme='dark'] .btnGit:hover { - background-color: rgba(255, 255, 255, 0.2); +.heroPanel::after { + content: ''; + position: absolute; + inset: 0; + background: radial-gradient(circle at 80% 10%, rgba(255, 255, 255, 0.15), transparent 35%); + pointer-events: none; } -.btnPromote { - display: none; /* Hiding promote button for cleaner look, or we can restyle it */ +.panelHeader { + padding: 1rem 1.25rem; + font-weight: 700; + color: #f8fafc; + letter-spacing: 0.01em; +} + +.panelBody { + position: relative; + z-index: 1; + padding: 0 1.25rem 1.25rem; + display: flex; + flex-direction: column; + gap: 1rem; + min-height: 100%; +} + +.panelBadge { + align-self: flex-start; + padding: 0.4rem 0.8rem; + border-radius: 999px; + background: rgba(15, 23, 42, 0.4); + color: #e0e7ff; + border: 1px solid rgba(255, 255, 255, 0.12); + font-weight: 600; + letter-spacing: 0.03em; +} + +.panelCode { + background: rgba(15, 23, 42, 0.7); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 14px; + padding: 1rem 1.25rem; + color: #e2e8f0; + font-family: var(--ifm-font-family-monospace); + font-size: 0.95rem; + line-height: 1.7; + margin: 0; + overflow-x: auto; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06); +} + +.panelFooter { + display: flex; + align-items: center; + gap: 0.75rem; + color: #cbd5e1; + font-weight: 600; + letter-spacing: 0.01em; +} + +.pulse { + width: 8px; + height: 8px; + border-radius: 50%; + background: #22d3ee; + box-shadow: 0 0 0 0 rgba(34, 211, 238, 0.8); + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0% { + box-shadow: 0 0 0 0 rgba(34, 211, 238, 0.7); + } + + 70% { + box-shadow: 0 0 0 14px rgba(34, 211, 238, 0); + } + + 100% { + box-shadow: 0 0 0 0 rgba(34, 211, 238, 0); + } } @media screen and (max-width: 768px) { .heroBanner { - padding: 3rem 1rem; + padding: 4rem 1.25rem 3.5rem; + } + + .heroGrid { + grid-template-columns: 1fr; } .heroTagline { - font-size: 1.2rem; + font-size: 1.05rem; } - .buttons { + .ctaGroup { flex-direction: column; + align-items: stretch; + width: 100%; + } + + .ctaGroup > * { + width: 100%; + text-align: center; + } + + .installBar { + width: 100%; + justify-content: space-between; + } + + .heroPanel { + margin-top: 0.5rem; width: 100%; } +} + +@media screen and (max-width: 1024px) { + .heroGrid { + grid-template-columns: 1fr; + } + + .heroContent { + max-width: none; + } - .btn { + .heroPanel { width: 100%; - max-width: 300px; } }