diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index d34394b2..04f37955 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -132,3 +132,839 @@ body { .landing-page { font-family: var(--font-body), sans-serif; } + +/* Landing (Enterprise) */ +.landing-enterprise { + --primary-navy: #0a1628; + --secondary-navy: #1a2942; + --accent-gold: #d4af37; + --accent-teal: #2dd4bf; + --neutral-100: #f8fafb; + --neutral-200: #e5e9ed; + --neutral-300: #cbd2d9; + --neutral-700: #3e4c59; + --neutral-800: #1e293b; + --success: #10b981; + --warning: #f59e0b; + + min-height: 100vh; + font-family: var(--font-body), -apple-system, sans-serif; + background: var(--neutral-100); + color: var(--neutral-800); + line-height: 1.6; + overflow-x: hidden; +} + +@keyframes landing-slide-down { + from { + transform: translateY(-100%); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes landing-fade-in-up { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes landing-pulse { + 0%, + 100% { + opacity: 1; + transform: scale(1); + } + 50% { + opacity: 0.5; + transform: scale(1.1); + } +} + +.landing-enterprise .landing-nav { + position: fixed; + top: 0; + width: 100%; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-bottom: 1px solid var(--neutral-200); + z-index: 40; + animation: landing-slide-down 0.6s ease-out; +} + +.landing-enterprise .nav-container { + max-width: 1400px; + margin: 0 auto; + padding: 1.25rem 2.5rem; + display: flex; + justify-content: space-between; + align-items: center; + gap: 1.5rem; +} + +.landing-enterprise .logo-section { + display: flex; + align-items: center; + gap: 0.75rem; + text-decoration: none; +} + +.landing-enterprise .logo-icon { + width: 36px; + height: 36px; + background: linear-gradient(135deg, var(--primary-navy), var(--secondary-navy)); + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-weight: 600; + font-size: 18px; + box-shadow: 0 2px 8px rgba(10, 22, 40, 0.15); +} + +.landing-enterprise .logo-text { + display: flex; + flex-direction: column; + line-height: 1.2; +} + +.landing-enterprise .logo-name { + font-weight: 600; + font-size: 20px; + letter-spacing: -0.02em; + color: var(--primary-navy); +} + +.landing-enterprise .logo-tagline { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--neutral-700); + font-weight: 500; +} + +.landing-enterprise .nav-links { + display: flex; + gap: 2.5rem; + align-items: center; +} + +.landing-enterprise .nav-links a { + color: var(--neutral-700); + text-decoration: none; + font-weight: 500; + font-size: 15px; + transition: color 0.3s ease; + letter-spacing: -0.01em; +} + +.landing-enterprise .nav-links a:hover { + color: var(--primary-navy); +} + +.landing-enterprise .nav-cta { + display: flex; + gap: 1rem; + align-items: center; +} + +.landing-enterprise .btn-secondary { + padding: 0.625rem 1.25rem; + border: 1.5px solid var(--neutral-300); + background: white; + color: var(--neutral-800); + border-radius: 8px; + font-weight: 500; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; +} + +.landing-enterprise .btn-secondary:hover { + border-color: var(--primary-navy); + background: var(--neutral-100); +} + +.landing-enterprise .btn-primary { + padding: 0.625rem 1.5rem; + background: var(--primary-navy); + color: white; + border: none; + border-radius: 8px; + font-weight: 500; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(10, 22, 40, 0.15); +} + +.landing-enterprise .btn-primary:hover { + background: var(--secondary-navy); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(10, 22, 40, 0.2); +} + +.landing-enterprise .hero { + margin-top: 80px; + padding: 6rem 2.5rem 4rem; + max-width: 1400px; + margin-left: auto; + margin-right: auto; + display: grid; + grid-template-columns: 1fr; + gap: 4rem; + align-items: center; +} + +.landing-enterprise .hero-content { + animation: landing-fade-in-up 0.8s ease-out 0.2s both; +} + +.landing-enterprise .hero-label { + display: inline-block; + padding: 0.5rem 1rem; + background: linear-gradient(135deg, rgba(10, 22, 40, 0.05), rgba(45, 212, 191, 0.08)); + border: 1px solid rgba(45, 212, 191, 0.2); + border-radius: 50px; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.05em; + text-transform: uppercase; + color: var(--accent-teal); + margin-bottom: 1.5rem; +} + +.landing-enterprise .hero h1 { + font-family: var(--font-display), serif; + font-size: 56px; + line-height: 1.15; + color: var(--primary-navy); + margin-bottom: 1.5rem; + font-weight: 400; + letter-spacing: -0.02em; +} + +.landing-enterprise .hero-highlight { + background: linear-gradient(135deg, var(--accent-teal), var(--accent-gold)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + font-style: italic; +} + +.landing-enterprise .hero p { + font-size: 19px; + line-height: 1.7; + color: var(--neutral-700); + margin-bottom: 2.5rem; + font-weight: 400; +} + +.landing-enterprise .hero-actions { + display: flex; + gap: 1rem; + margin-bottom: 3rem; +} + +.landing-enterprise .btn-large { + padding: 1rem 2rem; + font-size: 16px; + font-weight: 500; + border-radius: 10px; + cursor: pointer; + transition: all 0.3s ease; + display: inline-flex; + align-items: center; + gap: 0.5rem; + text-decoration: none; +} + +.landing-enterprise .btn-large.primary { + background: var(--primary-navy); + color: white; + border: none; + box-shadow: 0 4px 12px rgba(10, 22, 40, 0.2); +} + +.landing-enterprise .btn-large.primary:hover { + background: var(--secondary-navy); + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(10, 22, 40, 0.25); +} + +.landing-enterprise .btn-large.secondary { + background: white; + color: var(--neutral-800); + border: 1.5px solid var(--neutral-300); +} + +.landing-enterprise .btn-large.secondary:hover { + border-color: var(--primary-navy); + background: var(--neutral-100); +} + +.landing-enterprise .hero-features { + display: flex; + gap: 2rem; + padding-top: 2rem; + border-top: 1px solid var(--neutral-200); +} + +.landing-enterprise .hero-feature { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.landing-enterprise .feature-icon { + width: 20px; + height: 20px; + background: var(--accent-teal); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 12px; + flex-shrink: 0; +} + +.landing-enterprise .hero-feature span { + font-size: 14px; + font-weight: 500; + color: var(--neutral-700); +} + +.landing-enterprise .command-surface { + background: white; + border-radius: 16px; + box-shadow: 0 8px 32px rgba(10, 22, 40, 0.08); + overflow: hidden; + animation: landing-fade-in-up 0.8s ease-out 0.4s both; + border: 1px solid var(--neutral-200); +} + +.landing-enterprise .surface-header { + padding: 1.5rem 2rem; + background: linear-gradient(135deg, var(--primary-navy), var(--secondary-navy)); + color: white; + display: flex; + justify-content: space-between; + align-items: center; +} + +.landing-enterprise .surface-title { + font-size: 13px; + text-transform: uppercase; + letter-spacing: 0.1em; + font-weight: 600; + opacity: 0.9; +} + +.landing-enterprise .live-indicator { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 12px; + font-weight: 600; +} + +.landing-enterprise .live-dot { + width: 8px; + height: 8px; + background: var(--accent-teal); + border-radius: 50%; + animation: landing-pulse 2s infinite; +} + +.landing-enterprise .surface-subtitle { + padding: 1.25rem 2rem; + background: var(--neutral-100); + border-bottom: 1px solid var(--neutral-200); +} + +.landing-enterprise .surface-subtitle h3 { + font-size: 16px; + font-weight: 600; + color: var(--primary-navy); + margin-bottom: 0.25rem; +} + +.landing-enterprise .surface-subtitle p { + font-size: 13px; + color: var(--neutral-700); +} + +.landing-enterprise .metrics-row { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0; + border-bottom: 1px solid var(--neutral-200); +} + +.landing-enterprise .metric { + padding: 1.75rem 2rem; + text-align: center; + border-right: 1px solid var(--neutral-200); +} + +.landing-enterprise .metric:last-child { + border-right: none; +} + +.landing-enterprise .metric-value { + font-size: 36px; + font-weight: 300; + color: var(--primary-navy); + letter-spacing: -0.02em; + margin-bottom: 0.25rem; +} + +.landing-enterprise .metric-label { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--neutral-700); + font-weight: 600; +} + +.landing-enterprise .surface-content { + padding: 2rem; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; +} + +.landing-enterprise .content-section h4 { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--neutral-700); + font-weight: 600; + margin-bottom: 1rem; +} + +.landing-enterprise .status-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 0; + border-bottom: 1px solid var(--neutral-200); +} + +.landing-enterprise .status-item:last-child { + border-bottom: none; +} + +.landing-enterprise .status-icon { + width: 28px; + height: 28px; + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + font-size: 14px; +} + +.landing-enterprise .status-icon.progress { + background: rgba(45, 212, 191, 0.1); + color: var(--accent-teal); +} + +.landing-enterprise .status-item-title { + font-size: 14px; + font-weight: 500; + color: var(--primary-navy); +} + +.landing-enterprise .approval-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.875rem 0; + border-bottom: 1px solid var(--neutral-200); + gap: 0.75rem; +} + +.landing-enterprise .approval-item:last-child { + border-bottom: none; +} + +.landing-enterprise .approval-title { + font-size: 14px; + color: var(--neutral-800); + font-weight: 500; +} + +.landing-enterprise .approval-badge { + padding: 0.35rem 0.75rem; + border-radius: 6px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + white-space: nowrap; +} + +.landing-enterprise .approval-badge.ready { + background: rgba(16, 185, 129, 0.1); + color: var(--success); +} + +.landing-enterprise .approval-badge.waiting { + background: rgba(245, 158, 11, 0.1); + color: var(--warning); +} + +.landing-enterprise .signal-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.75rem 0; + border-bottom: 1px solid var(--neutral-200); + gap: 0.75rem; +} + +.landing-enterprise .signal-item:last-child { + border-bottom: none; +} + +.landing-enterprise .signal-text { + font-size: 13px; + color: var(--neutral-700); +} + +.landing-enterprise .signal-time { + font-size: 12px; + color: var(--neutral-700); + font-weight: 500; + white-space: nowrap; +} + +.landing-enterprise .features-section { + padding: 6rem 2.5rem; + max-width: 1400px; + margin: 0 auto; +} + +.landing-enterprise #capabilities { + scroll-margin-top: 110px; +} + +.landing-enterprise .features-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 2rem; + margin-top: 3rem; +} + +.landing-enterprise .feature-card { + background: white; + padding: 2rem; + border-radius: 12px; + border: 1px solid var(--neutral-200); + transition: all 0.3s ease; + animation: landing-fade-in-up 0.6s ease-out both; +} + +.landing-enterprise .feature-card:nth-child(1) { + animation-delay: 0.1s; +} + +.landing-enterprise .feature-card:nth-child(2) { + animation-delay: 0.2s; +} + +.landing-enterprise .feature-card:nth-child(3) { + animation-delay: 0.3s; +} + +.landing-enterprise .feature-card:nth-child(4) { + animation-delay: 0.4s; +} + +.landing-enterprise .feature-card:hover { + transform: translateY(-4px); + box-shadow: 0 12px 32px rgba(10, 22, 40, 0.12); + border-color: var(--accent-teal); +} + +.landing-enterprise .feature-number { + width: 48px; + height: 48px; + background: linear-gradient(135deg, rgba(10, 22, 40, 0.05), rgba(45, 212, 191, 0.08)); + border: 1px solid var(--neutral-200); + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + margin-bottom: 1.5rem; + color: var(--primary-navy); + font-weight: 300; +} + +.landing-enterprise .feature-card h3 { + font-size: 18px; + font-weight: 600; + color: var(--primary-navy); + margin-bottom: 0.75rem; + letter-spacing: -0.01em; +} + +.landing-enterprise .feature-card p { + font-size: 14px; + line-height: 1.6; + color: var(--neutral-700); +} + +.landing-enterprise .cta-section { + padding: 5rem 2.5rem; + background: linear-gradient(135deg, var(--primary-navy), var(--secondary-navy)); + text-align: center; +} + +.landing-enterprise .cta-content { + max-width: 800px; + margin: 0 auto; +} + +.landing-enterprise .cta-section h2 { + font-family: var(--font-display), serif; + font-size: 42px; + color: white; + margin-bottom: 1rem; + font-weight: 400; + letter-spacing: -0.01em; +} + +.landing-enterprise .cta-section p { + font-size: 18px; + color: rgba(255, 255, 255, 0.8); + margin-bottom: 2.5rem; +} + +.landing-enterprise .cta-actions { + display: flex; + gap: 1rem; + justify-content: center; + flex-wrap: wrap; +} + +.landing-enterprise .btn-large.white { + background: white; + color: var(--primary-navy); + border: none; +} + +.landing-enterprise .btn-large.white:hover { + background: var(--neutral-100); + transform: translateY(-2px); +} + +.landing-enterprise .btn-large.outline { + background: transparent; + color: white; + border: 1.5px solid rgba(255, 255, 255, 0.3); +} + +.landing-enterprise .btn-large.outline:hover { + background: rgba(255, 255, 255, 0.1); + border-color: white; +} + +.landing-enterprise .landing-footer { + background: var(--neutral-100); + border-top: 1px solid var(--neutral-200); + padding: 3rem 2.5rem 2rem; +} + +.landing-enterprise .footer-content { + max-width: 1400px; + margin: 0 auto; + display: grid; + grid-template-columns: 2fr 1fr 1fr 1fr; + gap: 4rem; + margin-bottom: 3rem; +} + +.landing-enterprise .footer-brand h3 { + font-size: 18px; + font-weight: 600; + color: var(--primary-navy); + margin-bottom: 0.75rem; +} + +.landing-enterprise .footer-brand p { + font-size: 14px; + color: var(--neutral-700); + line-height: 1.6; + margin-bottom: 1.5rem; +} + +.landing-enterprise .footer-tagline { + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--neutral-700); + font-weight: 600; +} + +.landing-enterprise .footer-column h4 { + font-size: 13px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--neutral-700); + font-weight: 600; + margin-bottom: 1rem; +} + +.landing-enterprise .footer-links { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.landing-enterprise .footer-links a, +.landing-enterprise .footer-links button { + color: var(--neutral-700); + text-decoration: none; + font-size: 14px; + transition: color 0.3s ease; + background: transparent; + border: none; + padding: 0; + cursor: pointer; + text-align: left; + font-weight: 400; +} + +.landing-enterprise .footer-links a:hover, +.landing-enterprise .footer-links button:hover { + color: var(--primary-navy); +} + +.landing-enterprise .footer-bottom { + max-width: 1400px; + margin: 0 auto; + padding-top: 2rem; + border-top: 1px solid var(--neutral-200); + display: flex; + justify-content: space-between; + align-items: center; + gap: 1rem; + flex-wrap: wrap; +} + +.landing-enterprise .footer-copyright { + font-size: 13px; + color: var(--neutral-700); +} + +.landing-enterprise .footer-bottom-links { + display: flex; + gap: 2rem; + flex-wrap: wrap; +} + +.landing-enterprise .footer-bottom-links a { + font-size: 13px; + color: var(--neutral-700); + text-decoration: none; + transition: color 0.3s ease; +} + +.landing-enterprise .footer-bottom-links a:hover { + color: var(--primary-navy); +} + +@media (max-width: 1024px) { + .landing-enterprise .nav-container { + padding: 1rem 1.5rem; + } + + .landing-enterprise .nav-links { + display: none; + } + + .landing-enterprise .hero { + grid-template-columns: 1fr; + gap: 3rem; + } + + .landing-enterprise .features-grid { + grid-template-columns: repeat(2, 1fr); + } + + .landing-enterprise .footer-content { + grid-template-columns: 1fr 1fr; + } +} + +@media (max-width: 768px) { + .landing-enterprise .hero { + padding: 4.5rem 1.25rem 3rem; + } + + .landing-enterprise .hero h1 { + font-size: 40px; + } + + .landing-enterprise .hero-actions { + flex-direction: column; + } + + .landing-enterprise .btn-large { + width: 100%; + justify-content: center; + } + + .landing-enterprise .hero-features { + flex-direction: column; + gap: 1rem; + } + + .landing-enterprise .features-section { + padding: 4.5rem 1.25rem; + } + + .landing-enterprise .features-grid { + grid-template-columns: 1fr; + } + + .landing-enterprise .metrics-row { + grid-template-columns: 1fr; + } + + .landing-enterprise .metric { + border-right: none; + border-bottom: 1px solid var(--neutral-200); + } + + .landing-enterprise .metric:last-child { + border-bottom: none; + } + + .landing-enterprise .surface-content { + grid-template-columns: 1fr; + } + + .landing-enterprise .landing-footer { + padding: 2.5rem 1.25rem 2rem; + } + + .landing-enterprise .footer-content { + grid-template-columns: 1fr; + gap: 2rem; + } +} diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 905dfaef..12028ad9 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -3,7 +3,7 @@ import "./globals.css"; import type { Metadata } from "next"; import type { ReactNode } from "react"; -import { IBM_Plex_Sans, Sora } from "next/font/google"; +import { DM_Serif_Display, IBM_Plex_Sans, Sora } from "next/font/google"; import { AuthProvider } from "@/components/providers/AuthProvider"; import { QueryProvider } from "@/components/providers/QueryProvider"; @@ -27,11 +27,18 @@ const headingFont = Sora({ weight: ["500", "600", "700"], }); +const displayFont = DM_Serif_Display({ + subsets: ["latin"], + display: "swap", + variable: "--font-display", + weight: ["400"], +}); + export default function RootLayout({ children }: { children: ReactNode }) { return ( {children} diff --git a/frontend/src/components/molecules/HeroCopy.tsx b/frontend/src/components/molecules/HeroCopy.tsx index b6892343..0639c68a 100644 --- a/frontend/src/components/molecules/HeroCopy.tsx +++ b/frontend/src/components/molecules/HeroCopy.tsx @@ -3,16 +3,22 @@ import { HeroKicker } from "@/components/atoms/HeroKicker"; export function HeroCopy() { return (
- Mission Control + OpenClaw Mission Control

- Enterprise control for + Command autonomous work.
- autonomous execution. + + Keep human oversight. +

- Coordinate boards, agents, and approvals in one command layer. No - status meetings. No blind spots. Just durable execution. + Track tasks, approvals, and agent health in one calm surface. Get + realtime signals when work changes, without chasing people for status.

diff --git a/frontend/src/components/organisms/LandingHero.tsx b/frontend/src/components/organisms/LandingHero.tsx index 349bd48a..e9117fc2 100644 --- a/frontend/src/components/organisms/LandingHero.tsx +++ b/frontend/src/components/organisms/LandingHero.tsx @@ -1,105 +1,269 @@ "use client"; -import { SignInButton, SignedIn, SignedOut } from "@/auth/clerk"; +import Link from "next/link"; -import { HeroCopy } from "@/components/molecules/HeroCopy"; -import { Button } from "@/components/ui/button"; +import { SignInButton, SignedIn, SignedOut, isClerkEnabled } from "@/auth/clerk"; + +const ArrowIcon = () => ( + +); export function LandingHero() { - return ( -
-
- -
- - - - - - -
- You're signed in. Open your boards when you're ready. -
-
-
-
- - Enterprise ready - - - Agent-first ops - - - 24/7 visibility - -
-
+ const clerkEnabled = isClerkEnabled(); -
-
-
- Command surface - - Live - + return ( + <> +
+
+
OpenClaw Mission Control
+

+ Command autonomous work. +
+ Keep human oversight. +

+

+ Track tasks, approvals, and agent health in one unified command + center. Get real-time signals when work changes, without losing the + thread of execution. +

+ +
+ + {clerkEnabled ? ( + <> + + + + + + + + ) : ( + <> + + Open Boards + + + Create Board + + + )} + + + + + Open Boards + + + Create Board + +
-
-
-

- Tasks claimed, tracked, delivered. -

-

- See every queue, agent, and handoff without chasing updates. -

+ +
+ {[ + "Agent-First Operations", + "Approval Queues", + "Live Signals", + ].map((label) => ( +
+
+ {label} +
+ ))} +
+
+ +
+
+
Command Surface
+
+
+ LIVE
-
+
+
+

Ship work without losing the thread.

+

Tasks, approvals, and agent status stay synced across the board.

+
+
+ {[ + { label: "Boards", value: "12" }, + { label: "Agents", value: "08" }, + { label: "Tasks", value: "46" }, + ].map((item) => ( +
+
{item.value}
+
{item.label}
+
+ ))} +
+
+
+

Board — In Progress

{[ - { label: "Active boards", value: "12" }, - { label: "Agents live", value: "08" }, - { label: "Tasks in flow", value: "46" }, - ].map((item) => ( -
-
- {item.value} -
-
- {item.label} + "Cut release candidate", + "Triage approvals backlog", + "Stabilize agent handoffs", + ].map((title) => ( +
+
+
+
{title}
))}
-
-
- Signals - Updated 2m ago -
-
-
- Agent Delta moved task to review - Just now + +
+

Approvals — 3 Pending

+ {[ + { title: "Deploy window confirmed", status: "ready" as const }, + { title: "Copy reviewed", status: "waiting" as const }, + { title: "Security sign-off", status: "waiting" as const }, + ].map((item) => ( +
+
{item.title}
+
+ {item.status} +
-
- Board Growth Ops hit WIP limit - 5m + ))} +
+
+ +
+
+

Signals — Updated Moments Ago

+ {[ + { text: "Agent Delta moved task to review", time: "Now" }, + { text: "Growth Ops hit WIP limit", time: "5m" }, + { text: "Release pipeline stabilized", time: "12m" }, + ].map((signal) => ( +
+
{signal.text}
+
{signal.time}
-
- Release tasks stabilized - 12m -
-
+ ))}
-
-
+
+ +
+
+ {[ + { + title: "Boards as ops maps", + description: + "Keep tasks, priorities, dependencies, and ownership visible at a glance.", + }, + { + title: "Approvals that move", + description: + "Queue, comment, and approve without losing context or slowing execution.", + }, + { + title: "Realtime signals", + description: + "See work change as it happens: tasks, agent status, and approvals update live.", + }, + { + title: "Audit trail built in", + description: + "Every decision leaves a trail, so the board stays explainable and reviewable.", + }, + ].map((feature, idx) => ( +
+
+ {String(idx + 1).padStart(2, "0")} +
+

{feature.title}

+

{feature.description}

+
+ ))} +
+
+ +
+
+

Start with one board. Grow into a control room.

+

+ Onboard a board, name a lead agent, and keep approvals and signals + visible from day one. +

+
+ + {clerkEnabled ? ( + <> + + + + + + + + ) : ( + <> + + Create Board + + + View Boards + + + )} + + + + + Create Board + + + View Boards + + +
+
+
+ ); } + diff --git a/frontend/src/components/organisms/UserMenu.tsx b/frontend/src/components/organisms/UserMenu.tsx index 661fbeab..c41f6f3c 100644 --- a/frontend/src/components/organisms/UserMenu.tsx +++ b/frontend/src/components/organisms/UserMenu.tsx @@ -1,13 +1,25 @@ "use client"; import Image from "next/image"; +import Link from "next/link"; +import { useState } from "react"; import { SignOutButton, useUser } from "@/auth/clerk"; -import { LogOut } from "lucide-react"; +import { + Activity, + Bot, + ChevronDown, + LayoutDashboard, + LogOut, + Plus, + Server, + Trello, +} from "lucide-react"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { cn } from "@/lib/utils"; export function UserMenu({ className }: { className?: string }) { + const [open, setOpen] = useState(false); const { user } = useUser(); if (!user) return null; @@ -19,39 +31,59 @@ export function UserMenu({ className }: { className?: string }) { const displayEmail = user.primaryEmailAddress?.emailAddress ?? ""; return ( - + -
+
- + {avatarUrl ? (
-
+
{displayName}
{displayEmail ? ( -
{displayEmail}
+
+ {displayEmail} +
) : null}
+
+ setOpen(false)} + > + + Open boards + + setOpen(false)} + > + + Create board + +
+ +
+ + {( + [ + { href: "/dashboard", label: "Dashboard", icon: LayoutDashboard }, + { href: "/activity", label: "Activity", icon: Activity }, + { href: "/agents", label: "Agents", icon: Bot }, + { href: "/gateways", label: "Gateways", icon: Server }, + ] as const + ).map((item) => ( + setOpen(false)} + > + + {item.label} + + ))} + +
+ diff --git a/frontend/src/components/templates/LandingShell.tsx b/frontend/src/components/templates/LandingShell.tsx index 32d6af7a..a63dfaae 100644 --- a/frontend/src/components/templates/LandingShell.tsx +++ b/frontend/src/components/templates/LandingShell.tsx @@ -1,39 +1,159 @@ "use client"; +import Link from "next/link"; import type { ReactNode } from "react"; -import { SignedIn } from "@/auth/clerk"; +import { SignInButton, SignedIn, SignedOut, isClerkEnabled } from "@/auth/clerk"; -import { BrandMark } from "@/components/atoms/BrandMark"; import { UserMenu } from "@/components/organisms/UserMenu"; export function LandingShell({ children }: { children: ReactNode }) { - return ( -
-
-
+ + +
{children}
+ +
); } diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs index 232ec029..f46b047b 100644 --- a/frontend/tailwind.config.cjs +++ b/frontend/tailwind.config.cjs @@ -7,6 +7,7 @@ module.exports = { fontFamily: { heading: ["var(--font-heading)", "sans-serif"], body: ["var(--font-body)", "sans-serif"], + display: ["var(--font-display)", "serif"], }, }, },