mirror of
https://github.com/pocketpaw/pocketpaw.git
synced 2026-05-21 01:04:57 +00:00
4076 lines
138 KiB
HTML
4076 lines
138 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.
|
|
2026-02-16: Fixed copy button (clipboard fallback + reads text from DOM),
|
|
fixed CTA button text color (white on btn--fill, specificity override). -->
|
|
<!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.xyz/" />
|
|
<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.xyz/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="@prakashd88" />
|
|
<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.xyz/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", "ProductivityApplication", "UtilitiesApplication"],
|
|
"operatingSystem": "Linux, macOS, Windows",
|
|
"url": "https://pocketpaw.xyz",
|
|
"downloadUrl": "https://pypi.org/project/pocketpaw/",
|
|
"softwareVersion": "0.4.7",
|
|
"license": "https://opensource.org/licenses/MIT",
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "0",
|
|
"priceCurrency": "USD"
|
|
},
|
|
"author": {
|
|
"@type": "Organization",
|
|
"name": "PocketPaw",
|
|
"url": "https://github.com/pocketpaw"
|
|
}
|
|
}
|
|
</script>
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "FAQPage",
|
|
"mainEntity": [
|
|
{
|
|
"@type": "Question",
|
|
"name": "What is a self-hosted AI agent?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "A self-hosted AI agent is software that runs on your own computer or server instead of in the cloud. It can answer questions, execute code, browse the web, manage files, and take actions on your behalf, all while keeping your data private. PocketPaw is an open-source self-hosted AI agent that connects to Telegram, Discord, Slack, WhatsApp, and more."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Can I run an AI agent without an API key?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Yes. PocketPaw works with Ollama, which runs open-source language models (like Llama, Qwen, Mistral) directly on your hardware. No API keys, no accounts, no usage fees. You need at least 4GB of RAM for a 7B parameter model."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "What messaging platforms does PocketPaw support?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "PocketPaw connects to 9+ platforms: Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Microsoft Teams, Google Chat, and a built-in web dashboard. All channels share the same AI agent, tools, and conversation memory."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Is PocketPaw free to use?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "PocketPaw is completely free and open-source under the MIT license. The software itself has no cost. If you use cloud AI providers like Anthropic or OpenAI, their standard API pricing applies. For zero-cost operation, use Ollama with free local models."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "What's the difference between an AI agent and a chatbot?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "A chatbot generates text responses to questions. An AI agent can take actions: browsing websites, executing code, managing files, sending emails, and completing multi-step tasks autonomously. PocketPaw is an AI agent with 50+ built-in tools that can act on your behalf across multiple platforms."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "How do I install PocketPaw?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Run 'pip install pocketpaw' or use the interactive installer: 'curl -fsSL https://pocketpaw.xyz/install.sh | sh'. Then run 'pocketpaw' to start the web dashboard. The whole process takes under 5 minutes. PocketPaw requires Python 3.11 or higher."
|
|
}
|
|
}
|
|
]
|
|
}
|
|
</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,
|
|
a.btn--fill {
|
|
background: var(--lp-blue);
|
|
color: #fff;
|
|
border: 2px solid var(--lp-blue);
|
|
}
|
|
.btn--fill:hover,
|
|
a.btn--fill:hover {
|
|
background: var(--lp-blue-hover);
|
|
border-color: var(--lp-blue-hover);
|
|
color: #fff;
|
|
}
|
|
.btn--ghost,
|
|
a.btn--ghost {
|
|
background: transparent;
|
|
color: var(--lp-text);
|
|
border: 1.5px solid transparent;
|
|
}
|
|
.btn--ghost:hover,
|
|
a.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>
|
|
<a
|
|
href="https://discord.gg/asRrtm95Zc"
|
|
target="_blank"
|
|
rel="noopener"
|
|
class="nav-a"
|
|
>
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
<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-.128 10.2 10.2 0 00.372-.292.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>
|
|
<span class="nav-a-text">Discord</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><br>
|
|
<br>
|
|
<span class="prompt">$</span> pip install pocketpaw<span class="hl">[memory]</span> <span class="comment"># Add Mem0 semantic search</span><br>
|
|
<br>
|
|
<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>
|
|
|
|
<!-- ───────────── FAQ ───────────── -->
|
|
<section style="padding: 80px 0; background: var(--bg, #f9f8f6);">
|
|
<div class="wrap" style="max-width: 800px;">
|
|
<h2 class="heading scroll-text" style="text-align: center; margin-bottom: 48px; font-size: clamp(1.6rem, 3vw, 2.2rem);">
|
|
Frequently Asked Questions
|
|
</h2>
|
|
|
|
<div style="display: flex; flex-direction: column; gap: 16px;">
|
|
<details style="border: 1px solid rgba(26,26,46,0.08); border-radius: 12px; padding: 20px 24px; background: var(--card, #fff);">
|
|
<summary style="cursor: pointer; font-weight: 600; font-size: 1.05rem; font-family: 'Plus Jakarta Sans', sans-serif; color: var(--text, #1a1a2e); list-style: none; display: flex; justify-content: space-between; align-items: center;">
|
|
What is a self-hosted AI agent?
|
|
</summary>
|
|
<p style="margin-top: 12px; line-height: 1.7; color: rgba(26,26,46,0.7); font-size: 0.95rem;">
|
|
A self-hosted AI agent runs on your own computer or server instead of in the cloud. It can answer questions, execute code, browse the web, manage files, and take actions on your behalf. Your data stays on your machine. PocketPaw is an open-source self-hosted AI agent that connects to Telegram, Discord, Slack, WhatsApp, and more.
|
|
</p>
|
|
</details>
|
|
|
|
<details style="border: 1px solid rgba(26,26,46,0.08); border-radius: 12px; padding: 20px 24px; background: var(--card, #fff);">
|
|
<summary style="cursor: pointer; font-weight: 600; font-size: 1.05rem; font-family: 'Plus Jakarta Sans', sans-serif; color: var(--text, #1a1a2e); list-style: none; display: flex; justify-content: space-between; align-items: center;">
|
|
Can I run PocketPaw without an API key?
|
|
</summary>
|
|
<p style="margin-top: 12px; line-height: 1.7; color: rgba(26,26,46,0.7); font-size: 0.95rem;">
|
|
Yes. PocketPaw works with <a href="/guides/local-llm-agent" style="color: #0A84FF;">Ollama</a>, which runs open-source models (Llama, Qwen, Mistral) directly on your hardware. No API keys, no accounts, no usage fees. You need at least 4GB of RAM for a 7B parameter model.
|
|
</p>
|
|
</details>
|
|
|
|
<details style="border: 1px solid rgba(26,26,46,0.08); border-radius: 12px; padding: 20px 24px; background: var(--card, #fff);">
|
|
<summary style="cursor: pointer; font-weight: 600; font-size: 1.05rem; font-family: 'Plus Jakarta Sans', sans-serif; color: var(--text, #1a1a2e); list-style: none; display: flex; justify-content: space-between; align-items: center;">
|
|
What messaging platforms does PocketPaw support?
|
|
</summary>
|
|
<p style="margin-top: 12px; line-height: 1.7; color: rgba(26,26,46,0.7); font-size: 0.95rem;">
|
|
PocketPaw connects to 9+ platforms: Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Microsoft Teams, Google Chat, and a built-in web dashboard. All channels share the same AI agent, tools, and conversation memory.
|
|
</p>
|
|
</details>
|
|
|
|
<details style="border: 1px solid rgba(26,26,46,0.08); border-radius: 12px; padding: 20px 24px; background: var(--card, #fff);">
|
|
<summary style="cursor: pointer; font-weight: 600; font-size: 1.05rem; font-family: 'Plus Jakarta Sans', sans-serif; color: var(--text, #1a1a2e); list-style: none; display: flex; justify-content: space-between; align-items: center;">
|
|
Is PocketPaw free?
|
|
</summary>
|
|
<p style="margin-top: 12px; line-height: 1.7; color: rgba(26,26,46,0.7); font-size: 0.95rem;">
|
|
Completely free and open-source under the MIT license. If you use cloud providers like Anthropic or OpenAI, their standard API pricing applies. For zero-cost operation, use Ollama with local models.
|
|
</p>
|
|
</details>
|
|
|
|
<details style="border: 1px solid rgba(26,26,46,0.08); border-radius: 12px; padding: 20px 24px; background: var(--card, #fff);">
|
|
<summary style="cursor: pointer; font-weight: 600; font-size: 1.05rem; font-family: 'Plus Jakarta Sans', sans-serif; color: var(--text, #1a1a2e); list-style: none; display: flex; justify-content: space-between; align-items: center;">
|
|
What's the difference between an AI agent and a chatbot?
|
|
</summary>
|
|
<p style="margin-top: 12px; line-height: 1.7; color: rgba(26,26,46,0.7); font-size: 0.95rem;">
|
|
A chatbot generates text responses. An AI agent can take real actions: browsing websites, writing code, managing files, sending emails, and completing multi-step tasks. PocketPaw ships with <a href="/tools" style="color: #0A84FF;">50+ built-in tools</a> that let it act on your behalf. <a href="/guides/ai-agent-vs-chatbot" style="color: #0A84FF;">Read the full comparison</a>.
|
|
</p>
|
|
</details>
|
|
|
|
<details style="border: 1px solid rgba(26,26,46,0.08); border-radius: 12px; padding: 20px 24px; background: var(--card, #fff);">
|
|
<summary style="cursor: pointer; font-weight: 600; font-size: 1.05rem; font-family: 'Plus Jakarta Sans', sans-serif; color: var(--text, #1a1a2e); list-style: none; display: flex; justify-content: space-between; align-items: center;">
|
|
How do I install PocketPaw?
|
|
</summary>
|
|
<p style="margin-top: 12px; line-height: 1.7; color: rgba(26,26,46,0.7); font-size: 0.95rem;">
|
|
Run <code style="background: rgba(10,132,255,0.08); padding: 2px 6px; border-radius: 4px; font-family: 'JetBrains Mono', monospace; font-size: 0.85rem;">pip install pocketpaw</code> or use the interactive installer. Then run <code style="background: rgba(10,132,255,0.08); padding: 2px 6px; border-radius: 4px; font-family: 'JetBrains Mono', monospace; font-size: 0.85rem;">pocketpaw</code> to start the web dashboard. Takes under 5 minutes. Requires Python 3.11+. See the <a href="/getting-started/installation" style="color: #0A84FF;">full installation guide</a>.
|
|
</p>
|
|
</details>
|
|
</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="/getting-started/installation" class="foot-a">Get Started</a>
|
|
<a href="/introduction" class="foot-a">Docs</a>
|
|
<a href="/guides" class="foot-a">Guides</a>
|
|
<a href="/channels" class="foot-a">Channels</a>
|
|
<a href="/tools" class="foot-a">Tools</a>
|
|
<a href="/backends" class="foot-a">Backends</a>
|
|
<a
|
|
href="https://github.com/pocketpaw/pocketpaw"
|
|
target="_blank"
|
|
rel="noopener"
|
|
class="foot-a"
|
|
>GitHub</a
|
|
>
|
|
<a
|
|
href="https://discord.gg/asRrtm95Zc"
|
|
target="_blank"
|
|
rel="noopener"
|
|
class="foot-a"
|
|
>Discord</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) {
|
|
var codeEl = btn.parentElement && btn.parentElement.querySelector("code");
|
|
var text = codeEl
|
|
? codeEl.textContent.replace(/^\$\s*/, "").trim()
|
|
: "curl -fsSL https://pocketpaw.xyz/install.sh | sh";
|
|
|
|
function onSuccess() {
|
|
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);
|
|
}
|
|
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
navigator.clipboard.writeText(text).then(onSuccess).catch(function () {
|
|
fallbackCopy(text, onSuccess);
|
|
});
|
|
} else {
|
|
fallbackCopy(text, onSuccess);
|
|
}
|
|
}
|
|
|
|
function fallbackCopy(text, cb) {
|
|
var ta = document.createElement("textarea");
|
|
ta.value = text;
|
|
ta.style.position = "fixed";
|
|
ta.style.opacity = "0";
|
|
document.body.appendChild(ta);
|
|
ta.select();
|
|
try {
|
|
document.execCommand("copy");
|
|
if (cb) cb();
|
|
} catch (_) {}
|
|
document.body.removeChild(ta);
|
|
}
|
|
|
|
/* 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, 0.12);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
border: 1px solid rgba(10, 132, 255, 0.25);
|
|
border-radius: 8px;
|
|
padding: 6px 14px;
|
|
font-family: "Plus Jakarta Sans", sans-serif;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.04em;
|
|
color: #0a84ff;
|
|
pointer-events: none;
|
|
user-select: none;
|
|
text-transform: uppercase;
|
|
"
|
|
>
|
|
beta
|
|
</div>
|
|
</body>
|
|
</html>
|