mirror of
https://github.com/pocketpaw/pocketpaw.git
synced 2026-05-13 21:21:53 +00:00
Consolidate documentation from the separate pocketpaw-web repo into the main pocketpaw repo. This keeps docs and code in sync so PRs can update both atomically. - Remove docs/ from .gitignore - Remove docs' own .git (was pocketpaw/pocketpaw-web) - Add .github/workflows/deploy-docs.yml (builds from docs/ subdirectory) - Track all 120+ MDX pages, config, landing page, and public assets The separate pocketpaw-web repo can now be archived. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3879 lines
126 KiB
HTML
3879 lines
126 KiB
HTML
<!-- PocketPaw Landing Page — 2026-02-10
|
|
Design: "Denim Blue" — clean, editorial feel inspired by the mascot's denim pocket.
|
|
Fonts: Fraunces (wonky soft serif) + Plus Jakarta Sans + JetBrains Mono.
|
|
Changes: Added UnoCSS CDN runtime (config + shortcuts + Tailwind reset + FOUC prevention).
|
|
Existing <style> block preserved intact — UnoCSS is additive for utility classes.
|
|
Previous: channel icons, humanized copy, pip extras fix, Command Center cycling,
|
|
GSAP ScrollTrigger reveals, mascot parallax. -->
|
|
<!doctype html>
|
|
<html lang="en" data-grad="prism">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>PocketPaw — Your AI Agent. Modular. Secure. Everywhere.</title>
|
|
<meta
|
|
name="description"
|
|
content="Self-hosted, open-source AI agent you control from Telegram, Discord, Slack, WhatsApp, or a web dashboard. Installs in 30 seconds. Python. MIT licensed."
|
|
/>
|
|
<meta
|
|
name="keywords"
|
|
content="AI agent, self-hosted, open source, Telegram bot, Discord bot, Slack bot, WhatsApp bot, Ollama, Claude, OpenAI, personal AI, encrypted, modular, Python, pip install"
|
|
/>
|
|
<meta name="robots" content="index, follow" />
|
|
<meta name="theme-color" content="#4a6fa5" />
|
|
<link rel="canonical" href="https://pocketpaw.xyz/" />
|
|
<link rel="apple-touch-icon" href="./paw.webp" />
|
|
|
|
<!-- Open Graph (Facebook, LinkedIn, Slack, iMessage) -->
|
|
<meta property="og:url" content="https://pocketpaw.netlify.app/" />
|
|
<meta property="og:type" content="website" />
|
|
<meta
|
|
property="og:title"
|
|
content="PocketPaw — Your AI Agent. Modular. Secure. Everywhere."
|
|
/>
|
|
<meta
|
|
property="og:description"
|
|
content="Self-hosted AI agent you control from Telegram, Discord, Slack, WhatsApp, or a web dashboard. One command install. Encrypted credentials. Open source."
|
|
/>
|
|
<meta
|
|
property="og:image"
|
|
content="https://pocketpaw.netlify.app/pocket-paw-og.webp"
|
|
/>
|
|
<meta property="og:image:width" content="1200" />
|
|
<meta property="og:image:height" content="630" />
|
|
|
|
<!-- Twitter Card -->
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta name="twitter:site" content="@PocketPaw89242" />
|
|
<meta
|
|
name="twitter:title"
|
|
content="PocketPaw — Your AI Agent. Modular. Secure. Everywhere."
|
|
/>
|
|
<meta
|
|
name="twitter:description"
|
|
content="Self-hosted AI agent. One command install. Encrypted credentials. Telegram, Discord, Slack, WhatsApp, Web. Open source, MIT licensed."
|
|
/>
|
|
<meta
|
|
name="twitter:image"
|
|
content="https://pocketpaw.netlify.app/pocket-paw-og.webp"
|
|
/>
|
|
|
|
<link rel="icon" href="./paw.webp" type="image/png" />
|
|
|
|
<!-- Structured Data -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "SoftwareApplication",
|
|
"name": "PocketPaw",
|
|
"description": "Self-hosted, open-source AI agent you control from Telegram, Discord, Slack, WhatsApp, or a web dashboard. Encrypted credentials, modular install, 3 LLM backends.",
|
|
"applicationCategory": "DeveloperApplication",
|
|
"operatingSystem": "Linux, macOS, Windows",
|
|
"url": "https://pocketpaw.xyz",
|
|
"downloadUrl": "https://pypi.org/project/pocketpaw/",
|
|
"softwareVersion": "0.1.0",
|
|
"license": "https://opensource.org/licenses/MIT",
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "0",
|
|
"priceCurrency": "USD"
|
|
},
|
|
"author": {
|
|
"@type": "Organization",
|
|
"name": "PocketPaw",
|
|
"url": "https://github.com/pocketpaw"
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<!-- CSS Reset (UnoCSS runtime has no preflight) -->
|
|
<link
|
|
rel="stylesheet"
|
|
href="https://cdn.jsdelivr.net/npm/@unocss/reset/tailwind.min.css"
|
|
/>
|
|
<!-- FOUC prevention -->
|
|
<style>
|
|
[un-cloak] {
|
|
display: none;
|
|
}
|
|
</style>
|
|
<!-- UnoCSS config -->
|
|
<script>
|
|
window.__unocss = {
|
|
theme: {
|
|
colors: {
|
|
bg: "#f9f8f6",
|
|
card: "#ffffff",
|
|
sand: "#f1eee9",
|
|
txt: { DEFAULT: "#1a1a2e", 2: "#5c5c7a", 3: "#9b9bb0" },
|
|
blue: { DEFAULT: "#4a6fa5", hover: "#3b5d8e", light: "#e8eef6" },
|
|
honey: { DEFAULT: "#d49a5c", light: "#f5ead8" },
|
|
coral: "#c46b5c",
|
|
},
|
|
fontFamily: {
|
|
serif: "Fraunces, Georgia, serif",
|
|
sans: "Plus Jakarta Sans, -apple-system, sans-serif",
|
|
mono: "JetBrains Mono, monospace",
|
|
},
|
|
animation: {
|
|
keyframes: {
|
|
bob: "{0%,100%{transform:translateY(0)}50%{transform:translateY(-12px)}}",
|
|
emerge:
|
|
"{from{opacity:0;filter:blur(12px);transform:translateY(10px) scale(0.98)}to{opacity:1;filter:blur(0);transform:translateY(0) scale(1)}}",
|
|
"pulse-dot": "{0%,100%{opacity:1}50%{opacity:.3}}",
|
|
"blink-cursor": "{0%,100%{opacity:1}50%{opacity:0}}",
|
|
},
|
|
durations: {
|
|
bob: "5s",
|
|
emerge: "1s",
|
|
"pulse-dot": "2s",
|
|
"blink-cursor": ".8s",
|
|
},
|
|
timingFns: {
|
|
bob: "ease-in-out",
|
|
emerge: "cubic-bezier(.16,1,.3,1)",
|
|
"pulse-dot": "ease-in-out",
|
|
"blink-cursor": "step-end",
|
|
},
|
|
counts: {
|
|
bob: "infinite",
|
|
"pulse-dot": "infinite",
|
|
"blink-cursor": "infinite",
|
|
},
|
|
},
|
|
},
|
|
shortcuts: [
|
|
{ wrap: "max-w-[1040px] mx-auto px-7" },
|
|
{ "wrap-sm": "max-w-[700px] mx-auto px-7" },
|
|
{
|
|
tag: "inline-block text-[0.7rem] font-semibold tracking-[0.18em] uppercase text-blue mb-2.5",
|
|
},
|
|
{
|
|
btn: "inline-flex items-center gap-2 px-[26px] py-3 font-sans text-[.88rem] font-medium no-underline rounded-full transition-all cursor-pointer active:scale-[.98]",
|
|
},
|
|
{
|
|
"btn-fill":
|
|
"btn bg-blue text-white border-2 border-blue hover:bg-blue-hover hover:border-blue-hover",
|
|
},
|
|
{
|
|
"btn-ghost":
|
|
"btn bg-transparent text-txt border-[1.5px] border-transparent hover:bg-black/4",
|
|
},
|
|
{
|
|
"f-card":
|
|
"bg-card border border-black/7 rounded-2xl p-[34px] transition-all hover:border-black/14 hover:shadow-lg hover:-translate-y-[3px]",
|
|
},
|
|
],
|
|
};
|
|
</script>
|
|
<!-- UnoCSS runtime -->
|
|
<script src="https://cdn.jsdelivr.net/npm/@unocss/runtime/uno.global.js"></script>
|
|
<style>
|
|
/* ════════════════════════════════════════
|
|
TOKENS — "Denim & Honey"
|
|
════════════════════════════════════════ */
|
|
:root {
|
|
--lp-bg: #f9f8f6;
|
|
--lp-card: #ffffff;
|
|
--lp-sand: #f1eee9;
|
|
--lp-text: #1a1a2e;
|
|
--lp-text-2: #5c5c7a;
|
|
--lp-text-3: #9b9bb0;
|
|
--lp-blue: #4a6fa5;
|
|
--lp-blue-hover: #3b5d8e;
|
|
--lp-blue-light: #e8eef6;
|
|
--lp-honey: #d49a5c;
|
|
--lp-honey-light: #f5ead8;
|
|
--lp-coral: #c46b5c;
|
|
--lp-border: rgba(26, 26, 46, 0.07);
|
|
--lp-border-hover: rgba(26, 26, 46, 0.14);
|
|
--lp-shadow-s:
|
|
0 1px 3px rgba(26, 26, 46, 0.04), 0 4px 12px rgba(26, 26, 46, 0.03);
|
|
--lp-shadow-m:
|
|
0 4px 16px rgba(26, 26, 46, 0.06), 0 12px 40px rgba(26, 26, 46, 0.04);
|
|
--lp-shadow-mascot: 0 20px 50px rgba(80, 60, 30, 0.18);
|
|
--lp-r-card: 16px;
|
|
--lp-r-code: 12px;
|
|
--lp-r-pill: 100px;
|
|
--lp-ease: cubic-bezier(0.22, 1, 0.36, 1);
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
RESET
|
|
════════════════════════════════════════ */
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
html {
|
|
scroll-behavior: smooth;
|
|
}
|
|
.landing-custom {
|
|
background: var(--lp-bg);
|
|
color: var(--lp-text);
|
|
font-family:
|
|
"Plus Jakarta Sans",
|
|
-apple-system,
|
|
sans-serif;
|
|
font-weight: 400;
|
|
font-size: 1rem;
|
|
line-height: 1.7;
|
|
-webkit-font-smoothing: antialiased;
|
|
overflow-x: hidden;
|
|
}
|
|
.landing-custom img {
|
|
display: block;
|
|
max-width: 100%;
|
|
}
|
|
.landing-custom a {
|
|
color: inherit;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
TEXTURE — subtle dot grid
|
|
════════════════════════════════════════ */
|
|
.landing-custom::before {
|
|
content: "";
|
|
position: fixed;
|
|
inset: 0;
|
|
background-image: radial-gradient(
|
|
rgba(26, 26, 46, 0.07) 1px,
|
|
transparent 1px
|
|
);
|
|
background-size: 24px 24px;
|
|
pointer-events: none;
|
|
z-index: 0;
|
|
}
|
|
section,
|
|
footer,
|
|
nav,
|
|
.section-break {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
TYPOGRAPHY
|
|
════════════════════════════════════════ */
|
|
h1,
|
|
h2 {
|
|
font-family: "Fraunces", Georgia, serif;
|
|
font-weight: 400;
|
|
font-optical-sizing: auto;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
LAYOUT
|
|
════════════════════════════════════════ */
|
|
.wrap {
|
|
max-width: 1040px;
|
|
margin: 0 auto;
|
|
padding: 0 28px;
|
|
}
|
|
.wrap--sm {
|
|
max-width: 700px;
|
|
margin: 0 auto;
|
|
padding: 0 28px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
SECTION LABEL
|
|
════════════════════════════════════════ */
|
|
.tag {
|
|
display: inline-block;
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-blue);
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
THREE-DOT SECTION BREAK
|
|
════════════════════════════════════════ */
|
|
.section-break {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
padding: 24px 0;
|
|
}
|
|
.section-break i {
|
|
width: 5px;
|
|
height: 5px;
|
|
border-radius: 50%;
|
|
background: var(--lp-blue);
|
|
opacity: 0.3;
|
|
font-style: normal;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
NAV
|
|
════════════════════════════════════════ */
|
|
nav {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 100;
|
|
padding: 8px 0;
|
|
background: rgba(255, 255, 255, 0.12);
|
|
backdrop-filter: blur(14px) saturate(140%);
|
|
-webkit-backdrop-filter: blur(14px) saturate(140%);
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
|
|
transition:
|
|
background 0.3s,
|
|
padding 0.3s,
|
|
border-color 0.3s;
|
|
}
|
|
nav.scrolled {
|
|
background: rgba(255, 255, 255, 0.28);
|
|
border-bottom-color: rgba(255, 255, 255, 0.45);
|
|
padding: 7px 0;
|
|
}
|
|
.nav-bar {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
position: relative;
|
|
}
|
|
.nav-brand {
|
|
display: grid;
|
|
}
|
|
.nav-brand > * {
|
|
grid-area: 1/1;
|
|
align-self: center;
|
|
transition:
|
|
opacity 0.35s var(--lp-ease),
|
|
transform 0.35s var(--lp-ease);
|
|
}
|
|
.nav-logo {
|
|
font-family: "Fraunces", serif;
|
|
font-size: 1.35rem;
|
|
letter-spacing: -0.04em;
|
|
color: var(--lp-text);
|
|
text-decoration: none;
|
|
opacity: 0;
|
|
transform: translateY(4px);
|
|
}
|
|
.nav-logo em {
|
|
font-style: italic;
|
|
color: var(--lp-blue);
|
|
}
|
|
.nav-tagline {
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-blue);
|
|
white-space: nowrap;
|
|
opacity: 0;
|
|
transform: translateY(-4px);
|
|
pointer-events: none;
|
|
}
|
|
/* Default (no scroll): brand hidden, GitHub icon centered */
|
|
.nav-brand {
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition: opacity 0.35s var(--lp-ease);
|
|
}
|
|
.nav-links {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
position: absolute;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
transition: all 0.35s var(--lp-ease);
|
|
}
|
|
.nav-a-text {
|
|
display: inline-block;
|
|
max-width: 0;
|
|
opacity: 0;
|
|
overflow: hidden;
|
|
transition:
|
|
max-width 0.35s var(--lp-ease),
|
|
opacity 0.35s var(--lp-ease);
|
|
}
|
|
/* Scrolled: brand visible, links move right, GitHub text appears */
|
|
nav.scrolled .nav-brand {
|
|
opacity: 1;
|
|
pointer-events: auto;
|
|
}
|
|
nav.scrolled .nav-logo {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
nav.scrolled .nav-tagline {
|
|
opacity: 0;
|
|
transform: translateY(-4px);
|
|
pointer-events: none;
|
|
}
|
|
nav.scrolled .nav-links {
|
|
position: static;
|
|
transform: none;
|
|
}
|
|
nav.scrolled .nav-a-text {
|
|
max-width: 80px;
|
|
opacity: 1;
|
|
}
|
|
.nav-a {
|
|
font-size: 0.85rem;
|
|
font-weight: 500;
|
|
color: var(--lp-text-2);
|
|
text-decoration: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
transition: color 0.2s;
|
|
}
|
|
.nav-a:hover {
|
|
color: var(--lp-text);
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
BUTTONS
|
|
════════════════════════════════════════ */
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 12px 26px;
|
|
font-family: inherit;
|
|
font-size: 0.88rem;
|
|
font-weight: 500;
|
|
text-decoration: none;
|
|
border-radius: var(--lp-r-pill);
|
|
transition:
|
|
background 0.2s,
|
|
border-color 0.2s,
|
|
transform 0.15s;
|
|
cursor: pointer;
|
|
}
|
|
.btn:active {
|
|
transform: scale(0.98);
|
|
}
|
|
.btn--fill {
|
|
background: var(--lp-blue);
|
|
color: #fff;
|
|
border: 2px solid var(--lp-blue);
|
|
}
|
|
.btn--fill:hover {
|
|
background: var(--lp-blue-hover);
|
|
border-color: var(--lp-blue-hover);
|
|
}
|
|
.btn--ghost {
|
|
background: transparent;
|
|
color: var(--lp-text);
|
|
border: 1.5px solid transparent;
|
|
}
|
|
.btn--ghost:hover {
|
|
background: rgba(26, 26, 46, 0.04);
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
PAGE LOAD ANIMATION — blur-to-sharp reveal
|
|
════════════════════════════════════════ */
|
|
@keyframes emerge {
|
|
from {
|
|
opacity: 0;
|
|
filter: blur(12px);
|
|
transform: translateY(10px) scale(0.98);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
filter: blur(0);
|
|
transform: translateY(0) scale(1);
|
|
}
|
|
}
|
|
.hero .load-in {
|
|
opacity: 0;
|
|
animation: emerge 1s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
}
|
|
.hero .load-in:nth-child(1) {
|
|
animation-delay: 0.15s;
|
|
}
|
|
.hero .load-in:nth-child(2) {
|
|
animation-delay: 0.3s;
|
|
}
|
|
.hero .load-in:nth-child(3) {
|
|
animation-delay: 0.45s;
|
|
}
|
|
.hero .load-in:nth-child(4) {
|
|
animation-delay: 0.62s;
|
|
}
|
|
.hero .load-in:nth-child(5) {
|
|
animation-delay: 0.78s;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
HERO
|
|
════════════════════════════════════════ */
|
|
.hero {
|
|
padding: 72px 0 40px;
|
|
text-align: center;
|
|
}
|
|
.hero-title {
|
|
font-size: clamp(3rem, 8vw, 5.8rem);
|
|
letter-spacing: -0.04em;
|
|
line-height: 1.02;
|
|
margin-bottom: 6px;
|
|
}
|
|
.hero-title em {
|
|
font-style: italic;
|
|
color: var(--lp-blue);
|
|
}
|
|
.hero-sub {
|
|
font-size: clamp(1rem, 2.2vw, 1.2rem);
|
|
color: var(--lp-text-2);
|
|
font-weight: 300;
|
|
line-height: 1.55;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
/* mascot */
|
|
.mascot-area {
|
|
position: relative;
|
|
display: inline-block;
|
|
margin-top: 10px;
|
|
margin-bottom: 14px;
|
|
}
|
|
.mascot-glow {
|
|
position: absolute;
|
|
width: 400px;
|
|
height: 400px;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
background: radial-gradient(
|
|
ellipse,
|
|
rgba(74, 111, 165, 0.09) 0%,
|
|
rgba(74, 111, 165, 0.04) 45%,
|
|
transparent 72%
|
|
);
|
|
pointer-events: none;
|
|
}
|
|
.mascot-img {
|
|
position: relative;
|
|
width: 210px;
|
|
height: auto;
|
|
filter: drop-shadow(var(--lp-shadow-mascot));
|
|
animation: bob 5s ease-in-out infinite;
|
|
}
|
|
.mascot-img:hover {
|
|
animation-duration: 2.5s;
|
|
}
|
|
@keyframes bob {
|
|
0%,
|
|
100% {
|
|
transform: translateY(0);
|
|
}
|
|
50% {
|
|
transform: translateY(-12px);
|
|
}
|
|
}
|
|
|
|
/* terminal install block */
|
|
.terminal {
|
|
display: inline-block;
|
|
text-align: left;
|
|
background: var(--lp-text);
|
|
border-radius: var(--lp-r-code);
|
|
padding: 0;
|
|
margin-top: 0;
|
|
box-shadow: var(--lp-shadow-m);
|
|
overflow: hidden;
|
|
max-width: 100%;
|
|
}
|
|
/* Animated gradient text on hero terminal */
|
|
.terminal--glow .terminal-body code {
|
|
background: var(--grad-text);
|
|
background-size: 200% 100%;
|
|
-webkit-background-clip: text;
|
|
background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
animation: glow-text 4s linear infinite;
|
|
}
|
|
@keyframes glow-text {
|
|
0% {
|
|
background-position: 0% 50%;
|
|
}
|
|
100% {
|
|
background-position: 200% 50%;
|
|
}
|
|
}
|
|
.terminal--glow .terminal-body .prompt {
|
|
-webkit-text-fill-color: #7cb3d9;
|
|
}
|
|
|
|
/* ── Gradient text color variations (toggle via picker) ── */
|
|
/* 1. Prism (current) — blue, honey, orange, coral, purple */
|
|
[data-grad="prism"] {
|
|
--grad-text: linear-gradient(
|
|
90deg,
|
|
#7cb3d9 0%,
|
|
#d49a5c 20%,
|
|
#e8834a 40%,
|
|
#c46b5c 55%,
|
|
#a855f7 70%,
|
|
#7cb3d9 85%,
|
|
#4a6fa5 100%
|
|
);
|
|
}
|
|
/* 2. Denim & Honey — stays on brand, warm */
|
|
[data-grad="denim"] {
|
|
--grad-text: linear-gradient(
|
|
90deg,
|
|
#4a6fa5 0%,
|
|
#7cb3d9 25%,
|
|
#d49a5c 50%,
|
|
#7cb3d9 75%,
|
|
#4a6fa5 100%
|
|
);
|
|
}
|
|
/* 3. Aurora — cool greens and teals */
|
|
[data-grad="aurora"] {
|
|
--grad-text: linear-gradient(
|
|
90deg,
|
|
#4ade80 0%,
|
|
#22d3ee 25%,
|
|
#818cf8 50%,
|
|
#22d3ee 75%,
|
|
#4ade80 100%
|
|
);
|
|
}
|
|
/* 4. Sunset — warm oranges and pinks */
|
|
[data-grad="sunset"] {
|
|
--grad-text: linear-gradient(
|
|
90deg,
|
|
#fb923c 0%,
|
|
#f472b6 25%,
|
|
#c084fc 50%,
|
|
#f472b6 75%,
|
|
#fb923c 100%
|
|
);
|
|
}
|
|
/* 5. Ice — cool blues and whites */
|
|
[data-grad="ice"] {
|
|
--grad-text: linear-gradient(
|
|
90deg,
|
|
#bfdbfe 0%,
|
|
#93c5fd 20%,
|
|
#60a5fa 40%,
|
|
#a5b4fc 60%,
|
|
#93c5fd 80%,
|
|
#bfdbfe 100%
|
|
);
|
|
}
|
|
/* 6. Fire — reds and golds */
|
|
[data-grad="fire"] {
|
|
--grad-text: linear-gradient(
|
|
90deg,
|
|
#fbbf24 0%,
|
|
#f97316 25%,
|
|
#ef4444 50%,
|
|
#f97316 75%,
|
|
#fbbf24 100%
|
|
);
|
|
}
|
|
/* 7. Mono — subtle silver shimmer */
|
|
[data-grad="mono"] {
|
|
--grad-text: linear-gradient(
|
|
90deg,
|
|
#94a3b8 0%,
|
|
#e2e8f0 30%,
|
|
#cbd5e1 50%,
|
|
#e2e8f0 70%,
|
|
#94a3b8 100%
|
|
);
|
|
}
|
|
|
|
/* Color picker strip (easter egg — Shift+C to toggle) */
|
|
.grad-picker {
|
|
position: fixed;
|
|
top: 12px;
|
|
left: 50%;
|
|
transform: translateX(-50%) translateY(-60px);
|
|
z-index: 9999;
|
|
display: flex;
|
|
gap: 6px;
|
|
background: rgba(26, 26, 46, 0.9);
|
|
padding: 8px 14px;
|
|
border-radius: 100px;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition:
|
|
transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
|
|
opacity 0.35s ease;
|
|
}
|
|
.grad-picker.visible {
|
|
transform: translateX(-50%) translateY(0);
|
|
opacity: 1;
|
|
pointer-events: auto;
|
|
}
|
|
.grad-picker button {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 50%;
|
|
border: 2px solid transparent;
|
|
cursor: pointer;
|
|
transition:
|
|
border-color 0.2s,
|
|
transform 0.2s;
|
|
font-size: 0;
|
|
}
|
|
.grad-picker button:hover {
|
|
transform: scale(1.15);
|
|
}
|
|
.grad-picker button.active {
|
|
border-color: #fff;
|
|
}
|
|
.grad-picker button[data-v="prism"] {
|
|
background: conic-gradient(#7cb3d9, #d49a5c, #c46b5c, #a855f7, #7cb3d9);
|
|
}
|
|
.grad-picker button[data-v="denim"] {
|
|
background: conic-gradient(#4a6fa5, #7cb3d9, #d49a5c, #7cb3d9, #4a6fa5);
|
|
}
|
|
.grad-picker button[data-v="aurora"] {
|
|
background: conic-gradient(#4ade80, #22d3ee, #818cf8, #4ade80);
|
|
}
|
|
.grad-picker button[data-v="sunset"] {
|
|
background: conic-gradient(#fb923c, #f472b6, #c084fc, #fb923c);
|
|
}
|
|
.grad-picker button[data-v="ice"] {
|
|
background: conic-gradient(#bfdbfe, #60a5fa, #a5b4fc, #bfdbfe);
|
|
}
|
|
.grad-picker button[data-v="fire"] {
|
|
background: conic-gradient(#fbbf24, #f97316, #ef4444, #fbbf24);
|
|
}
|
|
.grad-picker button[data-v="mono"] {
|
|
background: conic-gradient(#94a3b8, #e2e8f0, #cbd5e1, #94a3b8);
|
|
}
|
|
/* Auto-rotate indicator */
|
|
.grad-picker .auto-btn {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 50%;
|
|
border: 2px solid transparent;
|
|
cursor: pointer;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 14px;
|
|
line-height: 1;
|
|
color: #fff;
|
|
transition:
|
|
border-color 0.2s,
|
|
transform 0.2s;
|
|
margin-left: 4px;
|
|
}
|
|
.grad-picker .auto-btn:hover {
|
|
transform: scale(1.15);
|
|
}
|
|
.grad-picker .auto-btn.active {
|
|
border-color: #fff;
|
|
}
|
|
.terminal-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
padding: 12px 18px 0;
|
|
}
|
|
.terminal-bar i {
|
|
width: 11px;
|
|
height: 11px;
|
|
border-radius: 50%;
|
|
font-style: normal;
|
|
}
|
|
.terminal-bar i:nth-child(1) {
|
|
background: #ff5f57;
|
|
}
|
|
.terminal-bar i:nth-child(2) {
|
|
background: #febc2e;
|
|
}
|
|
.terminal-bar i:nth-child(3) {
|
|
background: #28c840;
|
|
}
|
|
.terminal-body {
|
|
padding: 14px 22px 18px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
}
|
|
.terminal-body code {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 0.88rem;
|
|
color: #d1d5e8;
|
|
white-space: nowrap;
|
|
}
|
|
.terminal-body .prompt {
|
|
color: #7cb3d9;
|
|
user-select: none;
|
|
}
|
|
.copy-btn {
|
|
font-family: inherit;
|
|
font-size: 0.65rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: #7a7a9a;
|
|
background: rgba(255, 255, 255, 0.08);
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
border-radius: 6px;
|
|
padding: 5px 10px;
|
|
cursor: pointer;
|
|
transition:
|
|
color 0.2s,
|
|
border-color 0.2s;
|
|
white-space: nowrap;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
.copy-btn:hover {
|
|
color: #d1d5e8;
|
|
border-color: rgba(255, 255, 255, 0.25);
|
|
}
|
|
.copy-btn.copied {
|
|
color: #7cb3d9;
|
|
border-color: #7cb3d9;
|
|
}
|
|
.copy-icon {
|
|
display: none;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.install-note {
|
|
font-size: 0.82rem;
|
|
color: var(--lp-text-3);
|
|
margin-top: 14px;
|
|
}
|
|
/* channel icons row */
|
|
.channel-icons {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 14px;
|
|
margin-top: 18px;
|
|
}
|
|
.channel-icon {
|
|
position: relative;
|
|
width: 36px;
|
|
height: 36px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 10px;
|
|
background: var(--lp-card);
|
|
border: 1px solid var(--lp-border);
|
|
box-shadow: var(--lp-shadow-s);
|
|
cursor: default;
|
|
transition:
|
|
border-color 0.2s var(--lp-ease),
|
|
box-shadow 0.2s var(--lp-ease),
|
|
transform 0.2s var(--lp-ease);
|
|
}
|
|
.channel-icon:hover {
|
|
border-color: var(--lp-border-hover);
|
|
box-shadow: var(--lp-shadow-m);
|
|
transform: translateY(-2px);
|
|
}
|
|
.channel-icon svg {
|
|
width: 18px;
|
|
height: 18px;
|
|
flex-shrink: 0;
|
|
fill: var(--lp-text-3);
|
|
transition: fill 0.2s var(--lp-ease);
|
|
}
|
|
.channel-icon:hover svg {
|
|
fill: var(--lp-blue);
|
|
}
|
|
/* stroke-based icons (web) */
|
|
.channel-icon svg.stroke-icon {
|
|
fill: none;
|
|
stroke: var(--lp-text-3);
|
|
stroke-width: 1.8;
|
|
}
|
|
.channel-icon:hover svg.stroke-icon {
|
|
stroke: var(--lp-blue);
|
|
}
|
|
/* tooltip */
|
|
.channel-icon::after {
|
|
content: attr(data-tip);
|
|
position: absolute;
|
|
bottom: calc(100% + 8px);
|
|
left: 50%;
|
|
transform: translateX(-50%) translateY(4px);
|
|
padding: 5px 10px;
|
|
font-size: 0.72rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.02em;
|
|
color: var(--lp-card);
|
|
background: var(--lp-text);
|
|
border-radius: 6px;
|
|
white-space: nowrap;
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition:
|
|
opacity 0.18s var(--lp-ease),
|
|
transform 0.18s var(--lp-ease);
|
|
}
|
|
.channel-icon:hover::after {
|
|
opacity: 1;
|
|
transform: translateX(-50%) translateY(0);
|
|
}
|
|
|
|
/* gradient time badge */
|
|
.time-badge {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
margin-top: 14px;
|
|
}
|
|
.time-badge svg {
|
|
flex-shrink: 0;
|
|
color: var(--lp-blue);
|
|
opacity: 0.7;
|
|
}
|
|
.time-badge span {
|
|
font-size: 0.88rem;
|
|
font-weight: 600;
|
|
letter-spacing: -0.01em;
|
|
background: linear-gradient(
|
|
135deg,
|
|
var(--lp-blue) 0%,
|
|
#7cb3d9 50%,
|
|
var(--lp-blue) 100%
|
|
);
|
|
background-size: 200% 200%;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
animation: gradient-shift 4s ease-in-out infinite;
|
|
}
|
|
@keyframes gradient-shift {
|
|
0%,
|
|
100% {
|
|
background-position: 0% 50%;
|
|
}
|
|
50% {
|
|
background-position: 100% 50%;
|
|
}
|
|
}
|
|
/* OS install buttons */
|
|
.install-options {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
margin-top: 18px;
|
|
flex-wrap: wrap;
|
|
}
|
|
.install-label {
|
|
font-size: 0.68rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-text-3);
|
|
margin-bottom: 8px;
|
|
}
|
|
.install-or {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
margin: 10px auto;
|
|
width: 280px;
|
|
}
|
|
.install-or::before,
|
|
.install-or::after {
|
|
content: "";
|
|
flex: 1;
|
|
height: 1px;
|
|
background: var(--lp-border);
|
|
}
|
|
.install-or span {
|
|
font-size: 0.68rem;
|
|
font-weight: 500;
|
|
color: var(--lp-text-3);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.12em;
|
|
white-space: nowrap;
|
|
}
|
|
/* animated cursor-click icon on OS buttons */
|
|
.btn--os .click-icon {
|
|
width: 16px;
|
|
height: 16px;
|
|
flex-shrink: 0;
|
|
opacity: 0.45;
|
|
}
|
|
.btn--os:hover .click-icon {
|
|
opacity: 0.7;
|
|
}
|
|
.click-icon .cursor-arrow {
|
|
animation: cursor-nudge 3s ease-in-out infinite;
|
|
transform-origin: 9px 10px;
|
|
}
|
|
.click-icon .click-line {
|
|
opacity: 0;
|
|
animation: click-spread 3s ease-out infinite;
|
|
}
|
|
.click-icon .click-line:nth-child(2) {
|
|
animation-delay: 0.05s;
|
|
}
|
|
.click-icon .click-line:nth-child(3) {
|
|
animation-delay: 0.1s;
|
|
}
|
|
.click-icon .click-line:nth-child(4) {
|
|
animation-delay: 0.15s;
|
|
}
|
|
.click-icon .click-line:nth-child(5) {
|
|
animation-delay: 0.2s;
|
|
}
|
|
@keyframes cursor-nudge {
|
|
0%,
|
|
100% {
|
|
transform: translate(0, 0);
|
|
}
|
|
15% {
|
|
transform: translate(-1px, -2px);
|
|
}
|
|
30% {
|
|
transform: translate(0, 0);
|
|
}
|
|
}
|
|
@keyframes click-spread {
|
|
0%,
|
|
10% {
|
|
opacity: 0;
|
|
transform: translate(0, 0);
|
|
}
|
|
20% {
|
|
opacity: 1;
|
|
transform: translate(0, 0);
|
|
}
|
|
40% {
|
|
opacity: 0;
|
|
transform: var(--spread);
|
|
}
|
|
100% {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
.btn--os {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
padding: 10px 20px;
|
|
font-family: inherit;
|
|
font-size: 0.82rem;
|
|
font-weight: 500;
|
|
text-decoration: none;
|
|
color: var(--lp-text);
|
|
background: var(--lp-card);
|
|
border: 1.5px solid var(--lp-border);
|
|
border-radius: var(--lp-r-pill);
|
|
transition:
|
|
border-color 0.2s,
|
|
box-shadow 0.2s,
|
|
transform 0.15s;
|
|
cursor: pointer;
|
|
}
|
|
.btn--os:hover {
|
|
border-color: var(--lp-border-hover);
|
|
box-shadow: var(--lp-shadow-s);
|
|
transform: translateY(-1px);
|
|
}
|
|
.btn--os.disabled {
|
|
opacity: 0.45;
|
|
pointer-events: none;
|
|
cursor: default;
|
|
}
|
|
.btn--os svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
flex-shrink: 0;
|
|
}
|
|
.btn--os .os-sub {
|
|
font-size: 0.62rem;
|
|
color: var(--lp-text-3);
|
|
font-weight: 400;
|
|
margin-left: -2px;
|
|
}
|
|
.hero-ctas {
|
|
display: flex;
|
|
gap: 12px;
|
|
justify-content: center;
|
|
flex-wrap: wrap;
|
|
margin-top: 18px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
MULTI-LINE TERMINAL
|
|
════════════════════════════════════════ */
|
|
.terminal--multi .terminal-body {
|
|
display: block;
|
|
padding: 14px 22px 20px;
|
|
}
|
|
.terminal--multi code {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 0.82rem;
|
|
line-height: 1.9;
|
|
color: #d1d5e8;
|
|
white-space: pre;
|
|
display: block;
|
|
}
|
|
.terminal--multi .prompt {
|
|
color: #7cb3d9;
|
|
}
|
|
.terminal--multi .comment {
|
|
color: #6a6a8a;
|
|
}
|
|
.terminal--multi .hl {
|
|
color: #8bb8e8;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
PROBLEM
|
|
════════════════════════════════════════ */
|
|
.problem-lead {
|
|
font-family: "Fraunces", serif;
|
|
font-size: clamp(1.25rem, 3vw, 1.8rem);
|
|
line-height: 1.45;
|
|
letter-spacing: -0.02em;
|
|
text-align: center;
|
|
}
|
|
.problem-body {
|
|
font-size: 1rem;
|
|
color: var(--lp-text-2);
|
|
line-height: 1.75;
|
|
margin-top: 16px;
|
|
font-weight: 300;
|
|
text-align: center;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
COMPARISON — two-card editorial breakdown
|
|
════════════════════════════════════════ */
|
|
.compare-panel {
|
|
margin-top: 48px;
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 16px;
|
|
align-items: stretch;
|
|
}
|
|
/* shared card base */
|
|
.compare-left,
|
|
.compare-right {
|
|
border-radius: var(--lp-r-card);
|
|
padding: 32px 28px;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
/* Left — warm coral tint */
|
|
.compare-left {
|
|
background: var(--lp-card);
|
|
border: 1px solid var(--lp-border);
|
|
}
|
|
.compare-heading {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 20px;
|
|
}
|
|
.compare-heading-icon {
|
|
width: 18px;
|
|
height: 18px;
|
|
flex-shrink: 0;
|
|
}
|
|
.compare-heading span {
|
|
font-size: 0.68rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
}
|
|
.compare-left .compare-heading span {
|
|
color: var(--lp-coral);
|
|
}
|
|
.compare-left .compare-heading-icon {
|
|
color: var(--lp-coral);
|
|
opacity: 0.6;
|
|
}
|
|
.compare-steps {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
.compare-step {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 8px 0;
|
|
border-bottom: 1px solid var(--lp-border);
|
|
font-size: 0.82rem;
|
|
color: var(--lp-text-3);
|
|
}
|
|
.compare-step:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.compare-step-name {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.compare-step-num {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 0.6rem;
|
|
color: var(--lp-text-3);
|
|
opacity: 0.4;
|
|
width: 14px;
|
|
text-align: right;
|
|
flex-shrink: 0;
|
|
}
|
|
.compare-step-time {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 0.7rem;
|
|
color: var(--lp-coral);
|
|
opacity: 0.7;
|
|
white-space: nowrap;
|
|
}
|
|
.compare-total {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: 14px;
|
|
padding-top: 14px;
|
|
border-top: 1.5px solid rgba(196, 107, 92, 0.15);
|
|
}
|
|
.compare-total-label {
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-text-3);
|
|
}
|
|
.compare-total-time {
|
|
font-family: "Fraunces", serif;
|
|
font-size: 1.5rem;
|
|
letter-spacing: -0.03em;
|
|
color: var(--lp-coral);
|
|
}
|
|
/* Right — soft blue accent card */
|
|
.compare-right {
|
|
background: var(--lp-blue-light);
|
|
border: 1px solid rgba(74, 111, 165, 0.12);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-align: center;
|
|
}
|
|
.compare-right .compare-heading span {
|
|
color: var(--lp-blue);
|
|
}
|
|
.compare-right .compare-heading-icon {
|
|
color: var(--lp-blue);
|
|
opacity: 0.6;
|
|
}
|
|
.compare-hero-time {
|
|
font-family: "Fraunces", serif;
|
|
font-size: clamp(3.4rem, 7vw, 5.4rem);
|
|
letter-spacing: -0.04em;
|
|
line-height: 1;
|
|
color: var(--lp-text);
|
|
margin: 8px 0 2px;
|
|
}
|
|
.compare-hero-time small {
|
|
font-size: 0.38em;
|
|
color: var(--lp-text-3);
|
|
}
|
|
.compare-hero-unit {
|
|
font-size: 0.82rem;
|
|
font-weight: 300;
|
|
color: var(--lp-text-2);
|
|
margin-bottom: 22px;
|
|
}
|
|
.compare-right-cmd {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 0.72rem;
|
|
color: var(--lp-text-2);
|
|
background: rgba(74, 111, 165, 0.08);
|
|
padding: 9px 16px;
|
|
border-radius: 8px;
|
|
margin-bottom: 18px;
|
|
}
|
|
.compare-right-cmd .prompt {
|
|
color: var(--lp-blue);
|
|
}
|
|
.compare-checks {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 5px;
|
|
}
|
|
.compare-checks li {
|
|
font-size: 0.78rem;
|
|
color: var(--lp-text-2);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.compare-checks .check {
|
|
color: #3fae6f;
|
|
font-weight: 600;
|
|
}
|
|
.compare-badges {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
margin-top: 16px;
|
|
}
|
|
.compare-badge {
|
|
font-size: 0.62rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
padding: 4px 10px;
|
|
border-radius: 100px;
|
|
background: var(--lp-card);
|
|
border: 1px solid rgba(74, 111, 165, 0.15);
|
|
color: var(--lp-blue);
|
|
box-shadow: 0 1px 2px rgba(26, 26, 46, 0.03);
|
|
}
|
|
.compare-badge--green {
|
|
color: #3fae6f;
|
|
border-color: rgba(63, 174, 111, 0.2);
|
|
background: rgba(63, 174, 111, 0.06);
|
|
}
|
|
.compare-badge--honey {
|
|
color: #b07d3a;
|
|
border-color: rgba(212, 154, 92, 0.25);
|
|
background: rgba(212, 154, 92, 0.08);
|
|
}
|
|
.compare-footer {
|
|
text-align: center;
|
|
margin-top: 20px;
|
|
font-size: 0.85rem;
|
|
color: var(--lp-text-2);
|
|
font-weight: 300;
|
|
}
|
|
.compare-footer strong {
|
|
font-weight: 600;
|
|
color: var(--lp-text);
|
|
}
|
|
@media (max-width: 700px) {
|
|
.compare-panel {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
SECTION HEADINGS
|
|
════════════════════════════════════════ */
|
|
.heading {
|
|
font-size: clamp(1.9rem, 5vw, 3.1rem);
|
|
letter-spacing: -0.035em;
|
|
line-height: 1.1;
|
|
margin-bottom: 14px;
|
|
}
|
|
.heading .honey {
|
|
color: var(--lp-blue);
|
|
}
|
|
.heading .dim {
|
|
color: var(--lp-text-2);
|
|
}
|
|
.heading .blue {
|
|
color: var(--lp-blue);
|
|
}
|
|
.s-desc {
|
|
font-size: 1.02rem;
|
|
color: var(--lp-text-2);
|
|
line-height: 1.7;
|
|
max-width: 520px;
|
|
font-weight: 300;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
INLINE STATS (solution section)
|
|
════════════════════════════════════════ */
|
|
.quick-stats {
|
|
display: flex;
|
|
gap: 48px;
|
|
flex-wrap: wrap;
|
|
margin-top: 48px;
|
|
}
|
|
.qs-val {
|
|
font-family: "Fraunces", serif;
|
|
font-size: clamp(2rem, 4vw, 3.2rem);
|
|
letter-spacing: -0.03em;
|
|
line-height: 1;
|
|
}
|
|
.qs-val small {
|
|
font-size: 0.5em;
|
|
color: var(--lp-text-3);
|
|
}
|
|
.qs-lbl {
|
|
font-size: 0.68rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-text-3);
|
|
margin-top: 5px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
CORE INCLUDES (pills)
|
|
════════════════════════════════════════ */
|
|
.core-includes {
|
|
margin-top: 36px;
|
|
}
|
|
.core-label {
|
|
font-size: 0.72rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-text-3);
|
|
margin-bottom: 12px;
|
|
}
|
|
.core-pills {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
}
|
|
.core-pills span {
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
color: var(--lp-blue);
|
|
background: var(--lp-blue-light);
|
|
padding: 6px 14px;
|
|
border-radius: var(--lp-r-pill);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
FEATURE CARDS
|
|
════════════════════════════════════════ */
|
|
.features {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 14px;
|
|
margin-top: 52px;
|
|
}
|
|
.f-card {
|
|
background: var(--lp-card);
|
|
border: 1px solid var(--lp-border);
|
|
border-radius: var(--lp-r-card);
|
|
padding: 34px;
|
|
transition:
|
|
border-color 0.25s,
|
|
box-shadow 0.25s,
|
|
transform 0.25s;
|
|
}
|
|
.f-card:hover {
|
|
border-color: var(--lp-border-hover);
|
|
box-shadow: var(--lp-shadow-m);
|
|
transform: translateY(-3px);
|
|
}
|
|
/* feature icon */
|
|
.f-icon {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 11px;
|
|
background: var(--lp-blue-light);
|
|
color: var(--lp-blue);
|
|
margin-bottom: 16px;
|
|
}
|
|
.f-icon svg {
|
|
width: 20px;
|
|
height: 20px;
|
|
}
|
|
.f-card h3 {
|
|
font-family: "Plus Jakarta Sans", sans-serif;
|
|
font-size: 1.05rem;
|
|
font-weight: 600;
|
|
letter-spacing: -0.01em;
|
|
margin-bottom: 7px;
|
|
}
|
|
.f-card p {
|
|
font-size: 0.9rem;
|
|
color: var(--lp-text-2);
|
|
line-height: 1.6;
|
|
font-weight: 300;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
COMMAND CENTER — animated dashboard
|
|
════════════════════════════════════════ */
|
|
.cc-desc {
|
|
font-size: 1rem;
|
|
color: var(--lp-text-2);
|
|
line-height: 1.7;
|
|
font-weight: 300;
|
|
margin-top: 14px;
|
|
max-width: 560px;
|
|
}
|
|
/* example selector pills */
|
|
.cc-examples {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
margin-top: 36px;
|
|
flex-wrap: wrap;
|
|
}
|
|
.cc-ex-btn {
|
|
font-family: inherit;
|
|
font-size: 0.78rem;
|
|
font-weight: 500;
|
|
color: var(--lp-text-3);
|
|
background: transparent;
|
|
border: 1.5px solid var(--lp-border);
|
|
border-radius: var(--lp-r-pill);
|
|
padding: 8px 18px;
|
|
cursor: pointer;
|
|
transition: all 0.25s;
|
|
}
|
|
.cc-ex-btn:hover {
|
|
border-color: var(--lp-text-2);
|
|
color: var(--lp-text-2);
|
|
}
|
|
.cc-ex-btn.active {
|
|
background: var(--lp-blue);
|
|
color: #fff;
|
|
border-color: var(--lp-blue);
|
|
}
|
|
/* dark panel */
|
|
.cc-panel {
|
|
margin-top: 20px;
|
|
background: #13131f;
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.18);
|
|
}
|
|
.cc-topbar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 14px 24px;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
|
}
|
|
.cc-topbar-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
.cc-topbar-dots {
|
|
display: flex;
|
|
gap: 6px;
|
|
}
|
|
.cc-topbar-dots i {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
font-style: normal;
|
|
}
|
|
.cc-topbar-dots i:nth-child(1) {
|
|
background: #ff5f57;
|
|
}
|
|
.cc-topbar-dots i:nth-child(2) {
|
|
background: #febc2e;
|
|
}
|
|
.cc-topbar-dots i:nth-child(3) {
|
|
background: #28c840;
|
|
}
|
|
.cc-topbar-title {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 0.72rem;
|
|
color: rgba(255, 255, 255, 0.55);
|
|
letter-spacing: 0.04em;
|
|
}
|
|
.cc-topbar-status {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
font-size: 0.68rem;
|
|
font-weight: 600;
|
|
color: #3fae6f;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
}
|
|
.cc-topbar-status::before {
|
|
content: "";
|
|
width: 6px;
|
|
height: 6px;
|
|
border-radius: 50%;
|
|
background: #3fae6f;
|
|
animation: pulse-dot 2s ease-in-out infinite;
|
|
}
|
|
@keyframes pulse-dot {
|
|
0%,
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
50% {
|
|
opacity: 0.3;
|
|
}
|
|
}
|
|
/* agent avatar stack */
|
|
.cc-agents {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.cc-agent-av {
|
|
width: 26px;
|
|
height: 26px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.52rem;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
border: 2px solid #13131f;
|
|
margin-left: -7px;
|
|
opacity: 0;
|
|
transform: scale(0.4);
|
|
transition:
|
|
opacity 0.35s ease,
|
|
transform 0.35s ease;
|
|
position: relative;
|
|
}
|
|
.cc-agent-av:first-child {
|
|
margin-left: 0;
|
|
}
|
|
.cc-agent-av.visible {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
.cc-agent-av .cc-av-tip {
|
|
position: absolute;
|
|
bottom: calc(100% + 6px);
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
background: #1e1e30;
|
|
color: rgba(255, 255, 255, 0.75);
|
|
font-size: 0.58rem;
|
|
font-weight: 500;
|
|
letter-spacing: 0.01em;
|
|
padding: 4px 8px;
|
|
border-radius: 5px;
|
|
white-space: nowrap;
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition: opacity 0.2s;
|
|
}
|
|
.cc-agent-av:hover .cc-av-tip {
|
|
opacity: 1;
|
|
}
|
|
.cc-agent-count {
|
|
width: 26px;
|
|
height: 26px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.52rem;
|
|
font-weight: 700;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
background: rgba(255, 255, 255, 0.08);
|
|
border: 2px solid #13131f;
|
|
margin-left: -7px;
|
|
opacity: 0;
|
|
transform: scale(0.4);
|
|
transition:
|
|
opacity 0.35s ease,
|
|
transform 0.35s ease;
|
|
}
|
|
.cc-agent-count.visible {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
/* prompt bubble */
|
|
.cc-prompt {
|
|
padding: 20px 24px 0;
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: flex-start;
|
|
}
|
|
.cc-prompt-avatar {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 8px;
|
|
background: var(--lp-blue);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
font-size: 0.65rem;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
}
|
|
.cc-prompt-text {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 0.82rem;
|
|
color: rgba(255, 255, 255, 0.7);
|
|
line-height: 1.5;
|
|
min-height: 1.5em;
|
|
}
|
|
.cc-prompt-cursor {
|
|
display: inline-block;
|
|
width: 2px;
|
|
height: 1em;
|
|
background: var(--lp-blue);
|
|
margin-left: 2px;
|
|
animation: blink-cursor 0.8s step-end infinite;
|
|
vertical-align: text-bottom;
|
|
}
|
|
@keyframes blink-cursor {
|
|
0%,
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
50% {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
/* flow header + progress */
|
|
.cc-header {
|
|
padding: 20px 24px 0;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
opacity: 0;
|
|
transition: opacity 0.4s;
|
|
}
|
|
.cc-header.visible {
|
|
opacity: 1;
|
|
}
|
|
.cc-flow-name {
|
|
color: #fff;
|
|
font-size: 0.88rem;
|
|
font-weight: 500;
|
|
}
|
|
.cc-flow-meta {
|
|
font-size: 0.68rem;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
margin-top: 3px;
|
|
}
|
|
.cc-progress-wrap {
|
|
text-align: right;
|
|
}
|
|
.cc-progress-pct {
|
|
font-family: "JetBrains Mono", monospace;
|
|
font-size: 1.5rem;
|
|
color: #fff;
|
|
font-weight: 500;
|
|
transition: all 0.3s;
|
|
}
|
|
.cc-progress-lbl {
|
|
font-size: 0.6rem;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
}
|
|
/* progress bar */
|
|
.cc-bar {
|
|
margin: 16px 24px 0;
|
|
height: 3px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
}
|
|
.cc-bar-fill {
|
|
height: 100%;
|
|
width: 0;
|
|
border-radius: 2px;
|
|
background: linear-gradient(90deg, var(--lp-blue), #7cb3d9);
|
|
transition: width 1.2s cubic-bezier(0.22, 1, 0.36, 1);
|
|
}
|
|
/* node cards */
|
|
.cc-nodes {
|
|
display: grid;
|
|
grid-template-columns: repeat(5, 1fr);
|
|
gap: 10px;
|
|
padding: 20px 24px 24px;
|
|
}
|
|
.cc-node {
|
|
background: rgba(255, 255, 255, 0.03);
|
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
border-radius: 10px;
|
|
padding: 14px;
|
|
position: relative;
|
|
overflow: hidden;
|
|
transition:
|
|
border-color 0.5s,
|
|
opacity 0.5s;
|
|
opacity: 0.3;
|
|
}
|
|
.cc-node.st-done {
|
|
border-color: rgba(63, 174, 111, 0.3);
|
|
opacity: 1;
|
|
}
|
|
.cc-node.st-active {
|
|
border-color: rgba(74, 111, 165, 0.5);
|
|
opacity: 1;
|
|
}
|
|
.cc-node.st-active::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 2px;
|
|
background: var(--lp-blue);
|
|
}
|
|
.cc-node.st-review {
|
|
border-color: rgba(254, 188, 46, 0.3);
|
|
opacity: 0.7;
|
|
}
|
|
.cc-node.st-pending {
|
|
opacity: 0.3;
|
|
}
|
|
.cc-node-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 0.58rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
margin-bottom: 8px;
|
|
padding: 3px 8px;
|
|
border-radius: 4px;
|
|
transition: all 0.4s;
|
|
}
|
|
.badge-done {
|
|
color: #3fae6f;
|
|
background: rgba(63, 174, 111, 0.1);
|
|
}
|
|
.badge-running {
|
|
color: #7cb3d9;
|
|
background: rgba(74, 111, 165, 0.15);
|
|
}
|
|
.badge-pending {
|
|
color: rgba(255, 255, 255, 0.45);
|
|
background: rgba(255, 255, 255, 0.06);
|
|
}
|
|
.badge-review {
|
|
color: #febc2e;
|
|
background: rgba(254, 188, 46, 0.1);
|
|
}
|
|
.badge-approved {
|
|
color: #3fae6f;
|
|
background: rgba(63, 174, 111, 0.1);
|
|
}
|
|
.cc-node-name {
|
|
color: #fff;
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
margin-bottom: 3px;
|
|
}
|
|
.cc-node-agent {
|
|
font-size: 0.68rem;
|
|
color: rgba(255, 255, 255, 0.45);
|
|
}
|
|
/* connector dots between nodes */
|
|
.cc-node + .cc-node::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 50%;
|
|
left: -7px;
|
|
width: 4px;
|
|
height: 4px;
|
|
border-radius: 50%;
|
|
background: rgba(255, 255, 255, 0.12);
|
|
transform: translateY(-50%);
|
|
}
|
|
@media (max-width: 900px) {
|
|
.cc-nodes {
|
|
grid-template-columns: repeat(3, 1fr);
|
|
}
|
|
.cc-node + .cc-node::before {
|
|
display: none;
|
|
}
|
|
}
|
|
@media (max-width: 560px) {
|
|
.cc-nodes {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
.cc-header {
|
|
flex-direction: column;
|
|
}
|
|
.cc-examples {
|
|
gap: 6px;
|
|
}
|
|
.cc-ex-btn {
|
|
font-size: 0.72rem;
|
|
padding: 6px 14px;
|
|
}
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
SECURITY
|
|
════════════════════════════════════════ */
|
|
.sec-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 72px;
|
|
align-items: start;
|
|
}
|
|
.sec-intro {
|
|
font-size: 1rem;
|
|
color: var(--lp-text-2);
|
|
line-height: 1.7;
|
|
margin-top: 14px;
|
|
font-weight: 300;
|
|
}
|
|
.sec-item {
|
|
display: flex;
|
|
gap: 14px;
|
|
padding: 16px 0;
|
|
border-bottom: 1px solid var(--lp-border);
|
|
}
|
|
.sec-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.sec-dot {
|
|
width: 7px;
|
|
height: 7px;
|
|
border-radius: 50%;
|
|
background: var(--lp-blue);
|
|
flex-shrink: 0;
|
|
margin-top: 7px;
|
|
}
|
|
.sec-name {
|
|
font-size: 0.93rem;
|
|
font-weight: 500;
|
|
margin-bottom: 2px;
|
|
}
|
|
.sec-detail {
|
|
font-size: 0.83rem;
|
|
color: var(--lp-text-3);
|
|
font-weight: 300;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
NUMBERS
|
|
════════════════════════════════════════ */
|
|
.nums {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 48px 28px;
|
|
margin-top: 44px;
|
|
text-align: center;
|
|
}
|
|
.n-val {
|
|
font-family: "Fraunces", serif;
|
|
font-size: clamp(2.4rem, 4.5vw, 3.6rem);
|
|
letter-spacing: -0.035em;
|
|
line-height: 1;
|
|
}
|
|
.n-val small {
|
|
font-size: 0.48em;
|
|
color: var(--lp-text-3);
|
|
vertical-align: baseline;
|
|
}
|
|
.n-lbl {
|
|
font-size: 0.68rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-text-3);
|
|
margin-top: 7px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
CTA
|
|
════════════════════════════════════════ */
|
|
.cta {
|
|
padding: 80px 0 110px;
|
|
text-align: center;
|
|
}
|
|
.cta-meta {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
color: var(--lp-text-3);
|
|
margin-bottom: 28px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
FOOTER
|
|
════════════════════════════════════════ */
|
|
footer {
|
|
border-top: 1px solid var(--lp-border);
|
|
padding: 28px 0;
|
|
}
|
|
.foot {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 14px;
|
|
}
|
|
.foot-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
.foot-logo {
|
|
font-family: "Fraunces", serif;
|
|
font-size: 1.08rem;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
.foot-sep {
|
|
color: var(--lp-border-hover);
|
|
}
|
|
.foot-sm {
|
|
font-size: 0.8rem;
|
|
color: var(--lp-text-3);
|
|
}
|
|
.foot-links {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
}
|
|
.foot-a {
|
|
font-size: 0.8rem;
|
|
color: var(--lp-text-3);
|
|
text-decoration: none;
|
|
transition: color 0.2s;
|
|
}
|
|
.foot-a:hover {
|
|
color: var(--lp-text);
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
TEXT REVEAL ON SCROLL (word by word, GSAP-driven)
|
|
════════════════════════════════════════ */
|
|
.scroll-text .word {
|
|
display: inline;
|
|
opacity: 0.12;
|
|
}
|
|
|
|
/* ════════════════════════════════════════
|
|
RESPONSIVE
|
|
════════════════════════════════════════ */
|
|
@media (max-width: 900px) {
|
|
.hero {
|
|
padding: 64px 0 32px;
|
|
}
|
|
.mascot-img {
|
|
width: 170px;
|
|
}
|
|
.features {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
.sec-grid {
|
|
grid-template-columns: 1fr;
|
|
gap: 44px;
|
|
}
|
|
.nums {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
.hero-ctas {
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
.btn {
|
|
width: 260px;
|
|
justify-content: center;
|
|
}
|
|
}
|
|
@media (max-width: 560px) {
|
|
.nav-bar {
|
|
overflow: hidden;
|
|
}
|
|
nav.scrolled .nav-a-text {
|
|
max-width: 0;
|
|
opacity: 0;
|
|
}
|
|
.nav-logo {
|
|
font-size: 1.15rem;
|
|
}
|
|
.hero {
|
|
padding: 56px 0 24px;
|
|
}
|
|
.tag {
|
|
font-size: 0.58rem;
|
|
letter-spacing: 0.1em;
|
|
}
|
|
.mascot-img {
|
|
width: 150px;
|
|
}
|
|
.mascot-area {
|
|
margin-bottom: 22px;
|
|
}
|
|
.install-options {
|
|
gap: 8px;
|
|
}
|
|
.btn--os {
|
|
padding: 8px 16px;
|
|
font-size: 0.78rem;
|
|
}
|
|
.btn--os .os-sub {
|
|
display: none;
|
|
}
|
|
.terminal-body {
|
|
padding: 12px 16px 14px;
|
|
}
|
|
.terminal-body code {
|
|
font-size: 0.78rem;
|
|
}
|
|
.copy-icon {
|
|
display: block;
|
|
}
|
|
.copy-label {
|
|
display: none;
|
|
}
|
|
.terminal--multi .terminal-body {
|
|
padding: 12px 16px 16px;
|
|
overflow-x: auto;
|
|
}
|
|
.terminal--multi code {
|
|
font-size: 0.65rem;
|
|
line-height: 1.7;
|
|
}
|
|
.terminal--multi .comment {
|
|
display: none;
|
|
}
|
|
.quick-stats {
|
|
gap: 28px;
|
|
}
|
|
.core-pills {
|
|
gap: 6px;
|
|
}
|
|
.core-pills span {
|
|
padding: 5px 12px;
|
|
font-size: 0.75rem;
|
|
}
|
|
.f-card {
|
|
padding: 26px;
|
|
}
|
|
.nums {
|
|
gap: 32px 18px;
|
|
}
|
|
.wrap,
|
|
.wrap--sm {
|
|
padding: 0 18px;
|
|
}
|
|
.btn {
|
|
width: 100%;
|
|
}
|
|
section.padded {
|
|
padding: 64px 0 52px;
|
|
}
|
|
}
|
|
|
|
section.padded {
|
|
padding: 88px 0 72px;
|
|
}
|
|
</style>
|
|
<!-- GSAP + ScrollTrigger loaded dynamically to avoid Vite strict-mode wrapper -->
|
|
</head>
|
|
<body class="landing-custom" un-cloak>
|
|
<!-- ───────────── NAV ───────────── -->
|
|
<nav
|
|
id="nav"
|
|
style="
|
|
opacity: 0;
|
|
animation: emerge 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.08s forwards;
|
|
"
|
|
>
|
|
<div class="wrap nav-bar">
|
|
<div class="nav-brand">
|
|
<a href="#top" class="nav-logo">Pocket<em>Paw</em></a>
|
|
<span class="nav-tagline"
|
|
>Open Source · MIT Licensed · Python 3.11+</span
|
|
>
|
|
</div>
|
|
<div class="nav-links">
|
|
<a href="/introduction" class="nav-a">
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />
|
|
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
|
|
</svg>
|
|
<span class="nav-a-text">Docs</span>
|
|
</a>
|
|
<a
|
|
href="https://github.com/pocketpaw/pocketpaw"
|
|
target="_blank"
|
|
rel="noopener"
|
|
class="nav-a"
|
|
>
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
<path
|
|
d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"
|
|
/>
|
|
</svg>
|
|
<span class="nav-a-text">GitHub</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- ───────────── HERO ───────────── -->
|
|
<section class="hero">
|
|
<div class="wrap">
|
|
<div class="load-in">
|
|
<span class="tag"
|
|
>Open Source · MIT Licensed · Python 3.11+</span
|
|
>
|
|
</div>
|
|
|
|
<div class="load-in mascot-area">
|
|
<div class="mascot-glow"></div>
|
|
<img
|
|
src="./paw.webp"
|
|
alt="PocketPaw mascot — a friendly puppy waving from a denim pocket"
|
|
class="mascot-img"
|
|
/>
|
|
</div>
|
|
|
|
<div class="load-in">
|
|
<h1 class="hero-title">Pocket<em>Paw</em></h1>
|
|
<p class="hero-sub">Your AI agent. Modular. Secure. Everywhere.</p>
|
|
</div>
|
|
|
|
<div class="load-in">
|
|
<p class="install-label">One-click install</p>
|
|
<div class="install-options" style="margin-top: 0; margin-bottom: 0">
|
|
<span class="btn--os disabled">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
width="16"
|
|
height="16"
|
|
>
|
|
<path
|
|
d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"
|
|
/>
|
|
</svg>
|
|
macOS
|
|
<span class="os-sub">Coming soon</span>
|
|
</span>
|
|
<span class="btn--os disabled">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
width="16"
|
|
height="16"
|
|
>
|
|
<path
|
|
d="M3 12V6.75l6-1.32v6.48L3 12zm6.98.01l.02 6.47-6.98-1.01V13l6.96-.99zM10 5.12L19.99 3v8.87H10V5.12zm10.01 7.73l-.01 8.15L10 19.75V12.85h10.01z"
|
|
/>
|
|
</svg>
|
|
Windows
|
|
<span class="os-sub">Coming soon</span>
|
|
</span>
|
|
</div>
|
|
<div class="install-or"><span>or</span></div>
|
|
<div class="terminal terminal--glow">
|
|
<div class="terminal-bar"><i></i><i></i><i></i></div>
|
|
<div class="terminal-body">
|
|
<code
|
|
><span class="prompt">$</span> curl -fsSL https://pocketpaw.xyz/install.sh | sh</code
|
|
>
|
|
<button class="copy-btn" onclick="copyCmd(this)">
|
|
<svg
|
|
class="copy-icon"
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="9" y="9" width="13" height="13" rx="2" />
|
|
<path
|
|
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
|
|
/></svg
|
|
><span class="copy-label">Copy</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="time-badge">
|
|
<svg
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<polyline points="12 6 12 12 16 14" />
|
|
</svg>
|
|
<span>30 seconds to your first message</span>
|
|
</div>
|
|
|
|
<div class="channel-icons">
|
|
<!-- Telegram -->
|
|
<div class="channel-icon" data-tip="Chat via Telegram">
|
|
<svg viewBox="0 0 24 24">
|
|
<path
|
|
d="M11.944 0A12 12 0 000 12a12 12 0 0012 12 12 12 0 0012-12A12 12 0 0012 0a12 12 0 00-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 01.171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<!-- Discord -->
|
|
<div class="channel-icon" data-tip="Chat via Discord">
|
|
<svg viewBox="0 0 24 24">
|
|
<path
|
|
d="M20.317 4.37a19.791 19.791 0 00-4.885-1.515.074.074 0 00-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 00-5.487 0 12.64 12.64 0 00-.617-1.25.077.077 0 00-.079-.037A19.736 19.736 0 003.677 4.37a.07.07 0 00-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 00.031.057 19.9 19.9 0 005.993 3.03.078.078 0 00.084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 00-.041-.106 13.107 13.107 0 01-1.872-.892.077.077 0 01-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 01.077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 01.078.01c.12.098.246.198.373.292a.077.077 0 01-.006.127 12.299 12.299 0 01-1.873.892.077.077 0 00-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 00.084.028 19.839 19.839 0 006.002-3.03.077.077 0 00.032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 00-.031-.03z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<!-- Slack -->
|
|
<div class="channel-icon" data-tip="Chat via Slack">
|
|
<svg viewBox="0 0 24 24">
|
|
<path
|
|
d="M5.042 15.165a2.528 2.528 0 01-2.52 2.523A2.528 2.528 0 010 15.165a2.527 2.527 0 012.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 012.521-2.52 2.527 2.527 0 012.521 2.52v6.313A2.528 2.528 0 018.834 24a2.528 2.528 0 01-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 01-2.521-2.52A2.528 2.528 0 018.834 0a2.528 2.528 0 012.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 012.521 2.521 2.528 2.528 0 01-2.521 2.521H2.522A2.528 2.528 0 010 8.834a2.528 2.528 0 012.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 012.522-2.521A2.528 2.528 0 0124 8.834a2.528 2.528 0 01-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 01-2.523 2.521 2.527 2.527 0 01-2.52-2.521V2.522A2.527 2.527 0 0115.165 0a2.528 2.528 0 012.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 012.523 2.522A2.528 2.528 0 0115.165 24a2.527 2.527 0 01-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 01-2.52-2.523 2.526 2.526 0 012.52-2.52h6.313A2.527 2.527 0 0124 15.165a2.528 2.528 0 01-2.522 2.523h-6.313z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<!-- WhatsApp -->
|
|
<div class="channel-icon" data-tip="Chat via WhatsApp">
|
|
<svg viewBox="0 0 24 24">
|
|
<path
|
|
d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<!-- Web Dashboard -->
|
|
<div class="channel-icon" data-tip="Web Dashboard">
|
|
<svg
|
|
class="stroke-icon"
|
|
viewBox="0 0 24 24"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
|
|
<line x1="8" y1="21" x2="16" y2="21" />
|
|
<line x1="12" y1="17" x2="12" y2="21" />
|
|
</svg>
|
|
</div>
|
|
<!-- QR / Mobile -->
|
|
<div class="channel-icon" data-tip="Scan QR to go mobile">
|
|
<svg
|
|
class="stroke-icon"
|
|
viewBox="0 0 24 24"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="2" y="2" width="8" height="8" rx="1" />
|
|
<rect x="14" y="2" width="8" height="8" rx="1" />
|
|
<rect x="2" y="14" width="8" height="8" rx="1" />
|
|
<rect x="14" y="14" width="4" height="4" rx="0.5" />
|
|
<line x1="22" y1="14" x2="22" y2="18" />
|
|
<line x1="18" y1="22" x2="22" y2="22" />
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="section-break"><i></i><i></i><i></i></div>
|
|
|
|
<!-- ───────────── THE PROBLEM ───────────── -->
|
|
<section class="padded">
|
|
<div class="wrap" style="text-align: center">
|
|
<div class="wrap--sm" style="margin: 0 auto; padding: 0">
|
|
<span class="tag">The Problem</span>
|
|
<p class="problem-lead scroll-text heading-reveal">
|
|
Most AI agents take thirty minutes to set up. Docker, OAuth,
|
|
tunneling, fifty config options, all before you send your first
|
|
message.
|
|
</p>
|
|
<p class="problem-body">
|
|
Your API keys sit in plain‑text config files. Dashboards get
|
|
exposed on Shodan. Safety controls can be toggled via API while the
|
|
agent runs. You install hundreds of packages whether you need them
|
|
or not. One bad dependency update breaks everything, even features
|
|
you never asked for.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Visual comparison — itemized breakdown -->
|
|
<div class="compare-panel">
|
|
<div class="compare-left">
|
|
<div class="compare-heading">
|
|
<svg
|
|
class="compare-heading-icon"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<line x1="15" y1="9" x2="9" y2="15" />
|
|
<line x1="9" y1="9" x2="15" y2="15" />
|
|
</svg>
|
|
<span>Typical AI Agent</span>
|
|
</div>
|
|
<ul class="compare-steps">
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">1</span> Provision a VM or
|
|
VPS</span
|
|
>
|
|
<span class="compare-step-time">10 min</span>
|
|
</li>
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">2</span> SSH setup &
|
|
authentication</span
|
|
>
|
|
<span class="compare-step-time">5 min</span>
|
|
</li>
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">3</span> Clone repo & Docker
|
|
setup</span
|
|
>
|
|
<span class="compare-step-time">8 min</span>
|
|
</li>
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">4</span> Edit 50+ config
|
|
variables</span
|
|
>
|
|
<span class="compare-step-time">5 min</span>
|
|
</li>
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">5</span> Set up OAuth &
|
|
tunneling</span
|
|
>
|
|
<span class="compare-step-time">10 min</span>
|
|
</li>
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">6</span> Install 200+
|
|
dependencies</span
|
|
>
|
|
<span class="compare-step-time">8 min</span>
|
|
</li>
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">7</span> Debug dependency
|
|
conflicts</span
|
|
>
|
|
<span class="compare-step-time">10 min</span>
|
|
</li>
|
|
<li class="compare-step">
|
|
<span class="compare-step-name"
|
|
><span class="compare-step-num">8</span> Configure AI
|
|
provider</span
|
|
>
|
|
<span class="compare-step-time">4 min</span>
|
|
</li>
|
|
</ul>
|
|
<div class="compare-total">
|
|
<span class="compare-total-label">Total</span>
|
|
<span class="compare-total-time">~60 min</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="compare-right">
|
|
<div class="compare-heading">
|
|
<svg
|
|
class="compare-heading-icon"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
|
|
<polyline points="22 4 12 14.01 9 11.01" />
|
|
</svg>
|
|
<span>PocketPaw</span>
|
|
</div>
|
|
<div class="compare-hero-time">30<small>s</small></div>
|
|
<div class="compare-hero-unit">to your first message</div>
|
|
<div class="compare-right-cmd">
|
|
<span class="prompt">$ </span>curl -fsSL https://pocketpaw.xyz/install.sh | sh
|
|
</div>
|
|
<ul class="compare-checks">
|
|
<li><span class="check">✓</span> Dashboard running</li>
|
|
<li><span class="check">✓</span> Credentials encrypted</li>
|
|
<li><span class="check">✓</span> Channels connected</li>
|
|
<li><span class="check">✓</span> Memory initialized</li>
|
|
<li><span class="check">✓</span> Ready to chat</li>
|
|
</ul>
|
|
<div class="compare-badges">
|
|
<span class="compare-badge--green compare-badge">Fast</span>
|
|
<span class="compare-badge--green compare-badge">Secure</span>
|
|
<span class="compare-badge">Modular</span>
|
|
<span class="compare-badge--honey compare-badge">Encrypted</span>
|
|
<span class="compare-badge">Open Source</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p class="compare-footer">
|
|
<strong>One command.</strong> No Docker. No tunneling. No config
|
|
files.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="section-break"><i></i><i></i><i></i></div>
|
|
|
|
<!-- ───────────── THE SOLUTION ───────────── -->
|
|
<section class="padded">
|
|
<div class="wrap">
|
|
<div>
|
|
<span class="tag">The Solution</span>
|
|
<h2 class="heading scroll-text">
|
|
Batteries included,<br />
|
|
<span class="honey">choose your pack.</span>
|
|
</h2>
|
|
<p class="s-desc">
|
|
One install gives you everything you need. Add channels when your
|
|
life demands them. Never carry what you don't use.
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<div
|
|
class="terminal terminal--multi"
|
|
style="max-width: 700px; margin-top: 40px"
|
|
>
|
|
<div class="terminal-bar"><i></i><i></i><i></i></div>
|
|
<div class="terminal-body">
|
|
<code
|
|
><span class="prompt">$</span> curl -fsSL https://pocketpaw.xyz/install.sh | sh
|
|
<span class="comment"># Interactive installer</span>
|
|
<span class="prompt">$</span> pip install pocketpaw<span
|
|
class="hl"
|
|
>[memory]</span
|
|
>
|
|
<span class="comment"># Add Mem0 semantic search</span>
|
|
<span class="prompt">$</span> pip install pocketpaw<span
|
|
class="hl"
|
|
>[all]</span
|
|
>
|
|
<span class="comment"># Everything, all channels</span></code
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="core-includes">
|
|
<p class="core-label">The full includes:</p>
|
|
<div class="core-pills">
|
|
<span>Web Dashboard</span>
|
|
<span>Command Center</span>
|
|
<span>Telegram Bot</span>
|
|
<span>3 LLM Backends</span>
|
|
<span>Encrypted Credentials</span>
|
|
<span>Persistent Memory</span>
|
|
<span>Browser Automation</span>
|
|
<span>Guardian AI</span>
|
|
<span>Skills</span>
|
|
<span>Audit Log</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="quick-stats">
|
|
<div>
|
|
<div class="qs-val">~30</div>
|
|
<div class="qs-lbl">Packages</div>
|
|
</div>
|
|
<div>
|
|
<div class="qs-val">~80<small>MB</small></div>
|
|
<div class="qs-lbl">Footprint</div>
|
|
</div>
|
|
<div>
|
|
<div class="qs-val">30<small>s</small></div>
|
|
<div class="qs-lbl">To Install</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="section-break"><i></i><i></i><i></i></div>
|
|
|
|
<!-- ───────────── FEATURES ───────────── -->
|
|
<section class="padded">
|
|
<div class="wrap">
|
|
<div>
|
|
<span class="tag">The Thin Core</span>
|
|
<h2 class="heading scroll-text">
|
|
Everything you need.<br />
|
|
<span class="dim">Add the rest later.</span>
|
|
</h2>
|
|
</div>
|
|
|
|
<div class="features">
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="3" y="3" width="7" height="7" />
|
|
<rect x="14" y="3" width="7" height="7" />
|
|
<rect x="3" y="14" width="7" height="7" />
|
|
<rect x="14" y="14" width="7" height="7" />
|
|
</svg>
|
|
</div>
|
|
<h3>Multi-Channel</h3>
|
|
<p>
|
|
Telegram, Discord, Slack, WhatsApp, and web dashboard. Same agent,
|
|
same context, every channel.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="4" y="4" width="16" height="16" rx="2" />
|
|
<path d="M9 9h6v6H9z" />
|
|
<path
|
|
d="M9 1v3M15 1v3M9 20v3M15 20v3M20 9h3M20 14h3M1 9h3M1 14h3"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<h3>3 LLM Backends</h3>
|
|
<p>
|
|
Claude Agent SDK, OpenAI, or Ollama for fully local models. $0 API
|
|
cost with local inference.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
</svg>
|
|
</div>
|
|
<h3>Encrypted Credentials</h3>
|
|
<p>
|
|
Fernet AES with machine-derived PBKDF2 key. Real encryption, not
|
|
base64 obfuscation.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
<path d="M9 12l2 2 4-4" />
|
|
</svg>
|
|
</div>
|
|
<h3>Guardian AI</h3>
|
|
<p>
|
|
Secondary LLM reviews dangerous commands before execution. 3-tier
|
|
tool policy with deny-lists.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<ellipse cx="12" cy="5" rx="9" ry="3" />
|
|
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
|
|
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
|
|
</svg>
|
|
</div>
|
|
<h3>Persistent Memory</h3>
|
|
<p>
|
|
Session history and long-term facts. Upgrade to Mem0 semantic
|
|
vector search when ready.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<line x1="2" y1="12" x2="22" y2="12" />
|
|
<path
|
|
d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<h3>Browser Automation</h3>
|
|
<p>
|
|
Playwright-powered with accessibility tree snapshots. Navigate,
|
|
extract, interact.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
|
|
/>
|
|
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
|
<line x1="12" y1="22.08" x2="12" y2="12" />
|
|
</svg>
|
|
</div>
|
|
<h3>Modular Install</h3>
|
|
<p>
|
|
pip extras for genuine dependency isolation. Toggle channels from
|
|
the dashboard. Auto-install, no restart.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.705.707 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.23 8.77c.24-.24.581-.353.917-.303.515.077.877.528 1.073 1.01a2.5 2.5 0 1 0 3.259-3.259c-.482-.196-.933-.558-1.01-1.073-.05-.336.062-.676.303-.917l1.525-1.525A2.402 2.402 0 0 1 12 1.998c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.968a2.5 2.5 0 1 1 3.237 3.237c-.464.18-.894.527-.967 1.02Z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<h3>Skills</h3>
|
|
<p>
|
|
Self-installing plugin system. Add capabilities from a registry or
|
|
build your own. The agent installs what it needs.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="f-card">
|
|
<div class="f-icon">
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
|
/>
|
|
<polyline points="14 2 14 8 20 8" />
|
|
<line x1="16" y1="13" x2="8" y2="13" />
|
|
<line x1="16" y1="17" x2="8" y2="17" />
|
|
<polyline points="10 9 9 9 8 9" />
|
|
</svg>
|
|
</div>
|
|
<h3>Audit Log</h3>
|
|
<p>
|
|
Append-only JSONL. Every tool execution logged with severity
|
|
levels. Tamper-evident by design.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="section-break"><i></i><i></i><i></i></div>
|
|
|
|
<!-- ───────────── SECURITY ───────────── -->
|
|
<section class="padded">
|
|
<div class="wrap">
|
|
<div class="sec-grid">
|
|
<div>
|
|
<span class="tag">Security</span>
|
|
<h2 class="heading scroll-text">
|
|
Security was the<br />
|
|
<span class="honey">starting point.</span>
|
|
</h2>
|
|
<p class="sec-intro">
|
|
Your AI agent has terminal access, file access, browser control,
|
|
and your API keys. The security architecture should match that
|
|
power.
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<div class="sec-item">
|
|
<div class="sec-dot"></div>
|
|
<div>
|
|
<div class="sec-name">Fernet AES encrypted credentials</div>
|
|
<div class="sec-detail">
|
|
Machine-derived PBKDF2 key. Auto-migrates from plain text.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sec-item">
|
|
<div class="sec-dot"></div>
|
|
<div>
|
|
<div class="sec-name">3-tier tool policy with deny-lists</div>
|
|
<div class="sec-detail">
|
|
Minimal, coding, full. Deny always wins. No override possible.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sec-item">
|
|
<div class="sec-dot"></div>
|
|
<div>
|
|
<div class="sec-name">Guardian AI safety check</div>
|
|
<div class="sec-detail">
|
|
Secondary LLM reviews dangerous commands before execution.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sec-item">
|
|
<div class="sec-dot"></div>
|
|
<div>
|
|
<div class="sec-name">Append-only audit log</div>
|
|
<div class="sec-detail">
|
|
Every tool execution. Tamper-evident. Severity levels.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sec-item">
|
|
<div class="sec-dot"></div>
|
|
<div>
|
|
<div class="sec-name">No exposed ports by default</div>
|
|
<div class="sec-detail">
|
|
Telegram-first. Nothing for Shodan to find.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sec-item">
|
|
<div class="sec-dot"></div>
|
|
<div>
|
|
<div class="sec-name">WebSocket auth via message body</div>
|
|
<div class="sec-detail">
|
|
Not URL params. Not in logs. Not in scan results.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="section-break"><i></i><i></i><i></i></div>
|
|
|
|
<!-- ───────────── COMMAND CENTER ───────────── -->
|
|
<section class="padded" id="command-center">
|
|
<div class="wrap">
|
|
<div style="text-align: center">
|
|
<span class="tag">Command Center</span>
|
|
<h2 class="heading scroll-text">
|
|
One agent is useful.<br />
|
|
<span class="honey">A team gets real work done.</span>
|
|
</h2>
|
|
<p class="cc-desc" style="margin: 14px auto 0">
|
|
Describe your goal. Command Center breaks it into small meaningful
|
|
tasks, assigns agents, streams progress live, and pauses for your
|
|
approval before anything ships.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Example selector pills -->
|
|
<div class="cc-examples">
|
|
<button class="cc-ex-btn active" data-example="0">
|
|
Morning Briefing
|
|
</button>
|
|
<button class="cc-ex-btn" data-example="1">Content Pipeline</button>
|
|
<button class="cc-ex-btn" data-example="2">Bug Fix from Phone</button>
|
|
<button class="cc-ex-btn" data-example="3">Guest Booking</button>
|
|
<button class="cc-ex-btn" data-example="4">Security Audit</button>
|
|
</div>
|
|
|
|
<!-- Dark dashboard mockup -->
|
|
<div class="cc-panel" id="cc-panel">
|
|
<div class="cc-topbar">
|
|
<div class="cc-topbar-left">
|
|
<div class="cc-topbar-dots"><i></i><i></i><i></i></div>
|
|
<span class="cc-topbar-title">command-center</span>
|
|
</div>
|
|
<div class="cc-agents" id="cc-agents"></div>
|
|
<div class="cc-topbar-status">Live</div>
|
|
</div>
|
|
|
|
<!-- User prompt bubble -->
|
|
<div class="cc-prompt">
|
|
<div class="cc-prompt-avatar">You</div>
|
|
<div class="cc-prompt-text" id="cc-prompt-text">
|
|
<span class="cc-prompt-cursor"></span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Flow header (hidden until typing done) -->
|
|
<div class="cc-header" id="cc-header">
|
|
<div>
|
|
<div class="cc-flow-name" id="cc-flow-name"></div>
|
|
<div class="cc-flow-meta" id="cc-flow-meta"></div>
|
|
</div>
|
|
<div class="cc-progress-wrap">
|
|
<div class="cc-progress-pct" id="cc-progress-pct">0%</div>
|
|
<div class="cc-progress-lbl">Progress</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cc-bar">
|
|
<div class="cc-bar-fill" id="cc-bar-fill"></div>
|
|
</div>
|
|
|
|
<!-- Node cards (5 nodes: idea→breakdown→execute→approve→complete) -->
|
|
<div class="cc-nodes" id="cc-nodes">
|
|
<div class="cc-node st-pending" data-node="0">
|
|
<div class="cc-node-badge badge-pending">Pending</div>
|
|
<div class="cc-node-name"></div>
|
|
<div class="cc-node-agent"></div>
|
|
</div>
|
|
<div class="cc-node st-pending" data-node="1">
|
|
<div class="cc-node-badge badge-pending">Pending</div>
|
|
<div class="cc-node-name"></div>
|
|
<div class="cc-node-agent"></div>
|
|
</div>
|
|
<div class="cc-node st-pending" data-node="2">
|
|
<div class="cc-node-badge badge-pending">Pending</div>
|
|
<div class="cc-node-name"></div>
|
|
<div class="cc-node-agent"></div>
|
|
</div>
|
|
<div class="cc-node st-pending" data-node="3">
|
|
<div class="cc-node-badge badge-pending">Pending</div>
|
|
<div class="cc-node-name"></div>
|
|
<div class="cc-node-agent"></div>
|
|
</div>
|
|
<div class="cc-node st-pending" data-node="4">
|
|
<div class="cc-node-badge badge-pending">Pending</div>
|
|
<div class="cc-node-name"></div>
|
|
<div class="cc-node-agent"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="section-break"><i></i><i></i><i></i></div>
|
|
|
|
<!-- ───────────── THE NUMBERS ───────────── -->
|
|
<section class="padded">
|
|
<div class="wrap">
|
|
<div style="text-align: center">
|
|
<span class="tag">By The Numbers</span>
|
|
</div>
|
|
<div class="nums">
|
|
<div>
|
|
<div class="n-val">5</div>
|
|
<div class="n-lbl">Channels</div>
|
|
</div>
|
|
<div>
|
|
<div class="n-val">3</div>
|
|
<div class="n-lbl">LLM Backends</div>
|
|
</div>
|
|
<div>
|
|
<div class="n-val">30<small>s</small></div>
|
|
<div class="n-lbl">To First Message</div>
|
|
</div>
|
|
<div>
|
|
<div class="n-val">~30</div>
|
|
<div class="n-lbl">Packages</div>
|
|
</div>
|
|
<div>
|
|
<div class="n-val">~80<small>MB</small></div>
|
|
<div class="n-lbl">Memory</div>
|
|
</div>
|
|
<div>
|
|
<div class="n-val">MIT</div>
|
|
<div class="n-lbl">Licensed</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="section-break"><i></i><i></i><i></i></div>
|
|
|
|
<!-- ───────────── CTA ───────────── -->
|
|
<section class="cta">
|
|
<div class="wrap">
|
|
<div>
|
|
<p class="cta-meta">
|
|
Open Source · MIT Licensed · No Telemetry · No
|
|
Cloud Dependency
|
|
</p>
|
|
<h2 class="heading scroll-text" style="margin-bottom: 40px">
|
|
Your agent.<br />
|
|
Your machine.<br />
|
|
<span class="blue">Your rules.</span>
|
|
</h2>
|
|
</div>
|
|
|
|
<div>
|
|
<div class="terminal">
|
|
<div class="terminal-bar"><i></i><i></i><i></i></div>
|
|
<div class="terminal-body">
|
|
<code
|
|
><span class="prompt">$</span> curl -fsSL https://pocketpaw.xyz/install.sh | sh</code
|
|
>
|
|
<button class="copy-btn" onclick="copyCmd(this)">
|
|
<svg
|
|
class="copy-icon"
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<rect x="9" y="9" width="13" height="13" rx="2" />
|
|
<path
|
|
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
|
|
/></svg
|
|
><span class="copy-label">Copy</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="hero-ctas" style="margin-top: 36px">
|
|
<a
|
|
href="https://github.com/pocketpaw/pocketpaw"
|
|
target="_blank"
|
|
rel="noopener"
|
|
class="btn btn--fill"
|
|
>
|
|
<svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path
|
|
d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"
|
|
/>
|
|
</svg>
|
|
View on GitHub
|
|
</a>
|
|
<a href="#" class="btn btn--ghost"
|
|
><!-- TODO: replace # with PH URL once live -->
|
|
<svg
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polygon
|
|
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
|
|
/>
|
|
</svg>
|
|
Product Hunt
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ───────────── FOOTER ───────────── -->
|
|
<footer>
|
|
<div class="wrap foot">
|
|
<div class="foot-left">
|
|
<span
|
|
class="foot-logo"
|
|
style="font-family: "Fraunces", serif"
|
|
>PocketPaw</span
|
|
>
|
|
<span class="foot-sep">|</span>
|
|
<span class="foot-sm">Built by You & Us</span>
|
|
</div>
|
|
<div class="foot-links">
|
|
<a href="/introduction" class="foot-a">Docs</a>
|
|
<a
|
|
href="https://github.com/pocketpaw/pocketpaw"
|
|
target="_blank"
|
|
rel="noopener"
|
|
class="foot-a"
|
|
>GitHub</a
|
|
>
|
|
<a href="#" class="foot-a">Product Hunt</a
|
|
><!-- TODO: replace # with PH URL -->
|
|
<span class="foot-sm">MIT License</span>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<!-- ───────────── JS ───────────── -->
|
|
<script>
|
|
/* ── Nav scroll ── */
|
|
var nav = document.getElementById("nav");
|
|
window.addEventListener(
|
|
"scroll",
|
|
function () {
|
|
nav.classList.toggle("scrolled", window.scrollY > 50);
|
|
},
|
|
{ passive: true },
|
|
);
|
|
|
|
/* ── Copy ── */
|
|
function copyCmd(btn) {
|
|
navigator.clipboard
|
|
.writeText("curl -fsSL https://pocketpaw.xyz/install.sh | sh")
|
|
.then(function () {
|
|
var label = btn.querySelector(".copy-label");
|
|
if (label) label.textContent = "Copied";
|
|
btn.classList.add("copied");
|
|
setTimeout(function () {
|
|
if (label) label.textContent = "Copy";
|
|
btn.classList.remove("copied");
|
|
}, 2000);
|
|
});
|
|
}
|
|
|
|
/* Load GSAP dynamically to bypass Vite/Astro strict-mode script processing */
|
|
(function () {
|
|
function loadScript(src) {
|
|
return new Promise(function (resolve, reject) {
|
|
var s = document.createElement("script");
|
|
s.src = src;
|
|
s.onload = resolve;
|
|
s.onerror = reject;
|
|
document.head.appendChild(s);
|
|
});
|
|
}
|
|
loadScript(
|
|
"https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js",
|
|
)
|
|
.then(function () {
|
|
return loadScript(
|
|
"https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js",
|
|
);
|
|
})
|
|
.then(initGSAP)
|
|
.catch(function (e) {
|
|
console.warn("GSAP failed to load:", e);
|
|
});
|
|
|
|
function initGSAP() {
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
|
/* ── Mascot scroll parallax (blur + fade, scrub-tied) ── */
|
|
const mascot = document.querySelector(".mascot-img");
|
|
if (mascot) {
|
|
gsap.to(mascot, {
|
|
filter: "drop-shadow(0 20px 50px rgba(80,60,30,0.18)) blur(6px)",
|
|
opacity: 0.5,
|
|
ease: "none",
|
|
scrollTrigger: {
|
|
trigger: ".hero",
|
|
start: "top top",
|
|
end: "bottom top",
|
|
scrub: true,
|
|
},
|
|
});
|
|
}
|
|
|
|
/* ── Word-by-word text reveal (1 timeline per block, not per word) ── */
|
|
document.querySelectorAll(".scroll-text").forEach((el) => {
|
|
const html = el.innerHTML;
|
|
const wrapped = html.replace(
|
|
/((&[^;]+;)|(<[^>]+>)|[^\s<]+)/g,
|
|
(match) => {
|
|
if (match.startsWith("<")) return match;
|
|
return '<span class="word">' + match + "</span>";
|
|
},
|
|
);
|
|
el.innerHTML = wrapped;
|
|
|
|
const words = el.querySelectorAll(".word");
|
|
if (!words.length) return;
|
|
|
|
// Single timeline for all words in this block
|
|
const tl = gsap.timeline({
|
|
scrollTrigger: {
|
|
trigger: el,
|
|
start: "top 85%",
|
|
end: "bottom 40%",
|
|
scrub: true,
|
|
},
|
|
});
|
|
tl.to(words, {
|
|
opacity: 1,
|
|
duration: 1,
|
|
stagger: 0.1,
|
|
ease: "none",
|
|
});
|
|
});
|
|
|
|
/* ════════════════════════════════════════
|
|
COMMAND CENTER — interactive cycling
|
|
════════════════════════════════════════ */
|
|
(function () {
|
|
const examples = [
|
|
{
|
|
prompt:
|
|
"Prepare my morning briefing: calendar, emails, and top priorities for today",
|
|
flowName: "Morning Briefing",
|
|
meta: "5 tasks \u00b7 5 agents \u00b7 ~2 min",
|
|
nodes: [
|
|
{
|
|
name: "Fetch Calendar",
|
|
agent: "Calendar agent",
|
|
badge: "done",
|
|
},
|
|
{ name: "Scan Inbox", agent: "Email agent", badge: "done" },
|
|
{
|
|
name: "Look Up Contacts",
|
|
agent: "Research agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Compile Briefing",
|
|
agent: "Writing agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Deliver to Slack",
|
|
agent: "Channel agent",
|
|
badge: "done",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
prompt:
|
|
"Turn my latest podcast episode into shorts and schedule across Instagram, X, and TikTok",
|
|
flowName: "Content Pipeline",
|
|
meta: "5 tasks \u00b7 4 agents \u00b7 ~8 min",
|
|
nodes: [
|
|
{
|
|
name: "Download & Transcribe",
|
|
agent: "Media agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Identify Highlights",
|
|
agent: "Analysis agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Generate Clips",
|
|
agent: "Video agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Your Review",
|
|
agent: "Human checkpoint",
|
|
badge: "review",
|
|
},
|
|
{
|
|
name: "Schedule Posts",
|
|
agent: "Publishing agent",
|
|
badge: "done",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
prompt:
|
|
"Someone screenshotted a bug on WhatsApp. Find it in the repo, fix it, and open a PR",
|
|
flowName: "Bug Fix from Phone",
|
|
meta: "5 tasks \u00b7 3 agents \u00b7 ~3 min",
|
|
nodes: [
|
|
{
|
|
name: "Analyze Screenshot",
|
|
agent: "Vision agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Locate in Codebase",
|
|
agent: "Coding agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Write Fix + Tests",
|
|
agent: "Coding agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Your Approval",
|
|
agent: "Human checkpoint",
|
|
badge: "review",
|
|
},
|
|
{ name: "Push & Open PR", agent: "Git agent", badge: "done" },
|
|
],
|
|
},
|
|
{
|
|
prompt:
|
|
"Find 5 trending AI guests for next week\u2019s podcast, vet them, and draft outreach emails",
|
|
flowName: "Guest Booking Pipeline",
|
|
meta: "5 tasks \u00b7 4 agents \u00b7 ~12 min",
|
|
nodes: [
|
|
{
|
|
name: "Scan News & X",
|
|
agent: "Research agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Vet Against Past Guests",
|
|
agent: "Database agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Find Contact Info",
|
|
agent: "LeadIQ agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Build Show Dockets",
|
|
agent: "Writing agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Your Approval",
|
|
agent: "Human checkpoint",
|
|
badge: "review",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
prompt:
|
|
"Run an overnight security audit on our main repo. Check deps, vulnerabilities, and have a report ready by morning",
|
|
flowName: "Security Audit",
|
|
meta: "5 tasks \u00b7 3 agents \u00b7 ~15 min",
|
|
nodes: [
|
|
{
|
|
name: "Clone & Scan Repo",
|
|
agent: "Git agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Check Dependencies",
|
|
agent: "Security agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Analyze Vulnerabilities",
|
|
agent: "Security agent",
|
|
badge: "done",
|
|
},
|
|
{
|
|
name: "Your Review",
|
|
agent: "Human checkpoint",
|
|
badge: "review",
|
|
},
|
|
{
|
|
name: "Generate Report",
|
|
agent: "Artifacts agent",
|
|
badge: "done",
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const promptEl = document.getElementById("cc-prompt-text");
|
|
const headerEl = document.getElementById("cc-header");
|
|
const flowNameEl = document.getElementById("cc-flow-name");
|
|
const flowMetaEl = document.getElementById("cc-flow-meta");
|
|
const progressPctEl = document.getElementById("cc-progress-pct");
|
|
const barFillEl = document.getElementById("cc-bar-fill");
|
|
const nodesEl = document.getElementById("cc-nodes");
|
|
const nodeCards = nodesEl.querySelectorAll(".cc-node");
|
|
const exBtns = document.querySelectorAll(".cc-ex-btn");
|
|
const agentsEl = document.getElementById("cc-agents");
|
|
let currentExample = 0;
|
|
let animating = false;
|
|
let autoTimer = null;
|
|
let hasBeenVisible = false;
|
|
|
|
// Agent color palette (consistent per agent name)
|
|
const agentColors = {
|
|
"Calendar agent": "#3fae6f",
|
|
"Email agent": "#8b5cf6",
|
|
"Research agent": "#4a6fa5",
|
|
"Writing agent": "#d49a5c",
|
|
"Channel agent": "#06b6d4",
|
|
"Media agent": "#ec4899",
|
|
"Analysis agent": "#6366f1",
|
|
"Video agent": "#ef4444",
|
|
"Publishing agent": "#f59e0b",
|
|
"Vision agent": "#a78bfa",
|
|
"Coding agent": "#10b981",
|
|
"Git agent": "#f97316",
|
|
"Database agent": "#64748b",
|
|
"LeadIQ agent": "#22d3ee",
|
|
"Security agent": "#dc2626",
|
|
"Artifacts agent": "#c9a96e",
|
|
"Build agent": "#78716c",
|
|
"Formatting agent": "#84cc16",
|
|
"Human checkpoint": "#febc2e",
|
|
};
|
|
function agentInitials(name) {
|
|
return name
|
|
.replace(" agent", "")
|
|
.replace(" checkpoint", "")
|
|
.slice(0, 2)
|
|
.toUpperCase();
|
|
}
|
|
function getUniqueAgents(ex) {
|
|
const seen = new Set();
|
|
const out = [];
|
|
ex.nodes.forEach((n) => {
|
|
if (n.agent === "Human checkpoint") return;
|
|
if (!seen.has(n.agent)) {
|
|
seen.add(n.agent);
|
|
out.push(n.agent);
|
|
}
|
|
});
|
|
return out;
|
|
}
|
|
function renderAgents(ex) {
|
|
agentsEl.innerHTML = "";
|
|
const agents = getUniqueAgents(ex);
|
|
const show = Math.min(agents.length, 4);
|
|
const extra = agents.length - show;
|
|
for (let i = 0; i < show; i++) {
|
|
const a = agents[i];
|
|
const el = document.createElement("div");
|
|
el.className = "cc-agent-av";
|
|
Object.assign(el.style, {
|
|
background: agentColors[a] || "#4a6fa5",
|
|
width: "26px",
|
|
height: "26px",
|
|
borderRadius: "50%",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
fontSize: ".52rem",
|
|
fontWeight: "700",
|
|
color: "#fff",
|
|
border: "2px solid #13131f",
|
|
marginLeft: i === 0 ? "0" : "-7px",
|
|
opacity: "0",
|
|
transform: "scale(0.4)",
|
|
transition: "opacity .35s ease,transform .35s ease",
|
|
position: "relative",
|
|
cursor: "default",
|
|
});
|
|
var tip = document.createElement("span");
|
|
tip.className = "cc-av-tip";
|
|
tip.textContent = a;
|
|
Object.assign(tip.style, {
|
|
position: "absolute",
|
|
bottom: "calc(100% + 6px)",
|
|
left: "50%",
|
|
transform: "translateX(-50%)",
|
|
background: "#1e1e30",
|
|
color: "rgba(255,255,255,0.75)",
|
|
fontSize: ".58rem",
|
|
fontWeight: "500",
|
|
letterSpacing: ".01em",
|
|
padding: "4px 8px",
|
|
borderRadius: "5px",
|
|
whiteSpace: "nowrap",
|
|
opacity: "0",
|
|
pointerEvents: "none",
|
|
transition: "opacity .2s",
|
|
});
|
|
el.textContent = agentInitials(a);
|
|
el.appendChild(tip);
|
|
el.addEventListener("mouseenter", function () {
|
|
tip.style.opacity = "1";
|
|
});
|
|
el.addEventListener("mouseleave", function () {
|
|
tip.style.opacity = "0";
|
|
});
|
|
agentsEl.appendChild(el);
|
|
setTimeout(
|
|
(function (e) {
|
|
return function () {
|
|
e.style.opacity = "1";
|
|
e.style.transform = "scale(1)";
|
|
};
|
|
})(el),
|
|
120 + i * 80,
|
|
);
|
|
}
|
|
if (extra > 0) {
|
|
const c = document.createElement("div");
|
|
c.className = "cc-agent-count";
|
|
c.textContent = "+" + extra;
|
|
Object.assign(c.style, {
|
|
width: "26px",
|
|
height: "26px",
|
|
borderRadius: "50%",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
fontSize: ".52rem",
|
|
fontWeight: "700",
|
|
color: "rgba(255,255,255,0.5)",
|
|
background: "rgba(255,255,255,0.08)",
|
|
border: "2px solid #13131f",
|
|
marginLeft: "-7px",
|
|
opacity: "0",
|
|
transform: "scale(0.4)",
|
|
transition: "opacity .35s ease,transform .35s ease",
|
|
});
|
|
agentsEl.appendChild(c);
|
|
setTimeout(
|
|
(function (e) {
|
|
return function () {
|
|
e.style.opacity = "1";
|
|
e.style.transform = "scale(1)";
|
|
};
|
|
})(c),
|
|
120 + show * 80,
|
|
);
|
|
}
|
|
}
|
|
|
|
function resetPanel() {
|
|
// Hide header
|
|
headerEl.classList.remove("visible");
|
|
progressPctEl.textContent = "0%";
|
|
barFillEl.style.width = "0%";
|
|
barFillEl.style.transition = "none";
|
|
// Reset prompt
|
|
promptEl.innerHTML = '<span class="cc-prompt-cursor"></span>';
|
|
// Clear agent avatars
|
|
agentsEl.innerHTML = "";
|
|
// Reset all nodes
|
|
nodeCards.forEach((card) => {
|
|
card.className = "cc-node st-pending";
|
|
const badge = card.querySelector(".cc-node-badge");
|
|
badge.className = "cc-node-badge badge-pending";
|
|
badge.textContent = "Pending";
|
|
});
|
|
}
|
|
|
|
function typePrompt(text, cb) {
|
|
let i = 0;
|
|
promptEl.innerHTML = "";
|
|
const cursor = document.createElement("span");
|
|
cursor.className = "cc-prompt-cursor";
|
|
promptEl.appendChild(cursor);
|
|
|
|
function next() {
|
|
if (i < text.length) {
|
|
promptEl.insertBefore(
|
|
document.createTextNode(text[i]),
|
|
cursor,
|
|
);
|
|
i++;
|
|
setTimeout(next, 25 + Math.random() * 20);
|
|
} else {
|
|
setTimeout(() => {
|
|
cursor.remove();
|
|
cb();
|
|
}, 300);
|
|
}
|
|
}
|
|
next();
|
|
}
|
|
|
|
function showHeader(ex) {
|
|
flowNameEl.textContent = ex.flowName;
|
|
flowMetaEl.textContent = ex.meta;
|
|
headerEl.classList.add("visible");
|
|
}
|
|
|
|
function setNodeState(card, state, label) {
|
|
card.className = "cc-node st-" + state;
|
|
const badge = card.querySelector(".cc-node-badge");
|
|
badge.className =
|
|
"cc-node-badge badge-" +
|
|
(state === "done"
|
|
? "done"
|
|
: state === "active"
|
|
? "running"
|
|
: state === "review"
|
|
? "review"
|
|
: "pending");
|
|
badge.textContent = label;
|
|
}
|
|
|
|
function populateNodeContent(ex) {
|
|
nodeCards.forEach((card, i) => {
|
|
card.querySelector(".cc-node-name").textContent =
|
|
ex.nodes[i].name;
|
|
card.querySelector(".cc-node-agent").textContent =
|
|
ex.nodes[i].agent;
|
|
});
|
|
}
|
|
|
|
function animateNodes(ex, cb) {
|
|
const nodes = ex.nodes;
|
|
let step = 0;
|
|
const totalSteps = nodes.length;
|
|
|
|
function tick() {
|
|
if (step >= totalSteps) {
|
|
setTimeout(cb, 1800);
|
|
return;
|
|
}
|
|
const card = nodeCards[step];
|
|
const node = nodes[step];
|
|
const isReview = node.badge === "review";
|
|
|
|
// Mark current as active
|
|
setNodeState(card, "active", "Running");
|
|
|
|
// Update progress
|
|
const pct = Math.round(((step + 0.5) / totalSteps) * 100);
|
|
barFillEl.style.transition =
|
|
"width 0.8s cubic-bezier(.22,1,.36,1)";
|
|
barFillEl.style.width = pct + "%";
|
|
progressPctEl.textContent = pct + "%";
|
|
|
|
setTimeout(() => {
|
|
if (isReview) {
|
|
// Show as review first, then approve
|
|
setNodeState(card, "review", "Review");
|
|
const reviewPct = Math.round(
|
|
((step + 0.7) / totalSteps) * 100,
|
|
);
|
|
barFillEl.style.width = reviewPct + "%";
|
|
progressPctEl.textContent = reviewPct + "%";
|
|
setTimeout(() => {
|
|
setNodeState(card, "done", "Approved");
|
|
const donePct = Math.round(
|
|
((step + 1) / totalSteps) * 100,
|
|
);
|
|
barFillEl.style.width = donePct + "%";
|
|
progressPctEl.textContent = donePct + "%";
|
|
step++;
|
|
setTimeout(tick, 400);
|
|
}, 900);
|
|
} else {
|
|
setNodeState(card, "done", "Done");
|
|
const donePct = Math.round(((step + 1) / totalSteps) * 100);
|
|
barFillEl.style.width = donePct + "%";
|
|
progressPctEl.textContent = donePct + "%";
|
|
step++;
|
|
setTimeout(tick, 400);
|
|
}
|
|
}, 600);
|
|
}
|
|
tick();
|
|
}
|
|
|
|
function runExample(idx) {
|
|
if (animating) return;
|
|
animating = true;
|
|
currentExample = idx;
|
|
|
|
// Update pills
|
|
exBtns.forEach((b) => b.classList.remove("active"));
|
|
exBtns[idx].classList.add("active");
|
|
|
|
const ex = examples[idx];
|
|
resetPanel();
|
|
populateNodeContent(ex);
|
|
renderAgents(ex);
|
|
|
|
// Step 1: Type the prompt
|
|
setTimeout(() => {
|
|
typePrompt(ex.prompt, () => {
|
|
// Step 2: Show header
|
|
showHeader(ex);
|
|
// Step 3: Animate nodes sequentially
|
|
setTimeout(() => {
|
|
animateNodes(ex, () => {
|
|
animating = false;
|
|
// Auto-cycle to next after pause
|
|
autoTimer = setTimeout(() => {
|
|
runExample((currentExample + 1) % examples.length);
|
|
}, 2200);
|
|
});
|
|
}, 500);
|
|
});
|
|
}, 200);
|
|
}
|
|
|
|
// Pill click handlers
|
|
exBtns.forEach((btn) => {
|
|
btn.addEventListener("click", () => {
|
|
if (autoTimer) clearTimeout(autoTimer);
|
|
animating = false; // force-stop current animation
|
|
runExample(parseInt(btn.dataset.example));
|
|
});
|
|
});
|
|
|
|
// Start when section scrolls into view
|
|
ScrollTrigger.create({
|
|
trigger: "#command-center",
|
|
start: "top 75%",
|
|
once: true,
|
|
onEnter: () => {
|
|
if (!hasBeenVisible) {
|
|
hasBeenVisible = true;
|
|
runExample(0);
|
|
}
|
|
},
|
|
});
|
|
})();
|
|
} /* end initGSAP */
|
|
})();
|
|
</script>
|
|
|
|
<!-- ── Gradient color picker (easter egg — Shift+C) ── -->
|
|
<div class="grad-picker">
|
|
<button data-v="prism" class="active">Prism</button>
|
|
<button data-v="denim">Denim</button>
|
|
<button data-v="aurora">Aurora</button>
|
|
<button data-v="sunset">Sunset</button>
|
|
<button data-v="ice">Ice</button>
|
|
<button data-v="fire">Fire</button>
|
|
<button data-v="mono">Mono</button>
|
|
<div class="auto-btn" title="Auto-rotate colors">↻</div>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
const themes = [
|
|
"prism",
|
|
"denim",
|
|
"aurora",
|
|
"sunset",
|
|
"ice",
|
|
"fire",
|
|
"mono",
|
|
];
|
|
let autoInterval = null;
|
|
let currentIdx = 0;
|
|
const picker = document.querySelector(".grad-picker");
|
|
const autoBtn = picker.querySelector(".auto-btn");
|
|
const allBtns = picker.querySelectorAll("button");
|
|
|
|
function setTheme(name) {
|
|
document.documentElement.setAttribute("data-grad", name);
|
|
allBtns.forEach((b) =>
|
|
b.classList.toggle("active", b.dataset.v === name),
|
|
);
|
|
currentIdx = themes.indexOf(name);
|
|
}
|
|
|
|
// Click a swatch
|
|
picker.addEventListener("click", (e) => {
|
|
const btn = e.target.closest("button");
|
|
if (!btn) return;
|
|
stopAuto();
|
|
setTheme(btn.dataset.v);
|
|
});
|
|
|
|
// Auto-rotate
|
|
function startAuto() {
|
|
autoBtn.classList.add("active");
|
|
autoInterval = setInterval(() => {
|
|
currentIdx = (currentIdx + 1) % themes.length;
|
|
setTheme(themes[currentIdx]);
|
|
}, 4000);
|
|
}
|
|
function stopAuto() {
|
|
autoBtn.classList.remove("active");
|
|
if (autoInterval) {
|
|
clearInterval(autoInterval);
|
|
autoInterval = null;
|
|
}
|
|
}
|
|
autoBtn.addEventListener("click", () => {
|
|
if (autoInterval) {
|
|
stopAuto();
|
|
} else {
|
|
startAuto();
|
|
}
|
|
});
|
|
|
|
// Shift+C toggle picker
|
|
document.addEventListener("keydown", (e) => {
|
|
if (e.shiftKey && e.code === "KeyC") {
|
|
picker.classList.toggle("visible");
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
|
|
<!-- Floating Beta Badge -->
|
|
<div style="position:fixed;bottom:20px;right:20px;z-index:9999;background:rgba(10,132,255,.12);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(10,132,255,.25);border-radius:8px;padding:6px 14px;font-family:'Plus Jakarta Sans',sans-serif;font-size:12px;font-weight:600;letter-spacing:.04em;color:#0A84FF;pointer-events:none;user-select:none;text-transform:uppercase">beta</div>
|
|
</body>
|
|
</html>
|