interim product page layout

This commit is contained in:
Ramon Perez 2025-07-24 23:57:14 +10:00
parent 49de36cac8
commit df5fac06b4
19 changed files with 1943 additions and 10117 deletions

View File

@ -1,366 +0,0 @@
---
export interface Props {
variant?: 'subtle' | 'prominent' | 'animated';
color?: 'green' | 'amber' | 'blue' | 'multi';
density?: 'low' | 'medium' | 'high';
animated?: boolean;
opacity?: number;
}
const {
variant = 'subtle',
color = 'green',
density = 'medium',
animated = true,
opacity = 0.1
} = Astro.props;
const colorSchemes = {
green: {
primary: '#00ff41',
secondary: '#00cc33',
accent: '#008822'
},
amber: {
primary: '#ffb000',
secondary: '#ff9500',
accent: '#cc7700'
},
blue: {
primary: '#00bfff',
secondary: '#0099cc',
accent: '#007799'
},
multi: {
primary: '#00ff41',
secondary: '#ffb000',
accent: '#00bfff'
}
};
const colors = colorSchemes[color];
const densitySettings = {
low: { size: 80, nodes: 6 },
medium: { size: 50, nodes: 8 },
high: { size: 30, nodes: 12 }
};
const settings = densitySettings[density];
---
<div class={`circuit-background ${variant} ${color} ${density} ${animated ? 'animated' : ''}`}
style={`--opacity: ${opacity}; --primary: ${colors.primary}; --secondary: ${colors.secondary}; --accent: ${colors.accent};`}>
<!-- Main circuit grid -->
<div class="circuit-grid"></div>
<!-- Connection nodes -->
<div class="circuit-nodes"></div>
<!-- Electronic components -->
<div class="circuit-components">
<div class="component resistor" style="top: 20%; left: 15%;"></div>
<div class="component capacitor" style="top: 35%; left: 60%;"></div>
<div class="component chip" style="top: 70%; left: 25%;"></div>
<div class="component led" style="top: 45%; left: 80%;"></div>
<div class="component transistor" style="top: 80%; left: 70%;"></div>
</div>
<!-- Flowing data lines -->
<div class="data-flow"></div>
</div>
<style define:vars={{ size: `${settings.size}px`, nodeCount: settings.nodes }}>
.circuit-background {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
pointer-events: none;
z-index: 0;
}
/* Circuit Grid Pattern */
.circuit-grid {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
/* Horizontal lines */
linear-gradient(90deg, transparent 49%, var(--primary) 50%, transparent 51%),
/* Vertical lines */
linear-gradient(0deg, transparent 49%, var(--primary) 50%, transparent 51%),
/* Junction dots */
radial-gradient(circle at 50% 50%, var(--secondary) 1px, transparent 2px),
/* Micro traces */
linear-gradient(45deg, transparent 48%, var(--accent) 49%, transparent 50%);
background-size:
var(--size) var(--size),
var(--size) var(--size),
var(--size) var(--size),
calc(var(--size) / 2) calc(var(--size) / 2);
opacity: var(--opacity);
}
/* Animated flowing effect */
.circuit-background.animated .circuit-grid {
animation: circuitFlow 30s linear infinite;
}
@keyframes circuitFlow {
0% {
background-position: 0 0, 0 0, 0 0, 0 0;
}
100% {
background-position:
var(--size) var(--size),
var(--size) var(--size),
var(--size) var(--size),
calc(var(--size) / 2) calc(var(--size) / 2);
}
}
/* Connection Nodes */
.circuit-nodes {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.circuit-nodes::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(circle at 25% 25%, var(--primary) 2px, transparent 3px),
radial-gradient(circle at 75% 25%, var(--secondary) 1.5px, transparent 2.5px),
radial-gradient(circle at 25% 75%, var(--accent) 1.5px, transparent 2.5px),
radial-gradient(circle at 75% 75%, var(--primary) 2px, transparent 3px);
background-size: calc(var(--size) * 2) calc(var(--size) * 2);
opacity: calc(var(--opacity) * 2);
}
/* Electronic Components */
.circuit-components {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.component {
position: absolute;
opacity: calc(var(--opacity) * 3);
transform: translate(-50%, -50%);
}
/* Resistor */
.resistor {
width: 20px;
height: 6px;
background:
linear-gradient(90deg,
transparent 0%,
var(--primary) 20%,
var(--secondary) 40%,
var(--primary) 60%,
var(--secondary) 80%,
transparent 100%);
border-radius: 1px;
}
.resistor::before {
content: '';
position: absolute;
top: 50%;
left: -5px;
right: -5px;
height: 1px;
background: var(--primary);
transform: translateY(-50%);
}
/* Capacitor */
.capacitor {
width: 2px;
height: 12px;
background: var(--secondary);
border-radius: 1px;
}
.capacitor::before {
content: '';
position: absolute;
top: 0;
right: -4px;
width: 2px;
height: 12px;
background: var(--secondary);
border-radius: 1px;
}
/* Microchip */
.chip {
width: 16px;
height: 12px;
background: var(--primary);
border-radius: 2px;
position: relative;
}
.chip::before,
.chip::after {
content: '';
position: absolute;
top: 50%;
width: 3px;
height: 1px;
background: var(--primary);
transform: translateY(-50%);
}
.chip::before {
left: -3px;
}
.chip::after {
right: -3px;
}
/* LED */
.led {
width: 8px;
height: 8px;
border-radius: 50%;
background: radial-gradient(circle, var(--accent), transparent);
box-shadow: 0 0 6px var(--accent);
}
/* Transistor */
.transistor {
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 10px solid var(--secondary);
border-radius: 1px;
}
/* Data Flow Animation */
.data-flow {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
linear-gradient(90deg,
transparent 0%,
var(--primary) 1%,
transparent 2%),
linear-gradient(0deg,
transparent 0%,
var(--secondary) 1%,
transparent 2%);
background-size: 200px 1px, 1px 200px;
opacity: calc(var(--opacity) * 0.5);
}
.circuit-background.animated .data-flow {
animation: dataFlow 8s linear infinite;
}
@keyframes dataFlow {
0% {
background-position: -200px 0, 0 -200px;
}
100% {
background-position: calc(100% + 200px) 0, 0 calc(100% + 200px);
}
}
/* Component animations */
.circuit-background.animated .led {
animation: ledBlink 3s ease-in-out infinite;
}
@keyframes ledBlink {
0%, 80%, 100% {
opacity: calc(var(--opacity) * 3);
box-shadow: 0 0 6px var(--accent);
}
85%, 95% {
opacity: calc(var(--opacity) * 6);
box-shadow: 0 0 12px var(--accent);
}
}
/* Variant Styles */
.circuit-background.prominent {
--opacity: 0.2;
}
.circuit-background.subtle {
--opacity: 0.05;
}
/* Density Variations */
.circuit-background.high .circuit-grid {
background-size: 30px 30px, 30px 30px, 30px 30px, 15px 15px;
}
.circuit-background.low .circuit-grid {
background-size: 80px 80px, 80px 80px, 80px 80px, 40px 40px;
}
/* Multi-color variant */
.circuit-background.multi .circuit-grid {
background-image:
linear-gradient(90deg, transparent 49%, var(--primary) 50%, transparent 51%),
linear-gradient(0deg, transparent 49%, var(--secondary) 50%, transparent 51%),
radial-gradient(circle at 50% 50%, var(--accent) 1px, transparent 2px),
linear-gradient(45deg, transparent 48%, var(--primary) 49%, transparent 50%);
}
/* Responsive adjustments */
@media (max-width: 768px) {
.circuit-background.high {
--size: 40px;
}
.circuit-background.medium {
--size: 60px;
}
.circuit-background.low {
--size: 100px;
}
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
.circuit-grid,
.data-flow,
.led {
animation: none;
}
}
/* High contrast mode */
@media (prefers-contrast: high) {
.circuit-background {
--opacity: 0.3;
}
}
</style>

View File

@ -1,371 +0,0 @@
---
export interface Props {
variant?: 'light' | 'dark' | 'colorful';
density?: 'sparse' | 'medium' | 'dense';
animated?: boolean;
pattern?: 'robots' | 'shapes' | 'mixed' | 'tech';
}
const {
variant = 'light',
density = 'medium',
animated = true,
pattern = 'mixed'
} = Astro.props;
// Generate random positions for doodles
const doodleCount = density === 'sparse' ? 8 : density === 'medium' ? 15 : 25;
const doodles = Array.from({ length: doodleCount }, (_, i) => ({
id: i,
x: Math.random() * 100,
y: Math.random() * 100,
type: ['squiggle', 'dot', 'star', 'heart', 'robot', 'circle', 'triangle', 'zigzag'][Math.floor(Math.random() * 8)],
size: Math.random() * 0.5 + 0.5,
rotation: Math.random() * 360,
delay: Math.random() * 5
}));
---
<div class={`doodle-background ${variant} ${density} ${animated ? 'animated' : ''}`} data-pattern={pattern}>
<svg class="doodle-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="none">
<defs>
<!-- Define reusable doodle shapes -->
<g id="squiggle">
<path d="M0,0 Q5,5 10,0 T20,0" stroke="currentColor" fill="none" stroke-width="0.5" stroke-linecap="round"/>
</g>
<g id="star">
<path d="M5,0 L6,4 L10,4 L7,6 L8,10 L5,7 L2,10 L3,6 L0,4 L4,4 Z" fill="currentColor"/>
</g>
<g id="heart">
<path d="M5,3 C5,1 3,0 2,1 C1,0 0,1 0,2 C0,3 1,5 5,8 C9,5 10,3 10,2 C10,1 9,0 8,1 C7,0 5,1 5,3 Z" fill="currentColor"/>
</g>
<g id="robot-mini">
<rect x="2" y="2" width="6" height="6" rx="1" fill="currentColor"/>
<circle cx="3.5" cy="4" r="0.5" fill="white"/>
<circle cx="6.5" cy="4" r="0.5" fill="white"/>
<path d="M3,6 Q5,7 7,6" stroke="white" fill="none" stroke-width="0.5"/>
</g>
<g id="zigzag">
<path d="M0,5 L5,0 L10,5 L15,0 L20,5" stroke="currentColor" fill="none" stroke-width="0.5" stroke-linecap="round"/>
</g>
<g id="dots">
<circle cx="0" cy="0" r="0.5" fill="currentColor"/>
<circle cx="3" cy="0" r="0.5" fill="currentColor"/>
<circle cx="6" cy="0" r="0.5" fill="currentColor"/>
</g>
<g id="triangle">
<path d="M5,0 L10,8 L0,8 Z" fill="currentColor" opacity="0.3"/>
<path d="M5,0 L10,8 L0,8 Z" stroke="currentColor" fill="none" stroke-width="0.5"/>
</g>
<g id="circle">
<circle cx="5" cy="5" r="4" stroke="currentColor" fill="none" stroke-width="0.5" stroke-dasharray="1,1"/>
</g>
</defs>
{doodles.map(doodle => (
<g
transform={`translate(${doodle.x}, ${doodle.y}) rotate(${doodle.rotation} 5 5) scale(${doodle.size})`}
class={`doodle doodle-${doodle.type}`}
style={`animation-delay: ${doodle.delay}s`}
>
<use href={`#${doodle.type === 'dot' ? 'dots' : doodle.type === 'robot' ? 'robot-mini' : doodle.type}`} />
</g>
))}
</svg>
<!-- Additional hand-drawn elements -->
<div class="doodle-extras">
<div class="floating-annotation">
<span class="annotation-text">AI magic happens here!</span>
<svg class="annotation-arrow" width="50" height="30">
<path d="M5,25 Q25,5 45,15" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" marker-end="url(#arrowhead)"/>
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="currentColor"/>
</marker>
</defs>
</svg>
</div>
<div class="corner-doodle top-left">
<svg width="100" height="100" viewBox="0 0 100 100">
<path d="M10,10 Q50,20 40,60 T20,90" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<circle cx="20" cy="20" r="3" fill="currentColor" opacity="0.5"/>
<circle cx="35" cy="40" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="25" cy="70" r="4" fill="currentColor" opacity="0.5"/>
</svg>
</div>
<div class="corner-doodle bottom-right">
<svg width="120" height="120" viewBox="0 0 120 120">
<g transform="rotate(180 60 60)">
<path d="M20,20 L30,10 L40,20 L50,10 L60,20" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<rect x="25" y="30" width="10" height="10" rx="2" stroke="currentColor" fill="none" opacity="0.5"/>
<rect x="45" y="35" width="8" height="8" rx="1" stroke="currentColor" fill="none" opacity="0.5"/>
</g>
</svg>
</div>
</div>
</div>
<style>
.doodle-background {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
pointer-events: none;
z-index: 0;
}
.doodle-svg {
position: absolute;
width: 100%;
height: 100%;
opacity: 0.5;
}
/* Color variants */
.doodle-background.light .doodle {
color: var(--medium-gray);
}
.doodle-background.dark .doodle {
color: rgba(255, 255, 255, 0.3);
}
.doodle-background.colorful .doodle:nth-child(4n) {
color: var(--robot-pink);
}
.doodle-background.colorful .doodle:nth-child(4n + 1) {
color: var(--robot-blue);
}
.doodle-background.colorful .doodle:nth-child(4n + 2) {
color: var(--robot-green);
}
.doodle-background.colorful .doodle:nth-child(4n + 3) {
color: var(--robot-yellow);
}
/* Animations */
.doodle-background.animated .doodle {
animation: doodleFloat 20s ease-in-out infinite;
}
.doodle-background.animated .doodle-squiggle {
animation: squiggleWave 15s ease-in-out infinite;
}
.doodle-background.animated .doodle-star {
animation: starTwinkle 10s ease-in-out infinite;
}
.doodle-background.animated .doodle-heart {
animation: heartPulse 8s ease-in-out infinite;
}
.doodle-background.animated .doodle-robot {
animation: robotDance 12s ease-in-out infinite;
}
@keyframes doodleFloat {
0%, 100% {
transform: translate(0, 0) rotate(0deg);
}
33% {
transform: translate(5px, -10px) rotate(5deg);
}
66% {
transform: translate(-5px, 5px) rotate(-5deg);
}
}
@keyframes squiggleWave {
0%, 100% {
transform: scaleX(1) scaleY(1);
}
50% {
transform: scaleX(1.1) scaleY(0.9);
}
}
@keyframes starTwinkle {
0%, 100% {
opacity: 0.5;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.2);
}
}
@keyframes heartPulse {
0%, 100% {
transform: scale(1);
}
25%, 75% {
transform: scale(1.1);
}
50% {
transform: scale(0.9);
}
}
@keyframes robotDance {
0%, 100% {
transform: rotate(0deg);
}
25% {
transform: rotate(-10deg) translateY(-2px);
}
75% {
transform: rotate(10deg) translateY(-2px);
}
}
/* Extra decorative elements */
.doodle-extras {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
}
.floating-annotation {
position: absolute;
top: 15%;
right: 10%;
color: var(--robot-pink);
font-family: 'Caveat', 'Comic Sans MS', cursive;
font-size: 1.2rem;
transform: rotate(-5deg);
opacity: 0;
animation: annotationAppear 15s ease-in-out infinite;
}
.annotation-arrow {
position: absolute;
bottom: -20px;
left: 50%;
transform: translateX(-50%);
}
@keyframes annotationAppear {
0%, 70%, 100% {
opacity: 0;
transform: rotate(-5deg) scale(0.8);
}
80%, 90% {
opacity: 1;
transform: rotate(-5deg) scale(1);
}
}
.corner-doodle {
position: absolute;
opacity: 0.3;
}
.corner-doodle.top-left {
top: 20px;
left: 20px;
}
.corner-doodle.bottom-right {
bottom: 20px;
right: 20px;
}
/* Pattern-specific styles */
.doodle-background[data-pattern="robots"] .doodle:not(.doodle-robot) {
display: none;
}
.doodle-background[data-pattern="shapes"] .doodle-robot {
display: none;
}
.doodle-background[data-pattern="tech"] .doodle-heart,
.doodle-background[data-pattern="tech"] .doodle-star {
display: none;
}
/* Density adjustments */
.doodle-background.sparse .doodle-svg {
opacity: 0.3;
}
.doodle-background.dense .doodle-svg {
opacity: 0.7;
}
/* Responsive */
@media (max-width: 768px) {
.floating-annotation {
font-size: 1rem;
top: 10%;
right: 5%;
}
.corner-doodle {
transform: scale(0.7);
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.doodle-background.animated .doodle,
.floating-annotation {
animation: none !important;
}
}
/* Dark mode adjustments */
@media (prefers-color-scheme: dark) {
.doodle-background.light .doodle {
color: rgba(255, 255, 255, 0.2);
}
}
</style>
<script>
// Add interactive easter eggs
document.addEventListener('DOMContentLoaded', () => {
const doodleBackground = document.querySelector('.doodle-background');
if (doodleBackground) {
// Random annotation messages
const annotations = [
"AI magic happens here!",
"Robots working hard!",
"← This is where the fun begins",
"100% locally powered!",
"No clouds were harmed",
"Beep boop beep! 🤖"
];
const annotationText = doodleBackground.querySelector('.annotation-text');
if (annotationText) {
setInterval(() => {
const randomMessage = annotations[Math.floor(Math.random() * annotations.length)];
annotationText.textContent = randomMessage;
}, 15000);
}
}
});
</script>

View File

@ -1,735 +0,0 @@
---
export interface Props {
sections?: Array<{
id: string;
label: string;
icon: string;
status?: 'active' | 'inactive' | 'processing';
}>;
position?: 'left' | 'right';
theme?: 'dark' | 'matrix' | 'circuit';
compact?: boolean;
}
const {
sections = [
{ id: 'models', label: 'Models', icon: '🧠', status: 'active' },
{ id: 'platforms', label: 'Platforms', icon: '💻', status: 'active' },
{ id: 'tools', label: 'Tools', icon: '🔧', status: 'processing' }
],
position = 'right',
theme = 'matrix',
compact = false
} = Astro.props;
const navId = `floating-nav-${Math.random().toString(36).substr(2, 9)}`;
---
<div id={navId} class={`floating-nav ${position} ${theme} ${compact ? 'compact' : ''}`}>
<!-- Main Navigation Button -->
<button class="nav-toggle" aria-label="Toggle Navigation">
<div class="nav-icon">
<span class="icon-line"></span>
<span class="icon-line"></span>
<span class="icon-line"></span>
</div>
<div class="status-ring"></div>
</button>
<!-- Navigation Menu -->
<nav class="nav-menu" role="navigation" aria-label="Section Navigation">
<div class="nav-header">
<div class="terminal-prompt">
<span class="prompt-symbol">></span>
<span class="prompt-text">NAVIGATE</span>
<span class="terminal-cursor"></span>
</div>
<div class="system-status">
<div class="status-indicator online"></div>
<span class="status-text">ONLINE</span>
</div>
</div>
<ul class="nav-list">
{sections.map((section, index) => (
<li class="nav-item">
<a href={`#${section.id}`} class="nav-link" data-section={section.id}>
<div class="nav-icon-wrapper">
<span class="nav-emoji">{section.icon}</span>
<div class="connection-line"></div>
</div>
<div class="nav-content">
<span class="nav-label">{section.label}</span>
<div class="nav-circuit">
<div class="circuit-dot"></div>
<div class="circuit-line"></div>
</div>
</div>
<div class={`nav-status ${section.status || 'inactive'}`}>
<div class="status-dot"></div>
<span class="status-code">
{section.status === 'active' ? '200' :
section.status === 'processing' ? '102' : '404'}
</span>
</div>
</a>
</li>
))}
</ul>
<div class="nav-footer">
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
<div class="system-info">
<span class="timestamp"></span>
<span class="version">v2.4.1</span>
</div>
</div>
</nav>
<!-- Background Circuit Pattern -->
<div class="nav-background">
<div class="circuit-pattern"></div>
<div class="data-stream"></div>
</div>
</div>
<style>
.floating-nav {
position: fixed;
top: 50%;
transform: translateY(-50%);
z-index: 1000;
font-family: 'JetBrains Mono', 'Monaco', 'Menlo', monospace;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.floating-nav.right {
right: 20px;
}
.floating-nav.left {
left: 20px;
}
/* Main Toggle Button */
.nav-toggle {
width: 60px;
height: 60px;
border-radius: 50%;
background:
radial-gradient(circle at 30% 30%, rgba(0, 255, 65, 0.1), transparent),
linear-gradient(135deg, #1a1a1a, #0a0a0a);
border: 2px solid #00ff41;
cursor: pointer;
position: relative;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
box-shadow:
0 4px 20px rgba(0, 0, 0, 0.3),
0 0 20px rgba(0, 255, 65, 0.2);
}
.nav-toggle:hover {
transform: scale(1.1);
box-shadow:
0 6px 30px rgba(0, 0, 0, 0.4),
0 0 30px rgba(0, 255, 65, 0.4);
border-color: #00ff65;
}
.nav-icon {
display: flex;
flex-direction: column;
gap: 4px;
transition: all 0.3s ease;
}
.icon-line {
width: 20px;
height: 2px;
background: #00ff41;
border-radius: 1px;
transition: all 0.3s ease;
box-shadow: 0 0 5px rgba(0, 255, 65, 0.5);
}
.floating-nav.active .icon-line:nth-child(1) {
transform: rotate(45deg) translate(6px, 6px);
}
.floating-nav.active .icon-line:nth-child(2) {
opacity: 0;
transform: translateX(20px);
}
.floating-nav.active .icon-line:nth-child(3) {
transform: rotate(-45deg) translate(6px, -6px);
}
.status-ring {
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border: 1px solid transparent;
border-radius: 50%;
background:
linear-gradient(45deg, #00ff41, transparent, #ffb000, transparent, #00ff41)
border-box;
mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
animation: statusRotate 4s linear infinite;
}
@keyframes statusRotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Navigation Menu */
.nav-menu {
position: absolute;
right: 80px;
top: 50%;
transform: translateY(-50%);
background:
linear-gradient(135deg, rgba(26, 26, 26, 0.95), rgba(10, 10, 10, 0.98));
border: 1px solid #00ff41;
border-radius: 8px;
min-width: 280px;
backdrop-filter: blur(10px);
opacity: 0;
visibility: hidden;
transform: translateY(-50%) translateX(20px) scale(0.95);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow:
0 10px 40px rgba(0, 0, 0, 0.5),
0 0 20px rgba(0, 255, 65, 0.1);
}
.floating-nav.left .nav-menu {
right: auto;
left: 80px;
transform: translateY(-50%) translateX(-20px) scale(0.95);
}
.floating-nav.active .nav-menu {
opacity: 1;
visibility: visible;
transform: translateY(-50%) translateX(0) scale(1);
}
/* Menu Header */
.nav-header {
padding: 1rem;
border-bottom: 1px solid rgba(0, 255, 65, 0.2);
display: flex;
justify-content: space-between;
align-items: center;
}
.terminal-prompt {
display: flex;
align-items: center;
gap: 0.5rem;
color: #00ff41;
font-size: 0.8rem;
font-weight: 600;
}
.prompt-symbol {
color: #ffb000;
}
.terminal-cursor {
width: 8px;
height: 12px;
background: #ffffff;
animation: cursorBlink 1s infinite;
}
@keyframes cursorBlink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
.system-status {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.7rem;
color: #888888;
}
.status-indicator {
width: 6px;
height: 6px;
border-radius: 50%;
background: #00ff41;
box-shadow: 0 0 8px #00ff41;
animation: statusPulse 2s infinite;
}
@keyframes statusPulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
/* Navigation List */
.nav-list {
list-style: none;
margin: 0;
padding: 0.5rem 0;
}
.nav-item {
margin: 0;
}
.nav-link {
display: flex;
align-items: center;
padding: 0.75rem 1rem;
color: #cccccc;
text-decoration: none;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.nav-link::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(0, 255, 65, 0.1),
transparent
);
transition: left 0.5s ease;
}
.nav-link:hover::before {
left: 100%;
}
.nav-link:hover {
color: #00ff41;
background: rgba(0, 255, 65, 0.05);
transform: translateX(5px);
}
.nav-icon-wrapper {
display: flex;
align-items: center;
margin-right: 1rem;
position: relative;
}
.nav-emoji {
font-size: 1.2rem;
display: block;
filter: grayscale(0.3);
transition: all 0.3s ease;
}
.nav-link:hover .nav-emoji {
filter: grayscale(0);
transform: scale(1.1);
}
.connection-line {
position: absolute;
right: -8px;
top: 50%;
width: 16px;
height: 1px;
background: #333333;
transform: translateY(-50%);
transition: all 0.3s ease;
}
.nav-link:hover .connection-line {
background: #00ff41;
box-shadow: 0 0 5px #00ff41;
}
.nav-content {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
}
.nav-label {
font-size: 0.9rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.nav-circuit {
display: flex;
align-items: center;
gap: 4px;
}
.circuit-dot {
width: 4px;
height: 4px;
border-radius: 50%;
background: #666666;
transition: all 0.3s ease;
}
.nav-link:hover .circuit-dot {
background: #00ff41;
box-shadow: 0 0 8px #00ff41;
}
.circuit-line {
width: 12px;
height: 1px;
background: #333333;
transition: all 0.3s ease;
}
.nav-link:hover .circuit-line {
background: #00ff41;
box-shadow: 0 0 5px #00ff41;
}
.nav-status {
display: flex;
align-items: center;
gap: 0.25rem;
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
margin-left: 0.5rem;
}
.nav-status .status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.nav-status.active .status-dot {
background: #00ff41;
box-shadow: 0 0 6px #00ff41;
}
.nav-status.processing .status-dot {
background: #ffb000;
box-shadow: 0 0 6px #ffb000;
animation: processingPulse 1s infinite;
}
.nav-status.inactive .status-dot {
background: #666666;
}
@keyframes processingPulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.7; transform: scale(1.2); }
}
.status-code {
color: #888888;
font-size: 0.6rem;
}
.nav-status.active .status-code {
color: #00ff41;
}
.nav-status.processing .status-code {
color: #ffb000;
}
/* Menu Footer */
.nav-footer {
padding: 0.75rem 1rem;
border-top: 1px solid rgba(0, 255, 65, 0.2);
}
.progress-bar {
width: 100%;
height: 3px;
background: #333333;
border-radius: 2px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #00ff41, #ffb000);
border-radius: 2px;
animation: progressFlow 3s ease-in-out infinite;
}
@keyframes progressFlow {
0% { width: 0%; }
50% { width: 100%; }
100% { width: 0%; }
}
.system-info {
display: flex;
justify-content: space-between;
font-size: 0.7rem;
color: #666666;
}
/* Background Effects */
.nav-background {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
overflow: hidden;
border-radius: 8px;
}
.circuit-pattern {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
linear-gradient(90deg, transparent 49%, rgba(0, 255, 65, 0.05) 50%, transparent 51%),
linear-gradient(0deg, transparent 49%, rgba(0, 255, 65, 0.05) 50%, transparent 51%);
background-size: 20px 20px;
opacity: 0.3;
}
.data-stream {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
45deg,
transparent 30%,
rgba(0, 255, 65, 0.02) 50%,
transparent 70%
);
animation: dataStreamFlow 4s linear infinite;
}
@keyframes dataStreamFlow {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* Theme Variations */
.floating-nav.matrix .nav-toggle {
border-color: #00ff41;
box-shadow:
0 4px 20px rgba(0, 0, 0, 0.3),
0 0 20px rgba(0, 255, 65, 0.3);
}
.floating-nav.circuit .nav-toggle {
border-color: #ffb000;
box-shadow:
0 4px 20px rgba(0, 0, 0, 0.3),
0 0 20px rgba(255, 176, 0, 0.3);
}
.floating-nav.circuit .nav-menu {
border-color: #ffb000;
}
/* Compact Mode */
.floating-nav.compact .nav-toggle {
width: 50px;
height: 50px;
}
.floating-nav.compact .nav-menu {
min-width: 240px;
}
/* Responsive Design */
@media (max-width: 768px) {
.floating-nav {
right: 10px;
}
.floating-nav.left {
left: 10px;
}
.nav-menu {
min-width: 260px;
right: 60px;
}
.floating-nav.left .nav-menu {
left: 60px;
}
.nav-toggle {
width: 50px;
height: 50px;
}
}
@media (max-width: 480px) {
.nav-menu {
min-width: 240px;
font-size: 0.85rem;
}
.nav-link {
padding: 0.6rem 0.8rem;
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.floating-nav *,
.floating-nav *::before,
.floating-nav *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
.nav-toggle:focus,
.nav-link:focus {
outline: 2px solid #00ff41;
outline-offset: 2px;
}
/* High contrast mode */
@media (prefers-contrast: high) {
.floating-nav {
filter: contrast(1.5);
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
const navs = document.querySelectorAll('.floating-nav');
navs.forEach(nav => {
const toggle = nav.querySelector('.nav-toggle');
const menu = nav.querySelector('.nav-menu');
const links = nav.querySelectorAll('.nav-link');
const timestamp = nav.querySelector('.timestamp');
// Update timestamp
if (timestamp) {
const updateTime = () => {
const now = new Date();
timestamp.textContent = now.toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit'
});
};
updateTime();
setInterval(updateTime, 1000);
}
// Toggle menu
toggle?.addEventListener('click', () => {
nav.classList.toggle('active');
});
// Close menu when clicking outside
document.addEventListener('click', (e) => {
if (!nav.contains(e.target)) {
nav.classList.remove('active');
}
});
// Handle navigation
links.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const sectionId = link.getAttribute('data-section');
const targetSection = document.getElementById(sectionId);
if (targetSection) {
// Smooth scroll with GSAP if available
if (typeof gsap !== 'undefined') {
gsap.to(window, {
duration: 1.2,
scrollTo: { y: targetSection, offsetY: 100 },
ease: 'power3.inOut'
});
} else {
targetSection.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
// Close menu after navigation
nav.classList.remove('active');
// Add ripple effect
const rect = link.getBoundingClientRect();
const ripple = document.createElement('div');
ripple.style.cssText = `
position: absolute;
border-radius: 50%;
background: rgba(0, 255, 65, 0.3);
transform: scale(0);
animation: ripple 0.6s linear;
left: ${e.clientX - rect.left - 10}px;
top: ${e.clientY - rect.top - 10}px;
width: 20px;
height: 20px;
pointer-events: none;
z-index: 10;
`;
link.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
}
});
});
// Keyboard navigation
nav.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
nav.classList.remove('active');
toggle?.focus();
}
});
});
// Add ripple animation styles
const style = document.createElement('style');
style.textContent = `
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
`;
document.head.appendChild(style);
});
</script>

View File

@ -0,0 +1,671 @@
---
export interface Props {
className?: string;
}
const { className = '' } = Astro.props;
---
<div class={`release-database ${className}`}>
<table class="newspaper-table">
<caption>Release Database</caption>
<thead>
<tr>
<th>Release Version</th>
<th>Target Date</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<!-- v0.6.7 - Released -->
<tr class="release-row" data-version="v0.6.7">
<td class="version-cell">
<strong>v0.6.7</strong>
<span class="version-name">Web Search</span>
</td>
<td>Released</td>
<td><span class="status released">Live</span></td>
</tr>
<tr class="release-details" data-for="v0.6.7">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>User Stories</h5>
<ul>
<li>As a user, I want to search the web directly from Jan chat for real-time information</li>
<li>As a developer, I want better API documentation for integration</li>
<li>As a researcher, I want source attribution for all search results</li>
</ul>
</div>
<div class="detail-section">
<h5>New Features</h5>
<ul>
<li>Privacy-respecting web search integration</li>
<li>Multiple search engine support</li>
<li>Improved model downloading experience</li>
<li>Enhanced error handling and user feedback</li>
</ul>
</div>
<div class="detail-section">
<h5>Documentation</h5>
<ul>
<li>Web Search API documentation</li>
<li>Privacy policy updates</li>
<li>Search configuration guide</li>
</ul>
</div>
</div>
</td>
</tr>
<!-- v0.6.5 - Released -->
<tr class="release-row" data-version="v0.6.5">
<td class="version-cell">
<strong>v0.6.5</strong>
<span class="version-name">Desktop Stability</span>
</td>
<td>Released</td>
<td><span class="status released">Live</span></td>
</tr>
<tr class="release-details" data-for="v0.6.5">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>Improvements</h5>
<ul>
<li>Enhanced memory management for large models</li>
<li>Improved GPU utilization</li>
<li>Better cross-platform compatibility</li>
</ul>
</div>
<div class="detail-section">
<h5>Bug Fixes</h5>
<ul>
<li>Fixed model loading crashes on Windows</li>
<li>Resolved memory leaks in long conversations</li>
<li>Fixed UI freezing during model downloads</li>
</ul>
</div>
<div class="detail-section">
<h5>Performance</h5>
<ul>
<li>30% faster model loading times</li>
<li>Reduced memory footprint by 25%</li>
<li>Improved response streaming</li>
</ul>
</div>
</div>
</td>
</tr>
<!-- v0.7.0 - In Development -->
<tr class="release-row" data-version="v0.7.0">
<td class="version-cell">
<strong>v0.7.0</strong>
<span class="version-name">Deep Research</span>
</td>
<td>January 2025</td>
<td><span class="status development">Building</span></td>
</tr>
<tr class="release-details" data-for="v0.7.0">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>User Stories</h5>
<ul>
<li>As a researcher, I want to conduct deep research with multiple sources and citations</li>
<li>As a user, I want Jan Nano to work seamlessly on mobile devices</li>
<li>As a team lead, I want to preview jan.ai for my organization</li>
</ul>
</div>
<div class="detail-section">
<h5>New Features</h5>
<ul>
<li>Deep research capabilities with multi-source analysis</li>
<li>jan.ai web platform beta launch</li>
<li>Improved Jan Nano performance and mobile optimization</li>
<li>Citation management and research reports</li>
</ul>
</div>
<div class="detail-section">
<h5>Documentation</h5>
<ul>
<li>Research methodology guide</li>
<li>jan.ai platform documentation</li>
<li>Mobile optimization best practices</li>
</ul>
</div>
</div>
</td>
</tr>
<!-- v0.8.0 - In Development -->
<tr class="release-row" data-version="v0.8.0">
<td class="version-cell">
<strong>v0.8.0</strong>
<span class="version-name">Browser Automation</span>
</td>
<td>March 2025</td>
<td><span class="status development">Building</span></td>
</tr>
<tr class="release-details" data-for="v0.8.0">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>User Stories</h5>
<ul>
<li>As a user, I want Jan to automate web tasks for me safely and efficiently</li>
<li>As a business user, I want to automate repetitive web workflows</li>
<li>As a developer, I want browser automation APIs for custom integrations</li>
</ul>
</div>
<div class="detail-section">
<h5>New Features</h5>
<ul>
<li>Browser automation capabilities (Beta)</li>
<li>Form filling and data extraction</li>
<li>Website navigation and interaction</li>
<li>Safety policies and user confirmation flows</li>
</ul>
</div>
<div class="detail-section">
<h5>Documentation</h5>
<ul>
<li>Browser automation safety guide</li>
<li>Web scraping best practices</li>
<li>API reference for automation tools</li>
</ul>
</div>
</div>
</td>
</tr>
<!-- v0.9.0 - Planned -->
<tr class="release-row" data-version="v0.9.0">
<td class="version-cell">
<strong>v0.9.0</strong>
<span class="version-name">Mobile Launch</span>
</td>
<td>Q1 2025</td>
<td><span class="status planned">Planned</span></td>
</tr>
<tr class="release-details" data-for="v0.9.0">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>User Stories</h5>
<ul>
<li>As a mobile user, I want Jan AI available on my iOS/Android device</li>
<li>As a commuter, I want to seamlessly switch between desktop and mobile</li>
<li>As a privacy-conscious user, I want local AI on my phone</li>
</ul>
</div>
<div class="detail-section">
<h5>New Features</h5>
<ul>
<li>iOS and Android mobile applications</li>
<li>Three adaptive modes (Desktop, Server, Local)</li>
<li>Voice-first interface</li>
<li>Cross-device synchronization</li>
<li>Jan Nano on-device processing</li>
</ul>
</div>
<div class="detail-section">
<h5>Documentation</h5>
<ul>
<li>Mobile setup and configuration guide</li>
<li>Voice interaction best practices</li>
<li>Device syncing tutorial</li>
</ul>
</div>
</div>
</td>
</tr>
<!-- v1.0.0 - Planned -->
<tr class="release-row" data-version="v1.0.0">
<td class="version-cell">
<strong>v1.0.0</strong>
<span class="version-name">Server Edition</span>
</td>
<td>Q2 2025</td>
<td><span class="status planned">Planned</span></td>
</tr>
<tr class="release-details" data-for="v1.0.0">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>User Stories</h5>
<ul>
<li>As an IT admin, I want to deploy Jan for my entire organization</li>
<li>As a team lead, I want centralized AI with team collaboration features</li>
<li>As a CTO, I want enterprise-grade security and compliance</li>
</ul>
</div>
<div class="detail-section">
<h5>New Features</h5>
<ul>
<li>Multi-user server deployment</li>
<li>Enterprise authentication (SSO, LDAP)</li>
<li>Team collaboration and shared conversations</li>
<li>Docker and Kubernetes deployment options</li>
<li>Admin dashboard and user management</li>
</ul>
</div>
<div class="detail-section">
<h5>Documentation</h5>
<ul>
<li>Enterprise deployment guide</li>
<li>Security and compliance documentation</li>
<li>Admin management tutorials</li>
</ul>
</div>
</div>
</td>
</tr>
<!-- v1.1.0 - Planned -->
<tr class="release-row" data-version="v1.1.0">
<td class="version-cell">
<strong>v1.1.0</strong>
<span class="version-name">AI Agents</span>
</td>
<td>Q1 2026</td>
<td><span class="status planned">Planned</span></td>
</tr>
<tr class="release-details" data-for="v1.1.0">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>User Stories</h5>
<ul>
<li>As a user, I want autonomous agents to handle complex multi-step tasks</li>
<li>As a business owner, I want AI that can coordinate multiple tools automatically</li>
<li>As a power user, I want to create custom agent workflows</li>
</ul>
</div>
<div class="detail-section">
<h5>New Features</h5>
<ul>
<li>Autonomous AI agents</li>
<li>Multi-step task planning and execution</li>
<li>Tool orchestration and coordination</li>
<li>Goal-oriented intelligent reasoning</li>
<li>Custom agent workflow builder</li>
</ul>
</div>
<div class="detail-section">
<h5>Documentation</h5>
<ul>
<li>Agent development guide</li>
<li>Workflow automation tutorials</li>
<li>Safety and oversight best practices</li>
</ul>
</div>
</div>
</td>
</tr>
<!-- v1.2.0 - Planned -->
<tr class="release-row" data-version="v1.2.0">
<td class="version-cell">
<strong>v1.2.0</strong>
<span class="version-name">Lucy Multimodal</span>
</td>
<td>Q2 2025</td>
<td><span class="status planned">Planned</span></td>
</tr>
<tr class="release-details" data-for="v1.2.0">
<td colspan="3">
<div class="details-grid">
<div class="detail-section">
<h5>User Stories</h5>
<ul>
<li>As a content creator, I want AI that can understand and process images</li>
<li>As a researcher, I want to analyze documents with both text and visuals</li>
<li>As a designer, I want AI that can help with visual content creation</li>
</ul>
</div>
<div class="detail-section">
<h5>New Features</h5>
<ul>
<li>Lucy multimodal model release</li>
<li>Image understanding and analysis</li>
<li>Document processing with OCR</li>
<li>Visual reasoning capabilities</li>
<li>Audio processing (planned)</li>
</ul>
</div>
<div class="detail-section">
<h5>Documentation</h5>
<ul>
<li>Multimodal AI usage guide</li>
<li>Image processing tutorials</li>
<li>Visual reasoning examples</li>
</ul>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<style>
.release-database {
margin: 3rem 0;
}
/* Newspaper-style table */
.newspaper-table {
width: 100%;
border-collapse: collapse;
font-size: 0.9rem;
font-family: Georgia, 'Times New Roman', serif;
margin: 2rem 0;
}
.newspaper-table caption {
font-size: 1.4rem;
font-weight: 700;
margin-bottom: 1rem;
text-align: left;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.newspaper-table th,
.newspaper-table td {
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid #000;
}
.newspaper-table th {
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
background: #f0f0f0;
border-top: 3px double #000;
border-bottom: 1px solid #000;
font-size: 0.8rem;
}
.newspaper-table tbody tr:last-child td {
border-bottom: 3px double #000;
}
/* Clickable rows */
.release-row {
cursor: pointer;
transition: background-color 0.2s ease;
}
.release-row:hover {
background: #f8f8f8;
}
.release-row.expanded {
background: #f0f0f0;
font-weight: 600;
}
/* Version cell styling */
.version-cell {
display: flex;
align-items: baseline;
gap: 0.5rem;
}
.version-name {
font-size: 0.85rem;
color: #333;
font-weight: normal;
}
/* Status badges */
.status {
display: inline-block;
padding: 0.2rem 0.5rem;
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.status.released {
background: #000;
color: #fff;
}
.status.development {
background: #666;
color: #fff;
}
.status.planned {
background: #fff;
color: #000;
border: 1px solid #000;
}
/* Details rows */
.release-details {
display: none;
background: #fafafa;
}
.release-details.expanded {
display: table-row;
}
.release-details td {
padding: 0;
border-bottom: 1px solid #000;
}
.details-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border-collapse: collapse;
}
.detail-section {
padding: 1rem;
border-right: 1px solid #ccc;
}
.detail-section:last-child {
border-right: none;
}
.detail-section h5 {
font-size: 0.85rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
margin: 0 0 0.75rem 0;
color: #000;
}
.detail-section ul {
list-style: none;
margin: 0;
padding: 0;
}
.detail-section li {
margin-bottom: 0.5rem;
padding-left: 1rem;
position: relative;
font-size: 0.85rem;
line-height: 1.4;
color: #333;
}
.detail-section li::before {
content: '•';
position: absolute;
left: 0;
color: #666;
}
/* Responsive */
@media (max-width: 768px) {
.newspaper-table {
font-size: 0.8rem;
}
.newspaper-table th,
.newspaper-table td {
padding: 0.5rem;
}
.version-cell {
flex-direction: column;
gap: 0.25rem;
}
.details-grid {
grid-template-columns: 1fr;
}
.detail-section {
border-right: none;
border-bottom: 1px solid #ccc;
}
.detail-section:last-child {
border-bottom: none;
}
}
/* Print styles */
@media print {
.release-row {
page-break-inside: avoid;
}
.release-details {
display: table-row !important;
}
}
/* Dark mode styles */
html[data-theme="dark"] .newspaper-table {
background: #1a1a1a;
color: #fff;
}
html[data-theme="dark"] .newspaper-table caption {
color: #fff;
}
html[data-theme="dark"] .newspaper-table th {
background: #2a2a2a;
border-color: #666;
color: #fff;
}
html[data-theme="dark"] .newspaper-table td {
border-color: #666;
color: #ccc;
}
html[data-theme="dark"] .newspaper-table tbody tr:last-child td {
border-bottom-color: #666;
}
html[data-theme="dark"] .release-row:hover {
background: #2a2a2a;
}
html[data-theme="dark"] .release-row.expanded {
background: #333;
}
html[data-theme="dark"] .version-name {
color: #999;
}
/* Dark mode status badges */
html[data-theme="dark"] .status.released {
background: #fff;
color: #000;
}
html[data-theme="dark"] .status.development {
background: #999;
color: #000;
}
html[data-theme="dark"] .status.planned {
background: transparent;
color: #fff;
border-color: #fff;
}
/* Dark mode details */
html[data-theme="dark"] .release-details {
background: #252525;
}
html[data-theme="dark"] .release-details td {
border-color: #666;
}
html[data-theme="dark"] .detail-section {
border-right-color: #444;
}
html[data-theme="dark"] .detail-section h5 {
color: #fff;
}
html[data-theme="dark"] .detail-section li {
color: #ccc;
}
html[data-theme="dark"] .detail-section li::before {
color: #999;
}
@media (max-width: 768px) {
html[data-theme="dark"] .detail-section {
border-bottom-color: #444;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
const releaseRows = document.querySelectorAll('.release-row');
releaseRows.forEach(row => {
row.addEventListener('click', () => {
const version = row.getAttribute('data-version');
const detailsRow = document.querySelector(`.release-details[data-for="${version}"]`);
if (detailsRow) {
// Toggle expanded state
const isExpanded = detailsRow.classList.contains('expanded');
// Close all other rows
document.querySelectorAll('.release-details').forEach(details => {
details.classList.remove('expanded');
});
document.querySelectorAll('.release-row').forEach(r => {
r.classList.remove('expanded');
});
// Toggle this row
if (!isExpanded) {
detailsRow.classList.add('expanded');
row.classList.add('expanded');
}
}
});
});
});
</script>

View File

@ -1,601 +0,0 @@
---
export interface Props {
variant?: 'terminal' | 'circuit' | 'data' | 'system';
color?: 'green' | 'amber' | 'blue' | 'red' | 'multi';
size?: 'small' | 'medium' | 'large';
glitch?: boolean;
scanlines?: boolean;
glow?: boolean;
interactive?: boolean;
status?: 'online' | 'offline' | 'error' | 'warning' | 'processing';
title?: string;
subtitle?: string;
className?: string;
}
const {
variant = 'terminal',
color = 'green',
size = 'medium',
glitch = false,
scanlines = true,
glow = true,
interactive = true,
status = 'online',
title,
subtitle,
className = ''
} = Astro.props;
const colorSchemes = {
green: {
primary: '#00ff41',
secondary: '#00cc33',
bg: 'rgba(0, 255, 65, 0.05)',
border: '#00ff41',
glow: 'rgba(0, 255, 65, 0.3)'
},
amber: {
primary: '#ffb000',
secondary: '#ff9500',
bg: 'rgba(255, 176, 0, 0.05)',
border: '#ffb000',
glow: 'rgba(255, 176, 0, 0.3)'
},
blue: {
primary: '#00bfff',
secondary: '#0099cc',
bg: 'rgba(0, 191, 255, 0.05)',
border: '#00bfff',
glow: 'rgba(0, 191, 255, 0.3)'
},
red: {
primary: '#ff0040',
secondary: '#cc0033',
bg: 'rgba(255, 0, 64, 0.05)',
border: '#ff0040',
glow: 'rgba(255, 0, 64, 0.3)'
},
multi: {
primary: '#00ff41',
secondary: '#ffb000',
bg: 'linear-gradient(135deg, rgba(0, 255, 65, 0.05), rgba(255, 176, 0, 0.05))',
border: '#00ff41',
glow: 'rgba(0, 255, 65, 0.3)'
}
};
const scheme = colorSchemes[color];
const cardId = `retro-card-${Math.random().toString(36).substr(2, 9)}`;
---
<div
id={cardId}
class={`retro-card ${variant} ${color} ${size} ${glitch ? 'glitch' : ''} ${scanlines ? 'scanlines' : ''} ${glow ? 'glow' : ''} ${interactive ? 'interactive' : ''} ${className}`}
data-status={status}
style={`--primary: ${scheme.primary}; --secondary: ${scheme.secondary}; --bg: ${scheme.bg}; --border: ${scheme.border}; --glow: ${scheme.glow};`}
>
<!-- Terminal header -->
<div class="retro-header">
<div class="terminal-controls">
<div class="control-dot red"></div>
<div class="control-dot yellow"></div>
<div class="control-dot green"></div>
</div>
{title && (
<div class="terminal-title">
<span class="title-text">{title}</span>
{subtitle && <span class="subtitle-text">{subtitle}</span>}
</div>
)}
<div class="status-indicator">
<div class={`status-dot ${status}`}></div>
<span class="status-text">{status.toUpperCase()}</span>
</div>
</div>
<!-- Content area -->
<div class="retro-content">
<slot />
</div>
<!-- Scanline overlay -->
{scanlines && (
<div class="scanline-overlay"></div>
)}
<!-- Border effects -->
<div class="border-glow"></div>
<!-- Corner brackets -->
<div class="corner-bracket top-left"></div>
<div class="corner-bracket top-right"></div>
<div class="corner-bracket bottom-left"></div>
<div class="corner-bracket bottom-right"></div>
</div>
<style>
.retro-card {
position: relative;
background: #111111;
border: 1px solid var(--border);
border-radius: 4px;
font-family: 'JetBrains Mono', 'Monaco', 'Menlo', monospace;
color: #ffffff;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Size variations */
.retro-card.small {
min-height: 200px;
font-size: 0.85rem;
}
.retro-card.medium {
min-height: 280px;
font-size: 0.9rem;
}
.retro-card.large {
min-height: 400px;
font-size: 1rem;
}
/* Interactive states */
.retro-card.interactive {
cursor: pointer;
}
.retro-card.interactive:hover {
transform: translateY(-2px) scale(1.02);
border-color: var(--primary);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.4),
0 0 20px var(--glow);
}
.retro-card.interactive:active {
transform: translateY(0) scale(1.01);
}
/* Terminal header */
.retro-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
background: rgba(0, 0, 0, 0.3);
border-bottom: 1px solid var(--border);
min-height: 40px;
}
.terminal-controls {
display: flex;
gap: 0.5rem;
}
.control-dot {
width: 12px;
height: 12px;
border-radius: 50%;
position: relative;
}
.control-dot.red {
background: #ff5f56;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.control-dot.yellow {
background: #ffbd2e;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.control-dot.green {
background: #27ca3f;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.terminal-title {
flex: 1;
text-align: center;
margin: 0 1rem;
}
.title-text {
color: var(--primary);
font-weight: 600;
font-size: 0.9rem;
display: block;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.subtitle-text {
color: #888888;
font-size: 0.7rem;
display: block;
margin-top: 0.25rem;
}
.status-indicator {
display: flex;
align-items: center;
gap: 0.5rem;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
animation: statusPulse 2s infinite;
}
.status-dot.online {
background: #00ff41;
box-shadow: 0 0 8px #00ff41;
}
.status-dot.offline {
background: #666666;
}
.status-dot.error {
background: #ff0040;
box-shadow: 0 0 8px #ff0040;
}
.status-dot.warning {
background: #ffb000;
box-shadow: 0 0 8px #ffb000;
}
.status-dot.processing {
background: #00bfff;
box-shadow: 0 0 8px #00bfff;
animation: processingPulse 1s infinite;
}
.status-text {
font-size: 0.7rem;
color: #888888;
font-weight: 500;
}
/* Content area */
.retro-content {
padding: 1.5rem;
position: relative;
z-index: 2;
min-height: 200px;
background: var(--bg);
}
/* Scanline effect */
.scanline-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0, 255, 65, 0.03) 2px,
rgba(0, 255, 65, 0.03) 4px
);
pointer-events: none;
z-index: 3;
}
.retro-card.scanlines .scanline-overlay {
animation: scanlineMove 8s linear infinite;
}
@keyframes scanlineMove {
0% {
transform: translateY(0);
}
100% {
transform: translateY(4px);
}
}
/* Border glow effect */
.border-glow {
position: absolute;
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
background: linear-gradient(45deg, var(--primary), transparent, var(--secondary), transparent, var(--primary));
border-radius: 4px;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 0;
}
.retro-card.glow:hover .border-glow {
opacity: 0.6;
animation: borderPulse 3s ease-in-out infinite;
}
@keyframes borderPulse {
0%, 100% {
opacity: 0.3;
}
50% {
opacity: 0.8;
}
}
/* Corner brackets */
.corner-bracket {
position: absolute;
width: 16px;
height: 16px;
border: 2px solid var(--primary);
opacity: 0.6;
transition: all 0.3s ease;
}
.corner-bracket.top-left {
top: 8px;
left: 8px;
border-right: none;
border-bottom: none;
}
.corner-bracket.top-right {
top: 8px;
right: 8px;
border-left: none;
border-bottom: none;
}
.corner-bracket.bottom-left {
bottom: 8px;
left: 8px;
border-right: none;
border-top: none;
}
.corner-bracket.bottom-right {
bottom: 8px;
right: 8px;
border-left: none;
border-top: none;
}
.retro-card:hover .corner-bracket {
opacity: 1;
transform: scale(1.1);
}
/* Variant styles */
.retro-card.circuit {
background: radial-gradient(circle at 50% 50%, rgba(0, 255, 65, 0.1), #111111);
}
.retro-card.circuit::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
linear-gradient(90deg, transparent 49%, rgba(0, 255, 65, 0.1) 50%, transparent 51%),
linear-gradient(0deg, transparent 49%, rgba(0, 255, 65, 0.1) 50%, transparent 51%);
background-size: 20px 20px;
opacity: 0.3;
z-index: 1;
}
.retro-card.data {
background: linear-gradient(135deg, #111111, #1a1a1a);
}
.retro-card.data::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
linear-gradient(45deg, transparent 30%, rgba(0, 255, 65, 0.05) 50%, transparent 70%);
animation: dataFlow 4s linear infinite;
z-index: 1;
}
@keyframes dataFlow {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.retro-card.system {
background:
radial-gradient(ellipse at top, rgba(0, 255, 65, 0.1), transparent),
radial-gradient(ellipse at bottom, rgba(255, 176, 0, 0.1), transparent),
#111111;
}
/* Glitch effect */
.retro-card.glitch {
animation: glitchCard 8s infinite;
}
.retro-card.glitch .retro-content {
animation: glitchContent 8s infinite;
}
@keyframes glitchCard {
0%, 90%, 100% {
transform: translate(0);
}
91% {
transform: translate(-2px, 0);
}
92% {
transform: translate(2px, 0);
}
93% {
transform: translate(-1px, 0);
}
94% {
transform: translate(1px, 0);
}
}
@keyframes glitchContent {
0%, 90%, 100% {
clip-path: inset(0);
}
91% {
clip-path: inset(10px 0 85px 0);
}
92% {
clip-path: inset(80px 0 10px 0);
}
93% {
clip-path: inset(40px 0 50px 0);
}
}
/* Animations */
@keyframes statusPulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
@keyframes processingPulse {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.7;
transform: scale(1.2);
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.retro-card,
.retro-card *,
.retro-card::before,
.retro-card::after {
animation: none !important;
transition: none !important;
}
}
/* Focus states */
.retro-card:focus {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
/* High contrast mode */
@media (prefers-contrast: high) {
.retro-card {
border-width: 2px;
}
.scanline-overlay {
display: none;
}
}
/* Responsive adjustments */
@media (max-width: 768px) {
.retro-header {
padding: 0.5rem;
flex-wrap: wrap;
gap: 0.5rem;
}
.terminal-title {
margin: 0;
order: 3;
flex-basis: 100%;
}
.retro-content {
padding: 1rem;
}
.corner-bracket {
width: 12px;
height: 12px;
}
}
</style>
<script>
// Add interactive behaviors
document.addEventListener('DOMContentLoaded', () => {
const cards = document.querySelectorAll('.retro-card.interactive');
cards.forEach(card => {
// Add click ripple effect
card.addEventListener('click', (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ripple = document.createElement('div');
ripple.style.cssText = `
position: absolute;
border-radius: 50%;
background: rgba(0, 255, 65, 0.3);
transform: scale(0);
animation: ripple 0.6s linear;
left: ${x - 10}px;
top: ${y - 10}px;
width: 20px;
height: 20px;
pointer-events: none;
z-index: 10;
`;
card.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
});
// Add hover sound effect placeholder
card.addEventListener('mouseenter', () => {
// Placeholder for sound effect
// playSound('terminal-hover');
});
});
});
// Add ripple animation
const style = document.createElement('style');
style.textContent = `
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
`;
document.head.appendChild(style);
</script>

View File

@ -0,0 +1,200 @@
---
export interface Props {
currentPage?: string;
}
const { currentPage = 'products' } = Astro.props;
---
<nav class="floating-nav">
<div class="nav-container">
<a href="/" class="nav-logo">Jan</a>
<div class="nav-links">
<a href="/" class={currentPage === 'home' ? 'active' : ''}>Home</a>
<a href="/docs" class={currentPage === 'docs' ? 'active' : ''}>Docs</a>
<a href="/prods" class={currentPage === 'products' ? 'active' : ''}>Products</a>
</div>
<button class="dark-mode-toggle" aria-label="Toggle dark mode">
<span class="toggle-icon sun">☀</span>
<span class="toggle-icon moon">☾</span>
</button>
</div>
</nav>
<style>
.floating-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
background: #fff;
border-bottom: 1px solid #ddd;
z-index: 1000;
padding: 1rem 0;
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-logo {
font-size: 1.25rem;
font-weight: 700;
color: #000;
text-decoration: none;
}
.nav-logo:hover {
color: #333;
}
.nav-links {
display: flex;
gap: 2rem;
}
.nav-links a {
color: #000;
text-decoration: none;
font-weight: 500;
transition: color 0.2s ease;
}
.nav-links a:hover {
color: #0066cc;
}
.nav-links a.active {
color: #0066cc;
border-bottom: 2px solid #0066cc;
padding-bottom: 2px;
}
@media (max-width: 768px) {
.nav-container {
padding: 0 1rem;
}
.nav-links {
gap: 1rem;
}
.nav-links a {
font-size: 0.9rem;
}
}
/* Dark mode toggle button */
.dark-mode-toggle {
background: none;
border: 1px solid #000;
padding: 0.5rem;
cursor: pointer;
font-size: 1.2rem;
line-height: 1;
border-radius: 4px;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
.dark-mode-toggle:hover {
background: #f0f0f0;
}
.toggle-icon {
position: absolute;
transition: opacity 0.3s ease, transform 0.3s ease;
}
.toggle-icon.sun {
opacity: 1;
transform: rotate(0deg);
}
.toggle-icon.moon {
opacity: 0;
transform: rotate(-180deg);
}
/* Dark mode active state */
html[data-theme="dark"] .toggle-icon.sun {
opacity: 0;
transform: rotate(180deg);
}
html[data-theme="dark"] .toggle-icon.moon {
opacity: 1;
transform: rotate(0deg);
}
html[data-theme="dark"] .dark-mode-toggle {
border-color: #fff;
color: #fff;
}
html[data-theme="dark"] .dark-mode-toggle:hover {
background: rgba(255, 255, 255, 0.1);
}
/* Dark mode nav styles */
html[data-theme="dark"] .floating-nav {
background: #1a1a1a;
border-bottom-color: #333;
}
html[data-theme="dark"] .nav-logo {
color: #fff;
}
html[data-theme="dark"] .nav-logo:hover {
color: #ccc;
}
html[data-theme="dark"] .nav-links a {
color: #fff;
}
html[data-theme="dark"] .nav-links a:hover {
color: #4a9eff;
}
html[data-theme="dark"] .nav-links a.active {
color: #4a9eff;
border-bottom-color: #4a9eff;
}
@media (max-width: 768px) {
.dark-mode-toggle {
width: 36px;
height: 36px;
font-size: 1rem;
}
}
</style>
<script>
// Dark mode toggle functionality
const toggleButton = document.querySelector('.dark-mode-toggle');
const html = document.documentElement;
// Check for saved theme preference or default to light
const currentTheme = localStorage.getItem('theme') || 'light';
html.setAttribute('data-theme', currentTheme);
toggleButton?.addEventListener('click', () => {
const currentTheme = html.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
});
</script>

View File

@ -0,0 +1,338 @@
---
export interface Props {
sections?: Array<{
id: string;
title: string;
level?: number;
}>;
}
const {
sections = [
{ id: 'what-were-building', title: 'What We\'re Building' },
{ id: 'two-modes-one-experience', title: 'Two Modes, One Experience' },
{ id: 'our-product-principles', title: 'Our Product Principles' },
{ id: 'available-on-every-device', title: 'Available on Every Device' },
{ id: 'jan-desktop', title: 'Jan Desktop', level: 2 },
{ id: 'jan-web', title: 'Jan Web', level: 2 },
{ id: 'jan-mobile', title: 'Jan Mobile', level: 2 },
{ id: 'jan-server', title: 'Jan Server', level: 2 },
{ id: 'jan-mobile-three-modes-one-experience', title: 'Jan Mobile: Three Modes' },
{ id: 'what-makes-jan-different', title: 'What Makes Jan Different' },
{ id: 'development-timeline', title: 'Development Timeline' }
]
} = Astro.props;
---
<nav class="toc" aria-label="Table of Contents">
<div class="toc-header">
<h3>Contents</h3>
</div>
<ul>
{sections.map((section, index) => {
// Calculate section numbering
let sectionNumber = '';
if (!section.level) {
const mainSectionIndex = sections.slice(0, index + 1).filter(s => !s.level).length;
sectionNumber = `${mainSectionIndex}.`;
} else if (section.level === 2) {
const parentIndex = sections.slice(0, index).reverse().findIndex(s => !s.level);
const mainSectionIndex = sections.slice(0, index - parentIndex).filter(s => !s.level).length;
const subSectionIndex = sections.slice(index - parentIndex, index + 1).filter(s => s.level === 2).length;
sectionNumber = `${mainSectionIndex}.${subSectionIndex}`;
}
return (
<li class={section.level ? `level-${section.level}` : ''}>
<span class="section-number">{sectionNumber}</span>
<a href={`#${section.id}`} data-section={section.id}>
{section.title}
</a>
</li>
);
})}
</ul>
</nav>
<style>
.toc {
position: fixed;
right: 2rem;
top: 50%;
transform: translateY(-50%);
width: 280px;
max-height: 70vh;
overflow-y: auto;
background: #fafafa;
border: 3px double #000;
padding: 0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
font-family: Georgia, 'Times New Roman', serif;
}
.toc-header {
background: #f0f0f0;
border-bottom: 1px solid #000;
padding: 1rem;
text-align: center;
}
.toc h3 {
font-size: 1.1rem;
text-transform: uppercase;
letter-spacing: 0.1em;
margin: 0;
color: #000;
font-weight: 900;
font-family: Georgia, 'Times New Roman', serif;
}
.toc ul {
list-style: none;
margin: 0;
padding: 1rem;
}
.toc li {
margin-bottom: 0;
border-bottom: 1px dotted #999;
padding: 0.5rem 0;
display: flex;
align-items: baseline;
gap: 0.5rem;
}
.toc li:last-child {
border-bottom: none;
}
.toc li.level-2 {
padding-left: 1.5rem;
font-size: 0.9rem;
}
.toc li.level-2 .section-number {
font-size: 0.85rem;
}
.toc li.level-3 {
padding-left: 3rem;
}
.section-number {
font-weight: 700;
font-size: 0.9rem;
color: #000;
flex-shrink: 0;
}
.toc a {
color: #000;
text-decoration: none;
font-size: 0.95rem;
display: block;
transition: all 0.2s ease;
line-height: 1.3;
font-family: Georgia, 'Times New Roman', serif;
}
.toc a:hover {
color: #000;
text-decoration: underline;
text-decoration-style: solid;
text-underline-offset: 2px;
}
.toc a.active {
color: #000;
font-weight: 700;
text-decoration: underline;
text-decoration-thickness: 2px;
}
/* Scrollbar styling - classic newspaper style */
.toc::-webkit-scrollbar {
width: 8px;
}
.toc::-webkit-scrollbar-track {
background: #f0f0f0;
border-left: 1px solid #ccc;
}
.toc::-webkit-scrollbar-thumb {
background: #999;
border-left: 1px solid #666;
}
.toc::-webkit-scrollbar-thumb:hover {
background: #666;
}
/* Add newspaper-style ornament */
.toc::before {
content: '§';
position: absolute;
top: 0.5rem;
right: 1rem;
font-size: 1.5rem;
color: #666;
font-weight: 700;
}
.toc::after {
content: '';
position: absolute;
bottom: 0;
left: 1rem;
right: 1rem;
height: 3px;
background: repeating-linear-gradient(
to right,
#000,
#000 2px,
transparent 2px,
transparent 4px
);
}
/* Dark mode styles */
html[data-theme="dark"] .toc {
background: #2a2a2a;
border-color: #666;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
html[data-theme="dark"] .toc-header {
background: #333;
border-bottom-color: #666;
}
html[data-theme="dark"] .toc h3 {
color: #fff;
}
html[data-theme="dark"] .toc li {
border-bottom-color: #444;
}
html[data-theme="dark"] .section-number {
color: #fff;
}
html[data-theme="dark"] .toc a {
color: #ccc;
}
html[data-theme="dark"] .toc a:hover {
color: #fff;
}
html[data-theme="dark"] .toc a.active {
color: #fff;
}
html[data-theme="dark"] .toc::before {
color: #999;
}
html[data-theme="dark"] .toc::after {
background: repeating-linear-gradient(
to right,
#666,
#666 2px,
transparent 2px,
transparent 4px
);
}
/* Dark mode scrollbar */
html[data-theme="dark"] .toc::-webkit-scrollbar-track {
background: #333;
border-left-color: #444;
}
html[data-theme="dark"] .toc::-webkit-scrollbar-thumb {
background: #666;
border-left-color: #888;
}
html[data-theme="dark"] .toc::-webkit-scrollbar-thumb:hover {
background: #888;
}
/* Hide on smaller screens */
@media (max-width: 1280px) {
.toc {
display: none;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
const tocLinks = document.querySelectorAll('.toc a');
const sections = document.querySelectorAll('h2[id], h3[id]');
// Smooth scrolling
tocLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetId = link.getAttribute('href')?.substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
const offset = 80; // Account for fixed header
const elementPosition = targetElement.getBoundingClientRect().top + window.pageYOffset;
const offsetPosition = elementPosition - offset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
}
});
});
// Update active section on scroll
const updateActiveSection = () => {
const scrollTop = window.pageYOffset + 100;
let activeSection = null;
// Find the current active section
sections.forEach(section => {
const rect = section.getBoundingClientRect();
const absoluteTop = rect.top + window.pageYOffset;
if (absoluteTop <= scrollTop) {
activeSection = section;
}
});
tocLinks.forEach(link => {
link.classList.remove('active');
if (activeSection && link.getAttribute('href') === `#${activeSection.id}`) {
link.classList.add('active');
}
});
};
// Throttled scroll handler
let ticking = false;
const handleScroll = () => {
if (!ticking) {
requestAnimationFrame(() => {
updateActiveSection();
ticking = false;
});
ticking = true;
}
};
window.addEventListener('scroll', handleScroll);
// Initial update
updateActiveSection();
});
</script>

View File

@ -1,900 +0,0 @@
---
// ProductsArchitecture.astro - 3-layer stack explanation component
---
<section id="architecture" class="products-section architecture-section">
<div class="container">
<div class="section-header">
<div class="section-badge">
<div class="badge-robot">
<div class="badge-robot-head"></div>
<div class="badge-robot-body">Stack</div>
</div>
<span>How Jan Works</span>
</div>
<h2 class="section-title">Three Layers, One Experience</h2>
<p class="section-description">
Unlike other AI assistants that do specific tasks with one model or have many models with a myriad of solutions,
Jan provides a complete, integrated stack that works together seamlessly.
</p>
</div>
<!-- Architecture Stack Visualization -->
<div class="architecture-stack">
<!-- Tools Layer (Top) -->
<div class="stack-layer tools-layer" data-layer="tools">
<div class="layer-number">3</div>
<div class="layer-robot">
<div class="tools-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye"></div>
<div class="robot-eye"></div>
</div>
<div class="robot-smile"></div>
</div>
<div class="robot-body"></div>
<div class="robot-arms">
<div class="arm left-arm"></div>
<div class="arm right-arm"></div>
</div>
</div>
</div>
<div class="layer-content">
<h3>Tools & Capabilities</h3>
<p>AI capabilities that actually get things done. Not just chat, but real automation and intelligence augmentation.</p>
<div class="layer-features">
<div class="feature-item active">
<div class="feature-status"></div>
<span>Web Search</span>
</div>
<div class="feature-item active">
<div class="feature-status"></div>
<span>Deep Research</span>
</div>
<div class="feature-item beta">
<div class="feature-status"></div>
<span>Browser Use</span>
</div>
<div class="feature-item coming">
<div class="feature-status"></div>
<span>AI Agents</span>
</div>
</div>
</div>
<div class="layer-connection">
<div class="connection-line tools-to-models"></div>
<div class="data-flow">
<div class="flow-packet"></div>
<div class="flow-packet"></div>
<div class="flow-packet"></div>
</div>
</div>
</div>
<!-- Models Layer (Middle) -->
<div class="stack-layer models-layer" data-layer="models">
<div class="layer-number">2</div>
<div class="layer-robot">
<div class="models-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye thinking"></div>
<div class="robot-eye thinking"></div>
</div>
<div class="robot-smile"></div>
</div>
<div class="robot-body"></div>
</div>
</div>
<div class="layer-content">
<h3>AI Models</h3>
<p>Purpose-built models, not API wrappers. Trained by us, optimized for privacy and performance.</p>
<div class="layer-features">
<div class="feature-item active">
<div class="feature-status"></div>
<span>Jan V1 Series</span>
</div>
<div class="feature-item beta">
<div class="feature-status"></div>
<span>Jan Nano</span>
</div>
<div class="feature-item coming">
<div class="feature-status"></div>
<span>Lucy (Multimodal)</span>
</div>
</div>
</div>
<div class="layer-connection">
<div class="connection-line models-to-platforms"></div>
<div class="data-flow">
<div class="flow-packet"></div>
<div class="flow-packet"></div>
</div>
</div>
</div>
<!-- Platforms Layer (Bottom) -->
<div class="stack-layer platforms-layer" data-layer="platforms">
<div class="layer-number">1</div>
<div class="layer-robot">
<div class="platforms-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye"></div>
<div class="robot-eye"></div>
</div>
<div class="robot-smile"></div>
</div>
<div class="robot-body"></div>
<div class="robot-base">
<div class="base-foundation"></div>
</div>
</div>
</div>
<div class="layer-content">
<h3>Platform Ecosystem</h3>
<p>Run anywhere - desktop, web, mobile, or server. Your AI assistant follows you across all devices.</p>
<div class="layer-features">
<div class="feature-item active">
<div class="feature-status"></div>
<span>Desktop App</span>
</div>
<div class="feature-item beta">
<div class="feature-status"></div>
<span>jan.ai Web</span>
</div>
<div class="feature-item coming">
<div class="feature-status"></div>
<span>Mobile Apps</span>
</div>
<div class="feature-item coming">
<div class="feature-status"></div>
<span>Server Edition</span>
</div>
</div>
</div>
</div>
</div>
<!-- Architecture Benefits -->
<div class="architecture-benefits">
<h3>Why This Architecture Matters</h3>
<div class="benefits-grid">
<div class="benefit-card">
<div class="benefit-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
</div>
</div>
<h4>Tight Integration</h4>
<p>Each layer is designed to work perfectly with the others. No API incompatibilities or integration headaches.</p>
</div>
<div class="benefit-card">
<div class="benefit-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
</div>
</div>
<h4>Your Control</h4>
<p>Own your models, choose your deployment, control your data. No vendor lock-in or surprise policy changes.</p>
</div>
<div class="benefit-card">
<div class="benefit-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
</div>
</div>
<h4>Scales With You</h4>
<p>Start simple with local models, add cloud power when needed, deploy for teams when you're ready.</p>
</div>
</div>
</div>
<!-- Interactive Demo -->
<div class="architecture-demo">
<h3>See It In Action</h3>
<div class="demo-container">
<div class="demo-scenario active" data-scenario="search">
<div class="scenario-title">User asks: "Find recent AI research papers"</div>
<div class="demo-flow">
<div class="flow-step" data-step="1">
<div class="step-number">1</div>
<div class="step-content">
<strong>Tools Layer:</strong> Web Search tool activates
</div>
</div>
<div class="flow-arrow"></div>
<div class="flow-step" data-step="2">
<div class="step-number">2</div>
<div class="step-content">
<strong>Models Layer:</strong> Jan V1 processes the request
</div>
</div>
<div class="flow-arrow"></div>
<div class="flow-step" data-step="3">
<div class="step-number">3</div>
<div class="step-content">
<strong>Platform Layer:</strong> Results displayed in your app
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<style>
.architecture-section {
background: var(--light-gray);
border-top: 1px solid var(--border-color);
}
.badge-robot-head {
background: var(--pastel-blue);
}
/* Architecture Stack */
.architecture-stack {
margin: 4rem 0;
max-width: 900px;
margin-left: auto;
margin-right: auto;
position: relative;
}
.stack-layer {
background: white;
border-radius: 20px;
border: 3px solid var(--border-color);
padding: 2rem;
margin-bottom: 2rem;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
position: relative;
display: flex;
align-items: center;
gap: 2rem;
}
.stack-layer:hover {
transform: translateX(8px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
}
.tools-layer {
border-color: var(--light-purple);
border-left-width: 8px;
}
.models-layer {
border-color: var(--soft-pink);
border-left-width: 8px;
}
.platforms-layer {
border-color: var(--primary-blue);
border-left-width: 8px;
margin-bottom: 0;
}
.layer-number {
position: absolute;
top: -15px;
left: 2rem;
width: 30px;
height: 30px;
background: var(--primary-blue);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 1.1rem;
border: 3px solid white;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.layer-robot {
flex-shrink: 0;
}
/* Robot Designs */
.tools-robot, .models-robot, .platforms-robot {
position: relative;
}
.tools-robot .robot-head,
.models-robot .robot-head,
.platforms-robot .robot-head {
width: 60px;
height: 60px;
border-radius: 15px;
border: 3px solid var(--dark-text);
margin: 0 auto 10px;
position: relative;
}
.tools-robot .robot-body,
.models-robot .robot-body,
.platforms-robot .robot-body {
width: 70px;
height: 80px;
border-radius: 15px;
border: 3px solid var(--dark-text);
margin: 0 auto;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.tools-robot .robot-head { background: var(--light-purple); }
.tools-robot .robot-body { background: var(--light-purple); }
.models-robot .robot-head { background: var(--soft-pink); }
.models-robot .robot-body { background: var(--soft-pink); }
.platforms-robot .robot-head { background: var(--pastel-blue); }
.platforms-robot .robot-body { background: var(--pastel-blue); }
.robot-eyes {
display: flex;
justify-content: space-between;
padding: 12px 8px;
}
.robot-eye {
width: 12px;
height: 12px;
background: var(--dark-text);
border-radius: 50%;
position: relative;
}
.robot-eye::after {
content: '';
position: absolute;
top: 2px;
right: 2px;
width: 3px;
height: 3px;
background: white;
border-radius: 50%;
}
.robot-eye.thinking {
animation: thinking 3s infinite ease-in-out;
}
/* Robot-specific details */
.robot-tools-display {
display: flex;
gap: 4px;
flex-wrap: wrap;
justify-content: center;
}
.tool-icon {
width: 8px;
height: 8px;
border-radius: 2px;
border: 1px solid var(--dark-text);
}
.tool-icon.search { background: var(--success-green); }
.tool-icon.research { background: var(--primary-blue); }
.tool-icon.browser { background: var(--warning-amber); }
.robot-brain {
position: absolute;
top: 5px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 10px;
}
.brain-wave {
width: 100%;
height: 2px;
background: var(--primary-blue);
margin: 1px 0;
border-radius: 1px;
animation: brainWave 2s infinite ease-in-out;
}
.brain-wave:nth-child(2) { animation-delay: 0.3s; }
.brain-wave:nth-child(3) { animation-delay: 0.6s; }
.neural-network {
position: relative;
width: 40px;
height: 40px;
}
.network-node {
position: absolute;
width: 6px;
height: 6px;
background: var(--dark-text);
border-radius: 50%;
}
.network-node:nth-child(1) { top: 5px; left: 5px; }
.network-node:nth-child(2) { top: 5px; right: 5px; }
.network-node:nth-child(3) { bottom: 5px; left: 50%; transform: translateX(-50%); }
.network-connection {
position: absolute;
height: 1px;
background: var(--dark-text);
}
.network-connection:nth-child(4) {
top: 8px;
left: 11px;
width: 18px;
}
.network-connection:nth-child(5) {
top: 11px;
left: 17px;
width: 15px;
transform: rotate(45deg);
}
.platform-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px;
}
.platform-icon {
width: 12px;
height: 12px;
border-radius: 3px;
border: 1px solid var(--dark-text);
}
.platform-icon.desktop { background: var(--success-green); }
.platform-icon.mobile { background: var(--warning-amber); }
.platform-icon.web { background: var(--primary-blue); }
.platform-icon.server { background: var(--medium-gray); }
.robot-base {
margin-top: 5px;
}
.base-foundation {
width: 50px;
height: 8px;
background: var(--medium-gray);
border-radius: 4px;
border: 2px solid var(--dark-text);
margin: 0 auto;
}
.layer-content {
flex: 1;
}
.layer-content h3 {
font-size: 1.5rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 0.75rem;
}
.layer-content p {
color: var(--medium-gray);
margin-bottom: 1.5rem;
line-height: 1.6;
}
.layer-features {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
}
.feature-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
font-weight: 500;
}
.feature-status {
width: 8px;
height: 8px;
border-radius: 50%;
border: 1px solid var(--dark-text);
}
.feature-item.active .feature-status {
background: var(--success-green);
animation: pulse 2s infinite;
}
.feature-item.beta .feature-status {
background: var(--warning-amber);
animation: pulse 2s infinite;
}
.feature-item.coming .feature-status {
background: var(--medium-gray);
}
/* Connection Lines */
.layer-connection {
position: absolute;
right: -20px;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 2px;
}
.connection-line {
width: 100%;
height: 2px;
background: var(--border-color);
position: relative;
}
.data-flow {
position: absolute;
top: -5px;
left: 0;
right: 0;
height: 12px;
}
.flow-packet {
position: absolute;
width: 6px;
height: 6px;
background: var(--primary-blue);
border-radius: 50%;
animation: flowData 3s infinite linear;
}
.flow-packet:nth-child(2) { animation-delay: 1s; }
.flow-packet:nth-child(3) { animation-delay: 2s; }
/* Architecture Benefits */
.architecture-benefits {
margin: 4rem 0;
}
.architecture-benefits h3 {
text-align: center;
font-size: 2rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 2rem;
}
.benefits-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.benefit-card {
background: white;
border-radius: 16px;
border: 2px solid var(--border-color);
padding: 2rem;
text-align: center;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.benefit-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
border-color: var(--primary-blue);
}
.benefit-robot {
margin-bottom: 1rem;
}
.benefit-robot .robot-head {
width: 40px;
height: 40px;
background: var(--warm-yellow);
border-radius: 10px;
border: 2px solid var(--dark-text);
margin: 0 auto 6px;
}
.benefit-robot .robot-body {
width: 50px;
height: 60px;
background: var(--gentle-orange);
border-radius: 10px;
border: 2px solid var(--dark-text);
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
}
.benefit-card h4 {
font-size: 1.3rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 1rem;
}
.benefit-card p {
color: var(--medium-gray);
line-height: 1.6;
}
/* Interactive Demo */
.architecture-demo {
margin: 4rem 0;
background: white;
border-radius: 20px;
border: 2px solid var(--border-color);
padding: 3rem;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
}
.architecture-demo h3 {
text-align: center;
font-size: 2rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 2rem;
}
.demo-container {
max-width: 800px;
margin: 0 auto;
}
.scenario-title {
text-align: center;
font-size: 1.2rem;
font-weight: 600;
color: var(--primary-blue);
margin-bottom: 2rem;
padding: 1rem;
background: var(--light-blue);
border-radius: 10px;
border: 2px solid var(--primary-blue);
}
.demo-flow {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
flex-wrap: wrap;
}
.flow-step {
background: var(--cream-white);
border-radius: 12px;
border: 2px solid var(--border-color);
padding: 1.5rem;
text-align: center;
max-width: 200px;
transition: all 0.3s ease;
}
.flow-step:hover {
border-color: var(--primary-blue);
transform: scale(1.05);
}
.step-number {
width: 30px;
height: 30px;
background: var(--primary-blue);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
margin: 0 auto 1rem;
}
.step-content {
font-size: 0.9rem;
line-height: 1.4;
}
.step-content strong {
color: var(--primary-blue);
display: block;
margin-bottom: 0.5rem;
}
.flow-arrow {
width: 30px;
height: 2px;
background: var(--primary-blue);
position: relative;
}
.flow-arrow::after {
content: '';
position: absolute;
right: -5px;
top: -3px;
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 8px solid var(--primary-blue);
}
/* Animations */
@keyframes thinking {
0%, 100% { transform: scaleY(1); }
50% { transform: scaleY(0.8); }
}
@keyframes brainWave {
0%, 100% { opacity: 0.3; transform: scaleX(1); }
50% { opacity: 1; transform: scaleX(1.2); }
}
@keyframes flowData {
0% { left: 0; opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { left: calc(100% - 6px); opacity: 0; }
}
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
}
/* Responsive Design */
@media (max-width: 1024px) {
.stack-layer {
flex-direction: column;
text-align: center;
gap: 1.5rem;
}
.layer-connection {
display: none;
}
.benefits-grid {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
}
@media (max-width: 768px) {
.architecture-stack {
margin: 3rem 0;
}
.stack-layer {
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.layer-content h3 {
font-size: 1.3rem;
}
.demo-flow {
flex-direction: column;
}
.flow-arrow {
transform: rotate(90deg);
}
.architecture-demo {
padding: 2rem;
}
}
@media (max-width: 480px) {
.stack-layer {
padding: 1.25rem;
}
.benefits-grid {
grid-template-columns: 1fr;
}
.benefit-card {
padding: 1.5rem;
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.robot-eye, .brain-wave, .flow-packet, .feature-status, .stack-layer, .benefit-card, .flow-step {
animation: none !important;
transition: none !important;
}
}
/* High contrast mode */
@media (prefers-contrast: high) {
.stack-layer, .benefit-card, .architecture-demo {
border-width: 3px;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Add interactive hover effects for stack layers
const stackLayers = document.querySelectorAll('.stack-layer');
stackLayers.forEach(layer => {
layer.addEventListener('mouseenter', () => {
const robot = layer.querySelector('.tools-robot, .models-robot, .platforms-robot');
if (robot) {
robot.style.animation = 'bounce 0.6s ease-in-out';
setTimeout(() => {
robot.style.animation = '';
}, 600);
}
});
});
// Animate flow packets when layer is in view
const observerOptions = {
threshold: 0.5,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const flowPackets = entry.target.querySelectorAll('.flow-packet');
flowPackets.forEach((packet, index) => {
packet.style.animationDelay = `${index}s`;
packet.style.animationPlayState = 'running';
});
}
});
}, observerOptions);
stackLayers.forEach(layer => {
observer.observe(layer);
});
// Add click interaction for demo steps
const demoSteps = document.querySelectorAll('.flow-step');
demoSteps.forEach((step, index) => {
step.addEventListener('click', () => {
// Remove active class from all steps
demoSteps.forEach(s => s.classList.remove('active'));
// Add active class to clicked step and previous steps
for (let i = 0; i <= index; i++) {
demoSteps[i].classList.add('active');
}
});
});
});
</script>

View File

@ -1,696 +0,0 @@
---
// ProductsHero.astro - Hero section with blue-tinted background and friendly robot
---
<section id="hero" class="products-hero">
<div class="hero-background">
<div class="floating-clouds">
<div class="cloud cloud-1"></div>
<div class="cloud cloud-2"></div>
<div class="cloud cloud-3"></div>
<div class="cloud cloud-4"></div>
</div>
<div class="floating-elements">
<div class="element element-1"></div>
<div class="element element-2"></div>
<div class="element element-3"></div>
</div>
</div>
<div class="container">
<div class="hero-content">
<div class="hero-badge">
<div class="badge-robot">
<div class="badge-robot-head"></div>
<div class="badge-robot-body">AI</div>
</div>
<span>Full Stack AI Solution</span>
</div>
<h1 class="hero-title">
<span class="title-main">Jan's Product Roadmap</span>
<span class="title-sub">AI that runs where you need it, how you need it</span>
</h1>
<p class="hero-description">
Complete ecosystem of models, applications, and tools. Let's build the future of AI together!
</p>
<div class="hero-robot">
<div class="robot-container bounce">
<div class="robot-head">
<div class="robot-blush left"></div>
<div class="robot-blush right"></div>
<div class="robot-antenna">
<div class="antenna-light"></div>
</div>
<div class="robot-eyes">
<div class="robot-eye left-eye wink">
<div class="eye-shine"></div>
</div>
<div class="robot-eye right-eye excited">
<div class="eye-shine"></div>
</div>
</div>
<div class="robot-mouth happy"></div>
</div>
<div class="robot-body">
<div class="robot-panel">
<div class="panel-light green pulse"></div>
<div class="panel-light blue pulse" style="animation-delay: 0.5s;"></div>
<div class="panel-light amber pulse" style="animation-delay: 1s;"></div>
</div>
<div class="robot-screen">
<div class="screen-content">
<div class="code-line"></div>
<div class="code-line short"></div>
<div class="code-line"></div>
</div>
</div>
</div>
<div class="robot-arms">
<div class="arm left-arm wave"></div>
<div class="arm right-arm wave" style="animation-delay: 1s;"></div>
</div>
<div class="robot-sparkles">
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
</div>
<div class="speech-bubble">
<span>Ready to build amazing AI experiences?</span>
<div class="bubble-tail"></div>
</div>
</div>
</div>
<div class="hero-stats">
<div class="stat">
<div class="stat-number">3</div>
<div class="stat-label">AI Models</div>
</div>
<div class="stat">
<div class="stat-number">4</div>
<div class="stat-label">Platforms</div>
</div>
<div class="stat">
<div class="stat-number">4</div>
<div class="stat-label">Tools</div>
</div>
</div>
</div>
</div>
</section>
<style>
.products-hero {
background: linear-gradient(135deg, #8338EC 0%, #3A86FF 25%, #FF006E 50%, #FFB700 75%, #06FFA5 100%);
min-height: 100vh;
display: flex;
align-items: center;
position: relative;
overflow: hidden;
padding: 2rem 0;
}
.hero-background {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
}
.floating-clouds {
position: absolute;
width: 100%;
height: 100%;
}
.cloud {
position: absolute;
background: rgba(255, 255, 255, 0.3);
border-radius: 50px;
opacity: 0.7;
animation: float 20s infinite ease-in-out;
}
.cloud-1 {
width: 120px;
height: 80px;
top: 15%;
left: 5%;
animation-delay: 0s;
}
.cloud-2 {
width: 100px;
height: 60px;
top: 25%;
right: 10%;
animation-delay: -5s;
}
.cloud-3 {
width: 80px;
height: 50px;
top: 60%;
left: 15%;
animation-delay: -10s;
}
.cloud-4 {
width: 140px;
height: 90px;
top: 70%;
right: 5%;
animation-delay: -15s;
}
.floating-elements {
position: absolute;
width: 100%;
height: 100%;
}
.element {
position: absolute;
width: 8px;
height: 8px;
background: rgba(255, 255, 255, 0.5);
border-radius: 50%;
animation: elementFloat 15s infinite ease-in-out;
}
.element-1 {
top: 20%;
left: 20%;
animation-delay: 0s;
}
.element-2 {
top: 40%;
right: 25%;
animation-delay: -5s;
}
.element-3 {
top: 75%;
left: 60%;
animation-delay: -10s;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
position: relative;
z-index: 2;
}
.hero-content {
text-align: center;
color: white;
}
.hero-badge {
display: inline-flex;
align-items: center;
gap: 0.75rem;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
padding: 0.75rem 1.5rem;
border-radius: 50px;
font-size: 0.9rem;
font-weight: 600;
margin-bottom: 2rem;
border: 1px solid rgba(255, 255, 255, 0.3);
}
.badge-robot {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.badge-robot-head {
width: 16px;
height: 16px;
background: rgba(255, 255, 255, 0.9);
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.1);
}
.badge-robot-body {
font-size: 0.7rem;
font-weight: 700;
color: white;
}
.hero-title {
margin-bottom: 2rem;
}
.title-main {
display: block;
font-size: clamp(2.5rem, 8vw, 4rem);
font-weight: 800;
margin-bottom: 0.5rem;
line-height: 1.1;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.title-sub {
display: block;
font-size: clamp(1.2rem, 4vw, 1.8rem);
font-weight: 500;
opacity: 0.9;
line-height: 1.3;
}
.hero-description {
font-size: clamp(1.1rem, 3vw, 1.3rem);
margin-bottom: 3rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
opacity: 0.9;
line-height: 1.6;
}
/* Hero Robot */
.hero-robot {
margin: 3rem 0;
display: flex;
justify-content: center;
}
.robot-container {
position: relative;
display: inline-block;
}
.robot-head {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #FFB700 0%, #FB5607 100%);
border-radius: 25px;
position: relative;
margin: 0 auto 15px;
border: 4px solid #1A1A2E;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
}
.robot-antenna {
position: absolute;
top: -25px;
left: 50%;
transform: translateX(-50%);
width: 4px;
height: 20px;
background: #1e293b;
border-radius: 2px;
}
.antenna-light {
position: absolute;
top: -10px;
left: 50%;
transform: translateX(-50%);
width: 10px;
height: 10px;
background: #FF006E;
border-radius: 50%;
border: 2px solid #1A1A2E;
animation: antennaGlow 2s infinite;
box-shadow: 0 0 20px rgba(255, 0, 110, 0.6);
}
.robot-eyes {
display: flex;
justify-content: space-between;
padding: 20px 15px 10px;
}
.robot-eye {
width: 20px;
height: 20px;
background: #1A1A2E;
border-radius: 50%;
position: relative;
transition: all 0.3s ease;
}
.robot-eye.wink {
height: 2px;
border-radius: 0;
animation: winkAnimation 4s infinite;
}
.robot-eye.excited {
transform: scale(1.2);
}
.eye-shine {
position: absolute;
top: 3px;
right: 3px;
width: 6px;
height: 6px;
background: white;
border-radius: 50%;
}
.robot-mouth.happy {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
width: 30px;
height: 15px;
border: 4px solid #1e293b;
border-top: none;
border-radius: 0 0 30px 30px;
}
.robot-body {
width: 120px;
height: 140px;
background: linear-gradient(135deg, #06FFA5 0%, #00F5FF 100%);
border-radius: 20px;
margin: 0 auto;
border: 4px solid #1A1A2E;
position: relative;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
}
.robot-panel {
display: flex;
justify-content: center;
gap: 10px;
padding: 25px 0 15px;
}
.panel-light {
width: 14px;
height: 14px;
border-radius: 50%;
border: 2px solid #1e293b;
}
.panel-light.green { background: #22c55e; }
.panel-light.blue { background: #3b82f6; }
.panel-light.amber { background: #f59e0b; }
.robot-screen {
width: 80px;
height: 50px;
background: #1e293b;
border-radius: 8px;
margin: 0 auto;
padding: 8px;
display: flex;
flex-direction: column;
gap: 4px;
}
.screen-content {
display: flex;
flex-direction: column;
gap: 3px;
}
.code-line {
height: 3px;
background: #22c55e;
border-radius: 2px;
animation: codeFlow 3s infinite ease-in-out;
}
.code-line.short {
width: 60%;
animation-delay: 0.5s;
}
.robot-arms {
display: flex;
justify-content: space-between;
margin-top: -70px;
padding: 0 25px;
position: relative;
z-index: -1;
}
.arm {
width: 15px;
height: 50px;
background: #fed7aa;
border-radius: 8px;
border: 3px solid #1e293b;
transform-origin: top center;
}
.speech-bubble {
position: absolute;
top: -50px;
left: 130%;
background: white;
color: #1e293b;
padding: 1rem 1.5rem;
border-radius: 20px;
border: 3px solid #1e293b;
font-size: 0.9rem;
font-weight: 600;
white-space: nowrap;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
animation: bubbleBounce 4s infinite ease-in-out;
}
.bubble-tail {
position: absolute;
left: -12px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right: 12px solid white;
}
.bubble-tail::before {
content: '';
position: absolute;
left: -3px;
top: -12px;
width: 0;
height: 0;
border-top: 12px solid transparent;
border-bottom: 12px solid transparent;
border-right: 15px solid #1e293b;
}
.hero-stats {
display: flex;
justify-content: center;
gap: 4rem;
flex-wrap: wrap;
margin-top: 2rem;
}
.stat {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.stat-number {
font-size: 3rem;
font-weight: 800;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.stat-label {
font-size: 1.1rem;
font-weight: 500;
opacity: 0.9;
}
/* Animations */
@keyframes float {
0%, 100% { transform: translateY(0px) translateX(0px); }
25% { transform: translateY(-20px) translateX(10px); }
50% { transform: translateY(0px) translateX(20px); }
75% { transform: translateY(-10px) translateX(10px); }
}
@keyframes elementFloat {
0%, 100% { transform: translateY(0px) scale(1); opacity: 0.5; }
50% { transform: translateY(-30px) scale(1.2); opacity: 1; }
}
@keyframes bounce {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.7; }
}
@keyframes antennaGlow {
0%, 100% {
background: #FF006E;
box-shadow: 0 0 20px rgba(255, 0, 110, 0.6);
}
50% {
background: #06FFA5;
box-shadow: 0 0 30px rgba(6, 255, 165, 0.8);
}
}
@keyframes winkAnimation {
0%, 90%, 100% { height: 20px; border-radius: 50%; }
95% { height: 2px; border-radius: 0; }
}
.robot-blush {
position: absolute;
width: 15px;
height: 10px;
background: rgba(255, 0, 110, 0.3);
border-radius: 50%;
top: 45%;
}
.robot-blush.left {
left: 10px;
}
.robot-blush.right {
right: 10px;
}
.robot-sparkles {
position: absolute;
top: -30px;
left: -30px;
right: -30px;
bottom: -30px;
pointer-events: none;
}
.sparkle {
position: absolute;
width: 6px;
height: 6px;
background: #FFB700;
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
animation: sparkleFloat 3s ease-in-out infinite;
}
.sparkle:nth-child(1) { top: 10%; left: 20%; animation-delay: 0s; }
.sparkle:nth-child(2) { top: 30%; right: 15%; animation-delay: 0.7s; }
.sparkle:nth-child(3) { bottom: 20%; left: 10%; animation-delay: 1.4s; }
.sparkle:nth-child(4) { bottom: 10%; right: 25%; animation-delay: 2.1s; }
@keyframes sparkleFloat {
0%, 100% {
opacity: 0;
transform: scale(0) rotate(0deg) translateY(0);
}
50% {
opacity: 1;
transform: scale(1) rotate(180deg) translateY(-10px);
}
}
@keyframes wave {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(-15deg); }
75% { transform: rotate(15deg); }
}
@keyframes codeFlow {
0% { width: 0%; opacity: 0; }
50% { width: 100%; opacity: 1; }
100% { width: 100%; opacity: 0.5; }
}
@keyframes bubbleBounce {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
}
/* Responsive Design */
@media (max-width: 1024px) {
.speech-bubble {
display: none;
}
.hero-stats {
gap: 2rem;
}
}
@media (max-width: 768px) {
.products-hero {
min-height: 80vh;
padding: 1rem 0;
}
.container {
padding: 0 1rem;
}
.hero-robot {
margin: 2rem 0;
}
.robot-head {
width: 80px;
height: 80px;
border-radius: 20px;
}
.robot-body {
width: 100px;
height: 120px;
border-radius: 16px;
}
.hero-stats {
gap: 1.5rem;
}
.stat-number {
font-size: 2.5rem;
}
}
@media (max-width: 480px) {
.hero-description {
margin-bottom: 2rem;
}
.robot-arms {
padding: 0 20px;
}
.hero-stats {
gap: 1rem;
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.cloud, .element, .robot-container, .panel-light, .arm, .antenna-light, .code-line, .speech-bubble {
animation: none !important;
}
}
</style>

View File

@ -1,909 +0,0 @@
---
// ProductsModels.astro - AI Models section with detailed specifications
---
<section id="models" class="products-section models-section">
<div class="container">
<div class="section-header">
<div class="section-badge">
<div class="badge-robot">
<div class="badge-robot-head"></div>
<div class="badge-robot-body">AI</div>
</div>
<span>AI Models</span>
</div>
<h2 class="section-title">Our AI Models</h2>
<p class="section-description">
Purpose-built models, not API wrappers. Trained by us, optimized for privacy and performance.
As of now, we have Jan Nano in 2 flavors and Lucy but more are coming soon.
</p>
</div>
<!-- Models Grid -->
<div class="models-grid">
<!-- Jan V1 Series -->
<div class="model-card jan-v1 feature-card">
<div class="model-robot-section">
<div class="model-robot v1-robot">
<div class="robot-head">
<div class="robot-glasses">
<div class="glasses-frame left">
<div class="robot-eye nerdy"></div>
</div>
<div class="glasses-bridge"></div>
<div class="glasses-frame right">
<div class="robot-eye nerdy"></div>
</div>
</div>
<div class="robot-smile cheeky"></div>
<div class="robot-antenna">
<div class="antenna-tip active"></div>
</div>
<div class="robot-thinking-bubbles">
<div class="bubble small"></div>
<div class="bubble medium"></div>
<div class="bubble large">🧠</div>
</div>
</div>
<div class="robot-body">
<div class="robot-chest">
<div class="chest-panel">
<div class="panel-line active"></div>
<div class="panel-line active"></div>
<div class="panel-line active"></div>
</div>
<div class="robot-pocket-protector">
<div class="pen"></div>
<div class="pen"></div>
<div class="calculator">π</div>
</div>
</div>
<div class="robot-badge">V1</div>
</div>
<div class="robot-arms">
<div class="arm left-arm"></div>
<div class="arm right-arm"></div>
</div>
</div>
<div class="model-status-bubble">
<div class="status-badge status-active">Production Ready</div>
</div>
</div>
<div class="model-content">
<div class="model-header">
<h3>Jan V1 Series</h3>
<div class="model-version">v1.2.1</div>
</div>
<p class="model-description">
Complete model family designed to compete with Claude and GPT-4.
Optimized for reasoning, coding, and general conversation.
</p>
<div class="model-specs">
<div class="spec-section">
<h4>Model Sizes</h4>
<div class="spec-grid">
<div class="spec-item">
<div class="spec-label">7B</div>
<div class="spec-value">8GB RAM</div>
</div>
<div class="spec-item">
<div class="spec-label">13B</div>
<div class="spec-value">16GB RAM</div>
</div>
<div class="spec-item">
<div class="spec-label">70B</div>
<div class="spec-value">64GB RAM</div>
</div>
</div>
</div>
<div class="spec-section">
<h4>Performance</h4>
<div class="spec-highlight">
<div class="highlight-label">Context Window</div>
<div class="highlight-value">32,768 tokens</div>
</div>
</div>
</div>
<div class="model-capabilities">
<h4>Capabilities</h4>
<div class="capabilities-grid">
<div class="capability active">
<div class="capability-icon reasoning"></div>
<span>Reasoning</span>
</div>
<div class="capability active">
<div class="capability-icon coding"></div>
<span>Code Generation</span>
</div>
<div class="capability active">
<div class="capability-icon multilingual"></div>
<span>Multilingual</span>
</div>
<div class="capability active">
<div class="capability-icon tools"></div>
<span>Tool Use</span>
</div>
</div>
</div>
<div class="model-metrics">
<div class="metric">
<div class="metric-value">Production</div>
<div class="metric-label">Status</div>
</div>
<div class="metric">
<div class="metric-value">3M+</div>
<div class="metric-label">Downloads</div>
</div>
</div>
</div>
</div>
<!-- Jan Nano -->
<div class="model-card jan-nano feature-card">
<div class="model-robot-section">
<div class="model-robot nano-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye research scanning"></div>
<div class="robot-eye research scanning"></div>
</div>
<div class="robot-smile curious"></div>
<div class="robot-scanner active">
<div class="scanner-beam"></div>
<div class="scanner-grid"></div>
</div>
<div class="robot-research-goggles">
<div class="goggle-strap"></div>
</div>
</div>
<div class="robot-body">
<div class="robot-chest">
<div class="research-display active">
<div class="display-wave"></div>
<div class="display-wave"></div>
<div class="display-wave"></div>
</div>
<div class="robot-lab-coat">
<div class="coat-collar"></div>
<div class="coat-buttons">
<div class="button"></div>
<div class="button"></div>
</div>
</div>
</div>
<div class="robot-badge">Nano</div>
</div>
<div class="robot-tools">
<div class="tool search-tool"></div>
<div class="tool analysis-tool"></div>
</div>
</div>
<div class="model-status-bubble">
<div class="status-badge status-beta">Beta</div>
</div>
</div>
<div class="model-content">
<div class="model-header">
<h3>Jan Nano</h3>
<div class="model-version">v0.6.0</div>
</div>
<p class="model-description">
Specialized for research and information retrieval. Native MCP integration
for web search, document analysis, and knowledge synthesis. Available in 2 flavors.
</p>
<div class="model-specs">
<div class="spec-section">
<h4>Specifications</h4>
<div class="spec-grid">
<div class="spec-item">
<div class="spec-label">Parameters</div>
<div class="spec-value">4B</div>
</div>
<div class="spec-item">
<div class="spec-label">RAM Required</div>
<div class="spec-value">6-8GB</div>
</div>
</div>
</div>
<div class="spec-section">
<h4>Context Options</h4>
<div class="spec-grid">
<div class="spec-item">
<div class="spec-label">Standard</div>
<div class="spec-value">32k tokens</div>
</div>
<div class="spec-item">
<div class="spec-label">Extended</div>
<div class="spec-value">128k tokens</div>
</div>
</div>
</div>
</div>
<div class="model-capabilities">
<h4>Specialized For</h4>
<div class="capabilities-grid">
<div class="capability active">
<div class="capability-icon search"></div>
<span>Web Search</span>
</div>
<div class="capability active">
<div class="capability-icon document"></div>
<span>Document Analysis</span>
</div>
<div class="capability active">
<div class="capability-icon mobile"></div>
<span>Mobile Optimized</span>
</div>
<div class="capability active">
<div class="capability-icon mcp"></div>
<span>MCP Tools</span>
</div>
</div>
</div>
<div class="model-metrics">
<div class="metric">
<div class="metric-value">Beta</div>
<div class="metric-label">Status</div>
</div>
<div class="metric">
<div class="metric-value">2</div>
<div class="metric-label">Flavors</div>
</div>
</div>
</div>
</div>
<!-- Lucy -->
<div class="model-card lucy feature-card">
<div class="model-robot-section">
<div class="model-robot lucy-robot">
<div class="robot-head dreamy">
<div class="robot-eyes">
<div class="robot-eye sleeping dreaming"></div>
<div class="robot-eye sleeping dreaming"></div>
</div>
<div class="robot-dream-cloud">
<div class="dream-content">
<span class="dream-emoji">🌟</span>
<span class="dream-emoji">👁️</span>
<span class="dream-emoji">🎨</span>
</div>
</div>
<div class="robot-sleep-cap">
<div class="cap-pom-pom"></div>
</div>
</div>
<div class="robot-body">
<div class="robot-pajamas">
<div class="pajama-pattern">
<div class="star"></div>
<div class="star"></div>
<div class="moon">🌙</div>
</div>
</div>
<div class="robot-badge dreamy">Lucy</div>
<div class="robot-teddy-bear">🧸</div>
</div>
<div class="robot-progress">
<div class="progress-bar">
<div class="progress-fill training"></div>
</div>
<div class="progress-text">Training...</div>
</div>
</div>
<div class="model-status-bubble">
<div class="status-badge status-coming">Q2 2025</div>
</div>
</div>
<div class="model-content">
<div class="model-header">
<h3>Lucy</h3>
<div class="model-version">v0.1.0-alpha</div>
</div>
<p class="model-description">
Advanced multimodal capabilities for image understanding, document processing,
and visual reasoning tasks. The future of AI interaction.
</p>
<div class="model-specs">
<div class="spec-section">
<h4>Modalities</h4>
<div class="spec-grid">
<div class="spec-item">
<div class="spec-label">Vision</div>
<div class="spec-value">Ready</div>
</div>
<div class="spec-item">
<div class="spec-label">Text</div>
<div class="spec-value">Ready</div>
</div>
<div class="spec-item">
<div class="spec-label">Audio</div>
<div class="spec-value">Soon</div>
</div>
</div>
</div>
<div class="spec-section">
<h4>Timeline</h4>
<div class="spec-highlight">
<div class="highlight-label">Release Target</div>
<div class="highlight-value">Q2 2025</div>
</div>
</div>
</div>
<div class="model-capabilities">
<h4>Future Capabilities</h4>
<div class="capabilities-grid">
<div class="capability coming">
<div class="capability-icon image"></div>
<span>Image Analysis</span>
</div>
<div class="capability coming">
<div class="capability-icon ocr"></div>
<span>OCR</span>
</div>
<div class="capability coming">
<div class="capability-icon visual"></div>
<span>Visual Reasoning</span>
</div>
<div class="capability coming">
<div class="capability-icon processing"></div>
<span>Document Processing</span>
</div>
</div>
</div>
<div class="model-metrics">
<div class="metric">
<div class="metric-value">Training</div>
<div class="metric-label">Status</div>
</div>
<div class="metric">
<div class="metric-value">Multimodal</div>
<div class="metric-label">Type</div>
</div>
</div>
</div>
</div>
</div>
<!-- Model Comparison -->
<div class="models-comparison">
<h3>Choose Your Model</h3>
<div class="comparison-table">
<div class="table-header">
<div class="header-cell feature-col">Feature</div>
<div class="header-cell model-col jan-v1">Jan V1</div>
<div class="header-cell model-col jan-nano">Jan Nano</div>
<div class="header-cell model-col lucy">Lucy</div>
</div>
<div class="table-row">
<div class="table-cell feature-col">Use Case</div>
<div class="table-cell model-col">General AI</div>
<div class="table-cell model-col">Research & Mobile</div>
<div class="table-cell model-col">Multimodal AI</div>
</div>
<div class="table-row">
<div class="table-cell feature-col">Status</div>
<div class="table-cell model-col">
<div class="status-indicator active">Production</div>
</div>
<div class="table-cell model-col">
<div class="status-indicator beta">Beta</div>
</div>
<div class="table-cell model-col">
<div class="status-indicator coming">Coming</div>
</div>
</div>
<div class="table-row">
<div class="table-cell feature-col">Parameters</div>
<div class="table-cell model-col">7B - 70B</div>
<div class="table-cell model-col">4B</div>
<div class="table-cell model-col">TBD</div>
</div>
<div class="table-row">
<div class="table-cell feature-col">RAM Required</div>
<div class="table-cell model-col">8GB - 64GB</div>
<div class="table-cell model-col">6GB - 8GB</div>
<div class="table-cell model-col">TBD</div>
</div>
<div class="table-row">
<div class="table-cell feature-col">Best For</div>
<div class="table-cell model-col">Coding, Reasoning</div>
<div class="table-cell model-col">Research, Mobile</div>
<div class="table-cell model-col">Vision, Documents</div>
</div>
</div>
</div>
</div>
</section>
<style>
@import '/src/styles/products-models.css';
.robot-smile {
position: absolute;
bottom: 8px;
left: 50%;
transform: translateX(-50%);
width: 15px;
height: 8px;
border: 3px solid var(--dark-text);
border-top: none;
border-radius: 0 0 12px 12px;
}
/* Nerdy V1 Robot Styles */
.robot-glasses {
display: flex;
align-items: center;
justify-content: center;
padding: 12px 8px;
position: relative;
}
.glasses-frame {
width: 24px;
height: 24px;
border: 3px solid var(--dark-text);
border-radius: 50%;
background: rgba(255, 255, 255, 0.8);
display: flex;
align-items: center;
justify-content: center;
}
.glasses-bridge {
width: 8px;
height: 2px;
background: var(--dark-text);
margin: 0 -2px;
}
.robot-eye.nerdy {
width: 8px;
height: 8px;
animation: nerdyBlink 5s infinite;
}
.robot-thinking-bubbles {
position: absolute;
top: -40px;
right: -20px;
animation: bubbleFloat 4s ease-in-out infinite;
}
.bubble {
position: absolute;
background: white;
border: 2px solid var(--dark-text);
border-radius: 50%;
}
.bubble.small {
width: 8px;
height: 8px;
bottom: 0;
left: 0;
}
.bubble.medium {
width: 12px;
height: 12px;
bottom: 10px;
left: -5px;
}
.bubble.large {
width: 30px;
height: 30px;
bottom: 25px;
left: -15px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.robot-pocket-protector {
position: absolute;
top: 10px;
left: 10px;
background: white;
border: 2px solid var(--dark-text);
padding: 4px;
border-radius: 4px;
display: flex;
gap: 2px;
}
.pen {
width: 3px;
height: 15px;
background: var(--primary-blue);
border-radius: 1px;
}
.calculator {
width: 15px;
height: 15px;
background: var(--dark-text);
color: white;
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 2px;
}
/* Research Nano Robot Styles */
.robot-eye.scanning {
animation: scanEyes 2s linear infinite;
}
.robot-scanner.active {
position: absolute;
top: -20px;
left: 50%;
transform: translateX(-50%);
width: 60px;
height: 40px;
}
.scanner-beam {
position: absolute;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, var(--soft-green), transparent);
animation: beamScan 3s linear infinite;
}
.scanner-grid {
position: absolute;
width: 100%;
height: 100%;
background-image:
repeating-linear-gradient(0deg, transparent, transparent 4px, var(--soft-green) 4px, var(--soft-green) 5px),
repeating-linear-gradient(90deg, transparent, transparent 4px, var(--soft-green) 4px, var(--soft-green) 5px);
opacity: 0.3;
}
.robot-research-goggles {
position: absolute;
top: 8px;
left: -5px;
right: -5px;
height: 30px;
}
.goggle-strap {
position: absolute;
top: 15px;
left: -10px;
right: -10px;
height: 3px;
background: var(--dark-text);
z-index: -1;
}
.research-display.active {
animation: dataFlow 2s ease-in-out infinite;
}
.display-wave {
height: 2px;
background: var(--soft-green);
margin: 2px 0;
border-radius: 1px;
animation: waveform 1s ease-in-out infinite;
}
.display-wave:nth-child(2) { animation-delay: 0.2s; }
.display-wave:nth-child(3) { animation-delay: 0.4s; }
.robot-lab-coat {
position: absolute;
bottom: 0;
left: -5px;
right: -5px;
height: 40px;
background: white;
border: 2px solid var(--dark-text);
border-radius: 0 0 10px 10px;
}
.coat-collar {
position: absolute;
top: -2px;
left: 50%;
transform: translateX(-50%);
width: 30px;
height: 10px;
background: white;
border: 2px solid var(--dark-text);
border-bottom: none;
clip-path: polygon(0 0, 30% 0, 50% 100%, 70% 0, 100% 0, 100% 100%, 0 100%);
}
.coat-buttons {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 15px;
align-items: center;
}
.coat-buttons .button {
width: 6px;
height: 6px;
background: var(--dark-text);
border-radius: 50%;
}
/* Dreamy Lucy Robot Styles */
.robot-head.dreamy {
background: linear-gradient(135deg, var(--light-purple), var(--soft-pink));
animation: dreamFloat 6s ease-in-out infinite;
}
.robot-eye.dreaming {
animation: dreamingEyes 4s ease-in-out infinite;
}
.robot-dream-cloud {
position: absolute;
top: -50px;
right: -40px;
width: 80px;
height: 60px;
background: white;
border: 2px solid var(--dark-text);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
animation: cloudFloat 5s ease-in-out infinite;
}
.robot-dream-cloud::before,
.robot-dream-cloud::after {
content: '';
position: absolute;
background: white;
border: 2px solid var(--dark-text);
border-radius: 50%;
}
.robot-dream-cloud::before {
width: 30px;
height: 30px;
bottom: -10px;
left: 10px;
}
.robot-dream-cloud::after {
width: 20px;
height: 20px;
bottom: -15px;
left: 30px;
}
.dream-content {
display: flex;
gap: 5px;
z-index: 1;
}
.dream-emoji {
font-size: 14px;
animation: emojiRotate 3s linear infinite;
}
.dream-emoji:nth-child(2) { animation-delay: 1s; }
.dream-emoji:nth-child(3) { animation-delay: 2s; }
.robot-sleep-cap {
position: absolute;
top: -15px;
left: 50%;
transform: translateX(-50%);
width: 40px;
height: 30px;
background: var(--soft-pink);
border: 2px solid var(--dark-text);
border-radius: 20px 20px 0 0;
clip-path: polygon(0 100%, 10% 20%, 30% 10%, 50% 15%, 70% 5%, 90% 20%, 100% 100%);
}
.cap-pom-pom {
position: absolute;
top: -10px;
right: 0;
width: 15px;
height: 15px;
background: white;
border: 2px solid var(--dark-text);
border-radius: 50%;
}
.robot-pajamas {
position: absolute;
inset: 10px;
background: linear-gradient(45deg, #e8d5ff 25%, #fce7f3 25%, #fce7f3 50%, #e8d5ff 50%, #e8d5ff 75%, #fce7f3 75%);
background-size: 20px 20px;
border-radius: 8px;
opacity: 0.5;
}
.pajama-pattern {
position: relative;
width: 100%;
height: 100%;
}
.star, .moon {
position: absolute;
font-size: 12px;
}
.star:nth-child(1) { top: 20%; left: 30%; }
.star:nth-child(2) { bottom: 30%; right: 20%; }
.moon { top: 50%; left: 50%; transform: translate(-50%, -50%); }
.robot-badge.dreamy {
background: linear-gradient(135deg, var(--light-purple), var(--soft-pink));
color: white;
}
.robot-teddy-bear {
position: absolute;
bottom: 10px;
right: -15px;
font-size: 20px;
animation: bearHug 4s ease-in-out infinite;
}
/* Animations */
@keyframes nerdyBlink {
0%, 90%, 100% { transform: scale(1); }
95% { transform: scaleY(0.1); }
}
@keyframes bubbleFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
@keyframes scanEyes {
0%, 100% { background: var(--dark-text); }
50% { background: var(--soft-green); box-shadow: 0 0 10px var(--soft-green); }
}
@keyframes beamScan {
0% { top: 0; opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { top: 100%; opacity: 0; }
}
@keyframes waveform {
0%, 100% { transform: scaleY(1); }
50% { transform: scaleY(2); }
}
@keyframes dreamFloat {
0%, 100% { transform: translateY(0) rotate(-2deg); }
50% { transform: translateY(-10px) rotate(2deg); }
}
@keyframes cloudFloat {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
@keyframes dreamingEyes {
0%, 100% { height: 2px; }
50% { height: 2px; transform: scaleX(1.2); }
}
@keyframes emojiRotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes bearHug {
0%, 100% { transform: rotate(-10deg); }
50% { transform: rotate(10deg) scale(1.1); }
}
@keyframes dataFlow {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Add interactive hover effects for model robots
const modelRobots = document.querySelectorAll('.model-robot');
modelRobots.forEach(robot => {
robot.addEventListener('mouseenter', () => {
robot.style.animation = 'bounce 0.6s ease-in-out';
setTimeout(() => {
robot.style.animation = '';
}, 600);
});
});
// Add click interactions for capability items
const capabilities = document.querySelectorAll('.capability');
capabilities.forEach(capability => {
capability.addEventListener('click', () => {
if (!capability.classList.contains('coming')) {
capability.style.transform = 'scale(0.95)';
setTimeout(() => {
capability.style.transform = '';
}, 150);
}
});
});
// Animate model cards when they come into view
const observerOptions = {
threshold: 0.2,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.animation = 'fadeInUp 0.8s ease-out forwards';
}
});
}, observerOptions);
const modelCards = document.querySelectorAll('.model-card');
modelCards.forEach(card => {
observer.observe(card);
});
// Add comparison table row hover effects
const tableRows = document.querySelectorAll('.table-row');
tableRows.forEach(row => {
row.addEventListener('mouseenter', () => {
const cells = row.querySelectorAll('.table-cell');
cells.forEach(cell => {
cell.style.backgroundColor = 'var(--light-blue)';
});
});
row.addEventListener('mouseleave', () => {
const cells = row.querySelectorAll('.table-cell');
cells.forEach(cell => {
cell.style.backgroundColor = 'white';
});
});
});
});
</script>

File diff suppressed because it is too large Load Diff

View File

@ -1,528 +0,0 @@
---
// ProductsPrinciples.astro - Why Jan is different comparison
---
<section id="principles" class="products-section principles-section">
<div class="container">
<div class="section-header">
<div class="section-badge">
<div class="badge-robot">
<div class="badge-robot-head"></div>
<div class="badge-robot-body">Why</div>
</div>
<span>Why Jan is Different</span>
</div>
<h2 class="section-title">What Makes Jan Different</h2>
<p class="section-description">
Most AI is just a wrapper around someone else's models. Jan is different.
We build the models, control the infrastructure, and integrate the tools.
</p>
</div>
<!-- Main Comparison -->
<div class="main-comparison">
<div class="comparison-sides">
<!-- Other AI Assistants -->
<div class="comparison-side other-ai">
<div class="side-header">
<div class="side-robot other-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye corporate"></div>
<div class="robot-eye corporate"></div>
</div>
<div class="robot-corporate-hat">
<div class="hat-logo">$</div>
</div>
</div>
<div class="robot-body">
<div class="robot-tie">
<div class="tie-pattern"></div>
</div>
<div class="robot-briefcase">
<div class="briefcase-lock"></div>
</div>
</div>
<div class="robot-chains">
<div class="chain-link"></div>
<div class="chain-link"></div>
<div class="chain-link"></div>
</div>
</div>
<h3>Other AI Assistants</h3>
<p>Subscription-based, cloud-only solutions</p>
</div>
<div class="side-features">
<div class="feature-item limitation">
<div class="feature-icon wrapper"></div>
<div class="feature-content">
<h4>API Wrappers</h4>
<p>Just interfaces around Claude/GPT models</p>
</div>
</div>
<div class="feature-item limitation">
<div class="feature-icon cloud-only"></div>
<div class="feature-content">
<h4>Cloud Only</h4>
<p>Your data travels to their servers</p>
</div>
</div>
<div class="feature-item limitation">
<div class="feature-icon subscription"></div>
<div class="feature-content">
<h4>Subscription Forever</h4>
<p>Monthly fees that never end</p>
</div>
</div>
<div class="feature-item limitation">
<div class="feature-icon control"></div>
<div class="feature-content">
<h4>Their Rules</h4>
<p>Limited by their policies and restrictions</p>
</div>
</div>
</div>
</div>
<!-- VS Divider -->
<div class="vs-divider">
<div class="vs-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye vs-eye"></div>
<div class="robot-eye vs-eye"></div>
</div>
</div>
<div class="robot-body">
<div class="vs-text">VS</div>
</div>
<div class="robot-lightning">
<div class="lightning-bolt"></div>
</div>
</div>
</div>
<!-- Jan -->
<div class="comparison-side jan-side">
<div class="side-header">
<div class="side-robot jan-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye friendly"></div>
<div class="robot-eye friendly"></div>
</div>
<div class="robot-smile"></div>
</div>
<div class="robot-body">
<div class="robot-heart">
<div class="heart-beat"></div>
</div>
<div class="robot-shield">
<div class="shield-lock"></div>
</div>
</div>
<div class="robot-freedom">
<div class="freedom-wings">
<div class="wing left-wing"></div>
<div class="wing right-wing"></div>
</div>
</div>
</div>
<h3>Jan</h3>
<p>Open, self-hostable, privacy-first AI</p>
</div>
<div class="side-features">
<div class="feature-item advantage">
<div class="feature-icon own-models"></div>
<div class="feature-content">
<h4>Our Own Models</h4>
<p>Purpose-built, optimized for your needs</p>
</div>
</div>
<div class="feature-item advantage">
<div class="feature-icon privacy-first"></div>
<div class="feature-content">
<h4>Your Data Stays Yours</h4>
<p>Local processing, complete privacy</p>
</div>
</div>
<div class="feature-item advantage">
<div class="feature-icon free-local"></div>
<div class="feature-content">
<h4>Free Locally</h4>
<p>No subscriptions for local usage</p>
</div>
</div>
<div class="feature-item advantage">
<div class="feature-icon your-rules"></div>
<div class="feature-content">
<h4>Your Rules</h4>
<p>Self-host and control everything</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Detailed Comparison Table -->
<div class="detailed-comparison">
<h3>Feature Comparison</h3>
<div class="comparison-table">
<div class="table-header">
<div class="header-cell feature-col">Feature</div>
<div class="header-cell other-col">Other AI Assistants</div>
<div class="header-cell jan-col">Jan</div>
</div>
<div class="table-row models-row">
<div class="table-cell feature-col">
<div class="feature-robot models-feature">
<div class="robot-mini-head"></div>
<div class="robot-mini-body"></div>
</div>
<span>Models</span>
</div>
<div class="table-cell other-col">
<div class="limitation-indicator">Wrapper around Claude/GPT</div>
</div>
<div class="table-cell jan-col">
<div class="advantage-indicator">Our own models + others</div>
</div>
</div>
<div class="table-row privacy-row">
<div class="table-cell feature-col">
<div class="feature-robot privacy-feature">
<div class="robot-mini-head"></div>
<div class="robot-mini-body"></div>
</div>
<span>Privacy</span>
</div>
<div class="table-cell other-col">
<div class="limitation-indicator">Your data on their servers</div>
</div>
<div class="table-cell jan-col">
<div class="advantage-indicator">Your data stays yours</div>
</div>
</div>
<div class="table-row deployment-row">
<div class="table-cell feature-col">
<div class="feature-robot deployment-feature">
<div class="robot-mini-head"></div>
<div class="robot-mini-body"></div>
</div>
<span>Deployment</span>
</div>
<div class="table-cell other-col">
<div class="limitation-indicator">Cloud only</div>
</div>
<div class="table-cell jan-col">
<div class="advantage-indicator">Local, self-hosted, or cloud</div>
</div>
</div>
<div class="table-row cost-row">
<div class="table-cell feature-col">
<div class="feature-robot cost-feature">
<div class="robot-mini-head"></div>
<div class="robot-mini-body"></div>
</div>
<span>Cost</span>
</div>
<div class="table-cell other-col">
<div class="limitation-indicator">Subscription forever</div>
</div>
<div class="table-cell jan-col">
<div class="advantage-indicator">Free locally, pay for cloud</div>
</div>
</div>
<div class="table-row control-row">
<div class="table-cell feature-col">
<div class="feature-robot control-feature">
<div class="robot-mini-head"></div>
<div class="robot-mini-body"></div>
</div>
<span>Control</span>
</div>
<div class="table-cell other-col">
<div class="limitation-indicator">Their rules, their limits</div>
</div>
<div class="table-cell jan-col">
<div class="advantage-indicator">Your infrastructure, your rules</div>
</div>
</div>
</div>
</div>
<!-- Philosophy Cards -->
<div class="philosophy-cards">
<h3>Our Philosophy</h3>
<div class="cards-grid">
<div class="philosophy-card models-card">
<div class="card-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye"></div>
<div class="robot-eye"></div>
</div>
<div class="robot-brain">
<div class="brain-core"></div>
</div>
</div>
<div class="robot-body">
<div class="model-display">
<div class="model-layer"></div>
<div class="model-layer"></div>
<div class="model-layer"></div>
</div>
</div>
</div>
<div class="card-content">
<div class="card-icon our-models"></div>
<h4>Our Models</h4>
<p>Trained by us, optimized for your use cases, not subscription revenue. Real AI, not API wrappers.</p>
</div>
</div>
<div class="philosophy-card infrastructure-card">
<div class="card-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye"></div>
<div class="robot-eye"></div>
</div>
<div class="robot-home">
<div class="home-roof"></div>
<div class="home-door"></div>
</div>
</div>
<div class="robot-body">
<div class="infrastructure-display">
<div class="server-rack"></div>
<div class="connection-lines">
<div class="line"></div>
<div class="line"></div>
</div>
</div>
</div>
</div>
<div class="card-content">
<div class="card-icon your-infrastructure"></div>
<h4>Your Infrastructure</h4>
<p>Run locally for privacy, or cloud when you need power. You choose where your data lives.</p>
</div>
</div>
<div class="philosophy-card tools-card">
<div class="card-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye"></div>
<div class="robot-eye"></div>
</div>
<div class="robot-tools-display">
<div class="tool-wrench"></div>
<div class="tool-gear"></div>
</div>
</div>
<div class="robot-body">
<div class="automation-display">
<div class="automation-flow">
<div class="flow-dot"></div>
<div class="flow-dot"></div>
<div class="flow-dot"></div>
</div>
</div>
</div>
</div>
<div class="card-content">
<div class="card-icon real-tools"></div>
<h4>Real Tools</h4>
<p>Not just chat, but automation that actually gets things done. Integrated, not bolted-on.</p>
</div>
</div>
</div>
</div>
<!-- Call to Action -->
<div class="principles-cta">
<div class="cta-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye confident"></div>
<div class="robot-eye confident"></div>
</div>
<div class="robot-confident-smile"></div>
</div>
<div class="robot-body">
<div class="robot-badge">
<span>Open AI</span>
</div>
</div>
<div class="robot-cape">
<div class="cape-flow"></div>
</div>
</div>
<div class="cta-content">
<h3>Ready for AI that respects your choices?</h3>
<p>Run it locally for privacy, connect to cloud for power, or self-host for both.</p>
<div class="cta-buttons">
<a href="#" class="btn-primary">Download Jan Desktop</a>
<a href="#" class="btn-secondary">Try jan.ai Beta</a>
</div>
</div>
</div>
</div>
</section>
<style>
@import '/src/styles/products-principles.css';
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Comparison robot animations
const comparisonRobots = document.querySelectorAll('.side-robot, .vs-robot');
comparisonRobots.forEach(robot => {
robot.addEventListener('mouseenter', () => {
if (robot.classList.contains('other-robot')) {
robot.style.animation = 'corporateShake 0.8s ease-in-out';
} else if (robot.classList.contains('jan-robot')) {
robot.style.animation = 'friendlyBounce 0.8s ease-in-out';
} else if (robot.classList.contains('vs-robot')) {
robot.style.animation = 'vsFlash 0.6s ease-in-out';
}
setTimeout(() => {
robot.style.animation = '';
}, 800);
});
});
// Table row interactions
const tableRows = document.querySelectorAll('.table-row');
tableRows.forEach(row => {
row.addEventListener('mouseenter', () => {
// Highlight the entire row
const cells = row.querySelectorAll('.table-cell');
cells.forEach(cell => {
if (cell.classList.contains('jan-col')) {
cell.style.background = 'var(--soft-green)';
} else if (cell.classList.contains('other-col')) {
cell.style.background = 'var(--warm-yellow)';
}
});
// Animate the feature robot
const featureRobot = row.querySelector('.feature-robot');
if (featureRobot) {
featureRobot.style.animation = 'featureBounce 0.4s ease-in-out';
}
});
row.addEventListener('mouseleave', () => {
const cells = row.querySelectorAll('.table-cell');
cells.forEach(cell => {
cell.style.background = 'white';
});
const featureRobot = row.querySelector('.feature-robot');
if (featureRobot) {
featureRobot.style.animation = '';
}
});
});
// Philosophy cards hover effects
const philosophyCards = document.querySelectorAll('.philosophy-card');
philosophyCards.forEach(card => {
card.addEventListener('mouseenter', () => {
const cardRobot = card.querySelector('.card-robot');
if (cardRobot) {
cardRobot.style.animation = 'cardRobotFloat 0.8s ease-in-out';
}
card.style.transform = 'translateY(-8px) scale(1.02)';
});
card.addEventListener('mouseleave', () => {
const cardRobot = card.querySelector('.card-robot');
if (cardRobot) {
cardRobot.style.animation = '';
}
card.style.transform = 'translateY(0) scale(1)';
});
});
// Scroll-triggered animations
const observerOptions = {
threshold: 0.2,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
if (entry.target.classList.contains('main-comparison')) {
// Animate comparison sides
const sides = entry.target.querySelectorAll('.comparison-side');
sides.forEach((side, index) => {
setTimeout(() => {
side.style.animation = 'slideInComparison 0.8s ease-out forwards';
}, index * 200);
});
} else if (entry.target.classList.contains('philosophy-cards')) {
// Animate philosophy cards
const cards = entry.target.querySelectorAll('.philosophy-card');
cards.forEach((card, index) => {
setTimeout(() => {
card.style.animation = 'fadeInUp 0.6s ease-out forwards';
}, index * 150);
});
}
}
});
}, observerOptions);
// Observe key sections
const mainComparison = document.querySelector('.main-comparison');
const philosophyCardsContainer = document.querySelector('.philosophy-cards');
if (mainComparison) observer.observe(mainComparison);
if (philosophyCardsContainer) observer.observe(philosophyCardsContainer);
// CTA robot interaction
const ctaRobot = document.querySelector('.cta-robot');
if (ctaRobot) {
ctaRobot.addEventListener('click', () => {
ctaRobot.style.animation = 'ctaRobotCelebrate 1s ease-in-out';
setTimeout(() => {
ctaRobot.style.animation = '';
}, 1000);
});
}
// Advantage/limitation indicators animation
const indicators = document.querySelectorAll('.advantage-indicator, .limitation-indicator');
indicators.forEach(indicator => {
indicator.addEventListener('mouseenter', () => {
if (indicator.classList.contains('advantage-indicator')) {
indicator.style.animation = 'advantagePulse 0.4s ease-in-out';
} else {
indicator.style.animation = 'limitationShake 0.4s ease-in-out';
}
});
indicator.addEventListener('mouseleave', () => {
indicator.style.animation = '';
});
});
});
</script>

View File

@ -1,763 +0,0 @@
---
// ProductsRoadmap.astro - Interactive release roadmap database
---
<section id="roadmap" class="products-section roadmap-section">
<div class="container">
<div class="section-header">
<div class="section-badge">
<div class="badge-robot">
<div class="badge-robot-head"></div>
<div class="badge-robot-body">Map</div>
</div>
<span>Release Roadmap</span>
</div>
<h2 class="section-title">Development Timeline</h2>
<p class="section-description">
Detailed roadmap with release versions, target dates, and comprehensive feature breakdowns.
Track our progress as we build the future of AI.
</p>
</div>
<!-- Roadmap Overview -->
<div class="roadmap-overview">
<div class="timeline-stats">
<div class="stat-card">
<div class="stat-robot released-robot">
<div class="robot-head"></div>
<div class="robot-body">
<div class="success-check"></div>
</div>
</div>
<div class="stat-content">
<div class="stat-number">3</div>
<div class="stat-label">Released</div>
</div>
</div>
<div class="stat-card">
<div class="stat-robot development-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye working"></div>
<div class="robot-eye working"></div>
</div>
</div>
<div class="robot-body">
<div class="work-indicator">
<div class="work-dot"></div>
<div class="work-dot"></div>
<div class="work-dot"></div>
</div>
</div>
</div>
<div class="stat-content">
<div class="stat-number">2</div>
<div class="stat-label">In Development</div>
</div>
</div>
<div class="stat-card">
<div class="stat-robot planned-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye planning"></div>
<div class="robot-eye planning"></div>
</div>
</div>
<div class="robot-body">
<div class="planning-board">
<div class="plan-item"></div>
<div class="plan-item"></div>
</div>
</div>
</div>
<div class="stat-content">
<div class="stat-number">4</div>
<div class="stat-label">Planned</div>
</div>
</div>
</div>
</div>
<!-- Interactive Roadmap Database -->
<div class="roadmap-database">
<div class="database-header">
<div class="database-title">
<div class="title-robot">
<div class="robot-head"></div>
<div class="robot-body">DB</div>
</div>
<h3>Release Database</h3>
</div>
<div class="database-controls">
<button class="control-btn expand-all" data-action="expand-all">
<span>Expand All</span>
</button>
<button class="control-btn collapse-all" data-action="collapse-all">
<span>Collapse All</span>
</button>
</div>
</div>
<div class="database-table">
<div class="table-header">
<div class="header-cell version-col">Release Version</div>
<div class="header-cell date-col">Target Date</div>
<div class="header-cell status-col">Status</div>
<div class="header-cell expand-col">Details</div>
</div>
<!-- Released Versions -->
<div class="roadmap-row released" data-version="v0.6.7">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot released-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">✓</div>
</div>
<div class="version-info">
<div class="version-number">v0.6.7</div>
<div class="version-name">Web Search</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge released">Released</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator released">
<div class="status-dot"></div>
<span>Live</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>User Stories</h4>
<ul>
<li>As a user, I want to search the web directly from Jan chat for real-time information</li>
<li>As a developer, I want better API documentation for integration</li>
<li>As a researcher, I want source attribution for all search results</li>
</ul>
</div>
<div class="detail-section">
<h4>New Features</h4>
<ul>
<li>Privacy-respecting web search integration</li>
<li>Multiple search engine support</li>
<li>Improved model downloading experience</li>
<li>Enhanced error handling and user feedback</li>
</ul>
</div>
<div class="detail-section">
<h4>Documentation</h4>
<ul>
<li>Web Search API documentation</li>
<li>Privacy policy updates</li>
<li>Search configuration guide</li>
</ul>
</div>
</div>
</div>
</div>
<div class="roadmap-row released" data-version="v0.6.5">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot released-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">✓</div>
</div>
<div class="version-info">
<div class="version-number">v0.6.5</div>
<div class="version-name">Desktop Stability</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge released">Released</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator released">
<div class="status-dot"></div>
<span>Live</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>Improvements</h4>
<ul>
<li>Enhanced memory management for large models</li>
<li>Improved GPU utilization</li>
<li>Better cross-platform compatibility</li>
</ul>
</div>
<div class="detail-section">
<h4>Bug Fixes</h4>
<ul>
<li>Fixed model loading crashes on Windows</li>
<li>Resolved memory leaks in long conversations</li>
<li>Fixed UI freezing during model downloads</li>
</ul>
</div>
</div>
</div>
</div>
<!-- In Development -->
<div class="roadmap-row development" data-version="v0.7.0">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot development-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">⚡</div>
</div>
<div class="version-info">
<div class="version-number">v0.7.0</div>
<div class="version-name">Deep Research</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge development">January 2025</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator development">
<div class="status-dot"></div>
<span>Building</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>User Stories</h4>
<ul>
<li>As a researcher, I want to conduct deep research with multiple sources and citations</li>
<li>As a user, I want Jan Nano to work seamlessly on mobile devices</li>
<li>As a team lead, I want to preview jan.ai for my organization</li>
</ul>
</div>
<div class="detail-section">
<h4>New Features</h4>
<ul>
<li>Deep research capabilities with multi-source analysis</li>
<li>jan.ai web platform beta launch</li>
<li>Improved Jan Nano performance and mobile optimization</li>
<li>Citation management and research reports</li>
</ul>
</div>
<div class="detail-section">
<h4>Documentation</h4>
<ul>
<li>Research methodology guide</li>
<li>jan.ai platform documentation</li>
<li>Mobile optimization best practices</li>
</ul>
</div>
</div>
</div>
</div>
<div class="roadmap-row development" data-version="v0.8.0">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot development-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">⚡</div>
</div>
<div class="version-info">
<div class="version-number">v0.8.0</div>
<div class="version-name">Browser Automation</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge development">March 2025</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator development">
<div class="status-dot"></div>
<span>Building</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>User Stories</h4>
<ul>
<li>As a user, I want Jan to automate web tasks for me safely and efficiently</li>
<li>As a business user, I want to automate repetitive web workflows</li>
<li>As a developer, I want browser automation APIs for custom integrations</li>
</ul>
</div>
<div class="detail-section">
<h4>New Features</h4>
<ul>
<li>Browser automation capabilities (Beta)</li>
<li>Form filling and data extraction</li>
<li>Website navigation and interaction</li>
<li>Safety policies and user confirmation flows</li>
</ul>
</div>
<div class="detail-section">
<h4>Documentation</h4>
<ul>
<li>Browser automation safety guide</li>
<li>Web scraping best practices</li>
<li>API reference for automation tools</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Planned Releases -->
<div class="roadmap-row planned" data-version="v0.9.0">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot planned-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">📱</div>
</div>
<div class="version-info">
<div class="version-number">v0.9.0</div>
<div class="version-name">Mobile Launch</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge planned">Q1 2025</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator planned">
<div class="status-dot"></div>
<span>Planned</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>User Stories</h4>
<ul>
<li>As a mobile user, I want Jan AI available on my iOS/Android device</li>
<li>As a commuter, I want to seamlessly switch between desktop and mobile</li>
<li>As a privacy-conscious user, I want local AI on my phone</li>
</ul>
</div>
<div class="detail-section">
<h4>New Features</h4>
<ul>
<li>iOS and Android mobile applications</li>
<li>Three adaptive modes (Desktop, Server, Local)</li>
<li>Voice-first interface</li>
<li>Cross-device synchronization</li>
<li>Jan Nano on-device processing</li>
</ul>
</div>
<div class="detail-section">
<h4>Documentation</h4>
<ul>
<li>Mobile setup and configuration guide</li>
<li>Voice interaction best practices</li>
<li>Device syncing tutorial</li>
</ul>
</div>
</div>
</div>
</div>
<div class="roadmap-row planned" data-version="v1.0.0">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot planned-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">🏢</div>
</div>
<div class="version-info">
<div class="version-number">v1.0.0</div>
<div class="version-name">Server Edition</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge planned">Q2 2025</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator planned">
<div class="status-dot"></div>
<span>Planned</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>User Stories</h4>
<ul>
<li>As an IT admin, I want to deploy Jan for my entire organization</li>
<li>As a team lead, I want centralized AI with team collaboration features</li>
<li>As a CTO, I want enterprise-grade security and compliance</li>
</ul>
</div>
<div class="detail-section">
<h4>New Features</h4>
<ul>
<li>Multi-user server deployment</li>
<li>Enterprise authentication (SSO, LDAP)</li>
<li>Team collaboration and shared conversations</li>
<li>Docker and Kubernetes deployment options</li>
<li>Admin dashboard and user management</li>
</ul>
</div>
<div class="detail-section">
<h4>Documentation</h4>
<ul>
<li>Enterprise deployment guide</li>
<li>Security and compliance documentation</li>
<li>Admin management tutorials</li>
</ul>
</div>
</div>
</div>
</div>
<div class="roadmap-row planned" data-version="v1.1.0">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot planned-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">🤖</div>
</div>
<div class="version-info">
<div class="version-number">v1.1.0</div>
<div class="version-name">AI Agents</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge planned">Q1 2026</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator planned">
<div class="status-dot"></div>
<span>Planned</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>User Stories</h4>
<ul>
<li>As a user, I want autonomous agents to handle complex multi-step tasks</li>
<li>As a business owner, I want AI that can coordinate multiple tools automatically</li>
<li>As a power user, I want to create custom agent workflows</li>
</ul>
</div>
<div class="detail-section">
<h4>New Features</h4>
<ul>
<li>Autonomous AI agents</li>
<li>Multi-step task planning and execution</li>
<li>Tool orchestration and coordination</li>
<li>Goal-oriented intelligent reasoning</li>
<li>Custom agent workflow builder</li>
</ul>
</div>
<div class="detail-section">
<h4>Documentation</h4>
<ul>
<li>Agent development guide</li>
<li>Workflow automation tutorials</li>
<li>Safety and oversight best practices</li>
</ul>
</div>
</div>
</div>
</div>
<div class="roadmap-row planned" data-version="v1.2.0">
<div class="row-main">
<div class="row-cell version-col">
<div class="version-robot planned-version">
<div class="robot-mini-head"></div>
<div class="robot-mini-body">👁️</div>
</div>
<div class="version-info">
<div class="version-number">v1.2.0</div>
<div class="version-name">Lucy Multimodal</div>
</div>
</div>
<div class="row-cell date-col">
<div class="date-badge planned">Q2 2025</div>
</div>
<div class="row-cell status-col">
<div class="status-indicator planned">
<div class="status-dot"></div>
<span>Planned</span>
</div>
</div>
<div class="row-cell expand-col">
<button class="expand-btn" data-expanded="false">
<div class="expand-icon">+</div>
</button>
</div>
</div>
<div class="row-details">
<div class="details-content">
<div class="detail-section">
<h4>User Stories</h4>
<ul>
<li>As a content creator, I want AI that can understand and process images</li>
<li>As a researcher, I want to analyze documents with both text and visuals</li>
<li>As a designer, I want AI that can help with visual content creation</li>
</ul>
</div>
<div class="detail-section">
<h4>New Features</h4>
<ul>
<li>Lucy multimodal model release</li>
<li>Image understanding and analysis</li>
<li>Document processing with OCR</li>
<li>Visual reasoning capabilities</li>
<li>Audio processing (planned)</li>
</ul>
</div>
<div class="detail-section">
<h4>Documentation</h4>
<ul>
<li>Multimodal AI usage guide</li>
<li>Image processing tutorials</li>
<li>Visual reasoning examples</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Roadmap CTA -->
<div class="roadmap-cta">
<div class="cta-robot">
<div class="robot-head">
<div class="robot-eyes">
<div class="robot-eye excited"></div>
<div class="robot-eye excited"></div>
</div>
<div class="robot-smile-big"></div>
</div>
<div class="robot-body">
<div class="robot-progress-wheel">
<div class="progress-segment"></div>
<div class="progress-segment"></div>
<div class="progress-segment"></div>
<div class="progress-segment active"></div>
</div>
</div>
<div class="robot-arms celebrating">
<div class="arm left-celebrate"></div>
<div class="arm right-celebrate"></div>
</div>
</div>
<div class="cta-content">
<h3>Join Our Journey</h3>
<p>Be part of building the future of AI. Download Jan today and help shape our roadmap.</p>
<div class="cta-buttons">
<a href="#" class="btn-primary">Download Jan Desktop</a>
<a href="#" class="btn-secondary">Follow Our Progress</a>
</div>
</div>
</div>
</div>
</section>
<style>
@import '/src/styles/products-roadmap.css';
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Roadmap row expand/collapse functionality
const expandButtons = document.querySelectorAll('.expand-btn');
const expandAllBtn = document.querySelector('[data-action="expand-all"]');
const collapseAllBtn = document.querySelector('[data-action="collapse-all"]');
expandButtons.forEach(button => {
button.addEventListener('click', () => {
const row = button.closest('.roadmap-row');
const details = row.querySelector('.row-details');
const icon = button.querySelector('.expand-icon');
const isExpanded = button.getAttribute('data-expanded') === 'true';
if (isExpanded) {
// Collapse
details.style.maxHeight = '0';
details.style.opacity = '0';
icon.textContent = '+';
icon.style.transform = 'rotate(0deg)';
button.setAttribute('data-expanded', 'false');
row.classList.remove('expanded');
} else {
// Expand
details.style.maxHeight = details.scrollHeight + 'px';
details.style.opacity = '1';
icon.textContent = '';
icon.style.transform = 'rotate(180deg)';
button.setAttribute('data-expanded', 'true');
row.classList.add('expanded');
// Animate the version robot
const versionRobot = row.querySelector('.version-robot');
if (versionRobot) {
versionRobot.style.animation = 'versionCelebrate 0.6s ease-in-out';
setTimeout(() => {
versionRobot.style.animation = '';
}, 600);
}
}
});
});
// Expand all functionality
expandAllBtn?.addEventListener('click', () => {
expandButtons.forEach(button => {
if (button.getAttribute('data-expanded') === 'false') {
button.click();
}
});
});
// Collapse all functionality
collapseAllBtn?.addEventListener('click', () => {
expandButtons.forEach(button => {
if (button.getAttribute('data-expanded') === 'true') {
button.click();
}
});
});
// Row hover effects
const roadmapRows = document.querySelectorAll('.roadmap-row');
roadmapRows.forEach(row => {
row.addEventListener('mouseenter', () => {
const versionRobot = row.querySelector('.version-robot');
if (versionRobot) {
versionRobot.style.animation = 'versionHover 0.4s ease-in-out';
}
});
row.addEventListener('mouseleave', () => {
const versionRobot = row.querySelector('.version-robot');
if (versionRobot && !row.classList.contains('expanded')) {
versionRobot.style.animation = '';
}
});
});
// Scroll-triggered animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
if (entry.target.classList.contains('roadmap-row')) {
entry.target.style.animation = 'slideInFromLeft 0.6s ease-out forwards';
} else if (entry.target.classList.contains('stat-card')) {
entry.target.style.animation = 'fadeInUp 0.6s ease-out forwards';
}
}
});
}, observerOptions);
// Observe roadmap rows and stat cards
roadmapRows.forEach(row => observer.observe(row));
document.querySelectorAll('.stat-card').forEach(card => observer.observe(card));
// Database controls hover effects
const controlBtns = document.querySelectorAll('.control-btn');
controlBtns.forEach(btn => {
btn.addEventListener('mouseenter', () => {
btn.style.transform = 'translateY(-2px) scale(1.05)';
});
btn.addEventListener('mouseleave', () => {
btn.style.transform = 'translateY(0) scale(1)';
});
});
// CTA robot celebration
const ctaRobot = document.querySelector('.cta-robot');
if (ctaRobot) {
ctaRobot.addEventListener('click', () => {
ctaRobot.style.animation = 'ctaRobotCelebration 1.2s ease-in-out';
setTimeout(() => {
ctaRobot.style.animation = '';
}, 1200);
});
}
// Auto-expand first row for demo
setTimeout(() => {
const firstExpandBtn = document.querySelector('.roadmap-row .expand-btn');
if (firstExpandBtn && firstExpandBtn.getAttribute('data-expanded') === 'false') {
firstExpandBtn.click();
}
}, 500);
// Update timestamp in real-time for current releases
const updateTimestamps = () => {
const now = new Date();
const timeString = now.toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit'
});
document.querySelectorAll('.real-time-stamp').forEach(stamp => {
stamp.textContent = timeString;
});
};
updateTimestamps();
setInterval(updateTimestamps, 60000); // Update every minute
});
</script>

View File

@ -1,628 +0,0 @@
---
// ProductsTOC.astro - Sticky table of contents navigation
---
<div class="products-toc">
<div class="toc-container">
<div class="toc-header">
<div class="toc-robot">
<div class="robot-head"></div>
<div class="robot-body">📋</div>
</div>
<h3>Navigate This Page</h3>
</div>
<nav class="toc-nav" role="navigation" aria-label="Table of Contents">
<ul class="toc-list">
<li class="toc-item">
<a href="#hero" class="toc-link" data-section="hero">
<div class="toc-icon hero-icon"></div>
<span>Product Overview</span>
</a>
</li>
<li class="toc-item">
<a href="#vision" class="toc-link" data-section="vision">
<div class="toc-icon vision-icon"></div>
<span>Product Vision</span>
</a>
</li>
<li class="toc-item">
<a href="#architecture" class="toc-link" data-section="architecture">
<div class="toc-icon architecture-icon"></div>
<span>How Jan Works</span>
</a>
</li>
<li class="toc-item">
<a href="#models" class="toc-link" data-section="models">
<div class="toc-icon models-icon"></div>
<span>AI Models</span>
</a>
</li>
<li class="toc-item">
<a href="#platforms" class="toc-link" data-section="platforms">
<div class="toc-icon platforms-icon"></div>
<span>Platforms</span>
</a>
</li>
<li class="toc-item">
<a href="#tools" class="toc-link" data-section="tools">
<div class="toc-icon tools-icon"></div>
<span>Tools</span>
</a>
</li>
<li class="toc-item">
<a href="#principles" class="toc-link" data-section="principles">
<div class="toc-icon principles-icon"></div>
<span>Why Jan</span>
</a>
</li>
<li class="toc-item">
<a href="#roadmap" class="toc-link" data-section="roadmap">
<div class="toc-icon roadmap-icon"></div>
<span>Roadmap</span>
</a>
</li>
</ul>
</nav>
<div class="toc-progress">
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
<div class="progress-text">
<span class="current-section">Getting Started</span>
</div>
</div>
</div>
<!-- Mobile TOC Toggle -->
<button class="toc-mobile-toggle" aria-label="Toggle Table of Contents">
<div class="toggle-icon">
<span></span>
<span></span>
<span></span>
</div>
</button>
</div>
<style>
.products-toc {
position: fixed;
top: 50%;
right: 2rem;
transform: translateY(-50%);
z-index: 1000;
transition: all 0.3s ease;
}
.toc-container {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border: 2px solid #e2e8f0;
border-radius: 16px;
padding: 1.5rem;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
min-width: 280px;
max-height: 80vh;
overflow-y: auto;
transition: all 0.3s ease;
}
.toc-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid #e2e8f0;
}
.toc-robot {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.toc-robot .robot-head {
width: 20px;
height: 20px;
background: #3b82f6;
border-radius: 6px;
border: 2px solid #1e293b;
}
.toc-robot .robot-body {
font-size: 1rem;
}
.toc-header h3 {
font-size: 1.1rem;
font-weight: 700;
color: #1e293b;
margin: 0;
}
.toc-nav {
margin-bottom: 1.5rem;
}
.toc-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.toc-item {
margin: 0;
}
.toc-link {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem;
border-radius: 10px;
text-decoration: none;
color: #64748b;
font-size: 0.9rem;
font-weight: 500;
transition: all 0.3s ease;
position: relative;
border: 1px solid transparent;
}
.toc-link:hover {
background: #f1f5f9;
color: #3b82f6;
border-color: #e2e8f0;
transform: translateX(4px);
}
.toc-link.active {
background: #3b82f6;
color: white;
border-color: #3b82f6;
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3);
}
.toc-link.active .toc-icon {
background: white;
}
.toc-icon {
width: 24px;
height: 24px;
border-radius: 6px;
border: 2px solid #1e293b;
flex-shrink: 0;
position: relative;
transition: all 0.3s ease;
}
/* Icon variations */
.hero-icon {
background: linear-gradient(135deg, #3b82f6, #1d4ed8);
}
.vision-icon {
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
}
.architecture-icon {
background: linear-gradient(135deg, #06b6d4, #0891b2);
}
.models-icon {
background: linear-gradient(135deg, #ec4899, #db2777);
}
.platforms-icon {
background: linear-gradient(135deg, #22c55e, #16a34a);
}
.tools-icon {
background: linear-gradient(135deg, #f59e0b, #d97706);
}
.principles-icon {
background: linear-gradient(135deg, #ef4444, #dc2626);
}
.roadmap-icon {
background: linear-gradient(135deg, #6366f1, #4f46e5);
}
/* Icon symbols */
.toc-icon::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 8px;
height: 8px;
background: white;
border-radius: 2px;
}
.hero-icon::after {
border-radius: 50%;
}
.vision-icon::after {
width: 6px;
height: 10px;
border-radius: 1px;
}
.architecture-icon::after {
width: 10px;
height: 6px;
}
.models-icon::after {
width: 10px;
height: 10px;
border-radius: 50%;
}
.platforms-icon::after {
width: 8px;
height: 8px;
}
.tools-icon::after {
width: 6px;
height: 6px;
border-radius: 50%;
}
.principles-icon::after {
width: 8px;
height: 8px;
border-radius: 50%;
}
.roadmap-icon::after {
width: 10px;
height: 4px;
border-radius: 2px;
}
/* Progress section */
.toc-progress {
border-top: 1px solid #e2e8f0;
padding-top: 1rem;
}
.progress-bar {
width: 100%;
height: 4px;
background: #e2e8f0;
border-radius: 2px;
overflow: hidden;
margin-bottom: 0.75rem;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
border-radius: 2px;
width: 0%;
transition: width 0.3s ease;
}
.progress-text {
text-align: center;
}
.current-section {
font-size: 0.8rem;
color: #64748b;
font-weight: 500;
}
/* Mobile toggle button */
.toc-mobile-toggle {
display: none;
position: fixed;
top: 2rem;
right: 2rem;
width: 50px;
height: 50px;
background: #3b82f6;
border: none;
border-radius: 50%;
cursor: pointer;
z-index: 1001;
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3);
transition: all 0.3s ease;
}
.toc-mobile-toggle:hover {
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.4);
}
.toggle-icon {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
}
.toggle-icon span {
width: 16px;
height: 2px;
background: white;
border-radius: 1px;
transition: all 0.3s ease;
}
/* Mobile states */
.products-toc.mobile-hidden .toc-container {
transform: translateX(100%);
opacity: 0;
pointer-events: none;
}
.products-toc.mobile-visible .toggle-icon span:nth-child(1) {
transform: rotate(45deg) translate(6px, 6px);
}
.products-toc.mobile-visible .toggle-icon span:nth-child(2) {
opacity: 0;
}
.products-toc.mobile-visible .toggle-icon span:nth-child(3) {
transform: rotate(-45deg) translate(6px, -6px);
}
/* Responsive Design */
@media (max-width: 1280px) {
.products-toc {
right: 1rem;
}
.toc-container {
min-width: 260px;
}
}
@media (max-width: 1024px) {
.products-toc {
top: auto;
bottom: 2rem;
right: 2rem;
transform: none;
}
.toc-container {
min-width: 240px;
max-height: 60vh;
}
.toc-mobile-toggle {
display: flex;
}
.products-toc:not(.mobile-visible) .toc-container {
transform: translateX(100%);
opacity: 0;
pointer-events: none;
}
}
@media (max-width: 768px) {
.toc-mobile-toggle {
width: 45px;
height: 45px;
top: 1.5rem;
right: 1.5rem;
}
.toc-container {
min-width: 220px;
padding: 1.25rem;
}
.toc-link {
padding: 0.65rem;
font-size: 0.85rem;
}
.toc-icon {
width: 20px;
height: 20px;
}
}
@media (max-width: 480px) {
.products-toc {
bottom: 1rem;
right: 1rem;
}
.toc-container {
min-width: 200px;
max-height: 50vh;
}
}
/* High contrast mode */
@media (prefers-contrast: high) {
.toc-container {
border-width: 3px;
background: white;
}
.toc-link {
border-width: 2px;
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.toc-link, .toc-container, .progress-fill, .toc-mobile-toggle, .toggle-icon span {
transition: none;
}
}
/* Scrollbar styling */
.toc-container::-webkit-scrollbar {
width: 6px;
}
.toc-container::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 3px;
}
.toc-container::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 3px;
}
.toc-container::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
const toc = document.querySelector('.products-toc');
const tocLinks = document.querySelectorAll('.toc-link');
const mobileToggle = document.querySelector('.toc-mobile-toggle');
const progressFill = document.querySelector('.progress-fill');
const currentSectionText = document.querySelector('.current-section');
// Mobile toggle functionality
if (mobileToggle) {
mobileToggle.addEventListener('click', () => {
toc?.classList.toggle('mobile-visible');
});
}
// Close TOC when clicking outside on mobile
document.addEventListener('click', (e) => {
if (window.innerWidth <= 1024 && toc && !toc.contains(e.target)) {
toc.classList.remove('mobile-visible');
}
});
// Smooth scrolling for TOC links
tocLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetId = link.getAttribute('href')?.substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
const offset = 100; // Account for fixed headers
const elementPosition = targetElement.getBoundingClientRect().top + window.pageYOffset;
const offsetPosition = elementPosition - offset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
// Close mobile TOC after navigation
if (window.innerWidth <= 1024) {
toc?.classList.remove('mobile-visible');
}
}
});
});
// Scroll progress and active section tracking
const sections = Array.from(document.querySelectorAll('[id]')).filter(el =>
['hero', 'vision', 'architecture', 'models', 'platforms', 'tools', 'principles', 'roadmap'].includes(el.id)
);
const updateProgress = () => {
const scrollTop = window.pageYOffset;
const documentHeight = document.documentElement.scrollHeight - window.innerHeight;
const scrollProgress = Math.min(scrollTop / documentHeight, 1);
if (progressFill) {
progressFill.style.width = `${scrollProgress * 100}%`;
}
};
const updateActiveSection = () => {
const scrollTop = window.pageYOffset + 150; // Offset for better UX
let activeSection = sections[0]; // Default to first section
for (const section of sections) {
if (section.offsetTop <= scrollTop) {
activeSection = section;
} else {
break;
}
}
// Update active TOC link
tocLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${activeSection.id}`) {
link.classList.add('active');
}
});
// Update current section text
if (currentSectionText) {
const sectionNames = {
hero: 'Product Overview',
vision: 'Product Vision',
architecture: 'How Jan Works',
models: 'AI Models',
platforms: 'Platforms',
tools: 'Tools',
principles: 'Why Jan',
roadmap: 'Roadmap'
};
currentSectionText.textContent = sectionNames[activeSection.id] || 'Getting Started';
}
};
// Throttled scroll handler
let ticking = false;
const handleScroll = () => {
if (!ticking) {
requestAnimationFrame(() => {
updateProgress();
updateActiveSection();
ticking = false;
});
ticking = true;
}
};
window.addEventListener('scroll', handleScroll);
// Initial call
updateProgress();
updateActiveSection();
// Handle window resize
window.addEventListener('resize', () => {
if (window.innerWidth > 1024) {
toc?.classList.remove('mobile-visible');
}
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && toc?.classList.contains('mobile-visible')) {
toc.classList.remove('mobile-visible');
}
});
});
</script>

File diff suppressed because it is too large Load Diff

View File

@ -1,810 +0,0 @@
---
// ProductsVision.astro - Product vision and principles section
---
<section id="vision" class="products-section vision-section">
<div class="container">
<div class="section-header">
<div class="section-badge">
<div class="badge-robot">
<div class="badge-robot-head"></div>
<div class="badge-robot-body">Vision</div>
</div>
<span>Product Vision</span>
</div>
<h2 class="section-title">What We're Building</h2>
<p class="section-description">
Jan is evolving from a local AI application to a complete full-stack AI solution that you can self-host.
This includes models, applications, and tools to solve real problems.
</p>
</div>
<!-- Jan Agent Formula -->
<div class="vision-formula">
<div class="formula-container">
<div class="formula-item">
<div class="formula-robot models-robot">
<div class="robot-head"></div>
<div class="robot-body">
</div>
</div>
<div class="formula-label">Jan Models</div>
<div class="formula-desc">Our own AI models optimized for local and private use</div>
</div>
<div class="formula-operator">+</div>
<div class="formula-item">
<div class="formula-robot app-robot">
<div class="robot-head"></div>
<div class="robot-body">
</div>
</div>
<div class="formula-label">Jan Application</div>
<div class="formula-desc">Applications that work across all your devices</div>
</div>
<div class="formula-operator">+</div>
<div class="formula-item">
<div class="formula-robot tools-robot">
<div class="robot-head"></div>
<div class="robot-body">
</div>
</div>
<div class="formula-label">Jan Tools</div>
<div class="formula-desc">Tools that actually get things done</div>
</div>
<div class="formula-equals">=</div>
<div class="formula-result">
<div class="result-robot">
<div class="robot-head crown"></div>
<div class="robot-body">
<div class="result-glow"></div>
</div>
<div class="robot-cape"></div>
</div>
<div class="result-label">Jan Agent</div>
<div class="result-desc">Complete AI ecosystem that you control</div>
</div>
</div>
</div>
<!-- Two Modes Explanation -->
<div class="dual-modes">
<div class="modes-header">
<h3>Two Modes, One Experience</h3>
<p>Users shouldn't need to understand models, APIs, or technical details. Just choose Local for privacy or Cloud for power.</p>
</div>
<div class="modes-grid">
<div class="mode-card local-mode">
<div class="mode-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
</div>
<div class="robot-lock">
<div class="lock-icon"></div>
</div>
</div>
<div class="mode-content">
<h4>Local (Incognito) Mode</h4>
<p>Run AI models entirely on your device, giving you complete privacy with no internet required.</p>
<div class="mode-features">
<div class="feature-item">
<div class="feature-icon privacy"></div>
<span>Complete privacy</span>
</div>
<div class="feature-item">
<div class="feature-icon offline"></div>
<span>No internet required</span>
</div>
<div class="feature-item">
<div class="feature-icon hardware"></div>
<span>Your hardware, your data</span>
</div>
<div class="feature-item">
<div class="feature-icon local"></div>
<span>Offline capable</span>
</div>
</div>
</div>
</div>
<div class="mode-card cloud-mode">
<div class="mode-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
</div>
<div class="robot-signal">
<div class="signal-bars">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
</div>
</div>
<div class="mode-content">
<h4>Cloud Mode</h4>
<p>Connect to more powerful models when needed - either self-hosted or via jan.ai.</p>
<div class="mode-features">
<div class="feature-item">
<div class="feature-icon power"></div>
<span>Powerful models</span>
</div>
<div class="feature-item">
<div class="feature-icon speed"></div>
<span>Faster processing</span>
</div>
<div class="feature-item">
<div class="feature-icon selfhost"></div>
<span>Self-hosted option</span>
</div>
<div class="feature-item">
<div class="feature-icon janai"></div>
<span>jan.ai integration</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Product Principles -->
<div class="product-principles">
<div class="principles-header">
<h3>Our Product Principles</h3>
</div>
<div class="principles-grid">
<div class="principle-card">
<div class="principle-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
<div class="magic-wand">
<div class="wand"></div>
<div class="sparkles">
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
</div>
</div>
</div>
</div>
<div class="principle-content">
<h4>It Just Works</h4>
<div class="principle-steps">
<div class="step">1. Open Jan, start chatting.</div>
<div class="step">2. Onboarding is fully available but optional.</div>
<div class="step">3. Setting up an API key is optional.</div>
<div class="step">4. Selecting a local model is optional.</div>
</div>
<div class="principle-quote">We handle the complexity.</div>
</div>
</div>
<div class="principle-card">
<div class="principle-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
<div class="balance-scale">
<div class="scale-base"></div>
<div class="scale-left">
<div class="scale-icon privacy-icon"></div>
</div>
<div class="scale-right">
<div class="scale-icon cloud-icon"></div>
</div>
</div>
</div>
</div>
<div class="principle-content">
<h4>Privacy First, Cloud When Needed</h4>
<p>Start with complete privacy by default. Add cloud capabilities only when you choose to.</p>
<div class="principle-benefit">
Your choice, your control, your data.
</div>
</div>
</div>
<div class="principle-card">
<div class="principle-robot">
<div class="robot-head">
<div class="robot-smile"></div>
</div>
<div class="robot-body">
<div class="solution-gear">
<div class="gear-main">
<div class="gear-teeth"></div>
</div>
<div class="gear-small">
<div class="gear-teeth"></div>
</div>
</div>
</div>
</div>
<div class="principle-content">
<h4>Solve Problems, Not Settings</h4>
<p>Users want answers, not configuration options. Power users can dig deeper, but it's never required.</p>
<div class="principle-benefit">
Focus on what matters: getting things done.
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<style>
.vision-section {
background: var(--cream-white);
border-top: 1px solid var(--border-color);
}
.section-badge {
display: inline-flex;
align-items: center;
gap: 0.75rem;
background: rgba(255, 255, 255, 0.9);
padding: 0.75rem 1.5rem;
border-radius: 50px;
font-size: 0.9rem;
font-weight: 600;
color: var(--dark-text);
margin-bottom: 1rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
border: 2px solid var(--primary-blue);
}
.badge-robot {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.badge-robot-head {
width: 20px;
height: 20px;
background: var(--light-purple);
border-radius: 6px;
border: 2px solid var(--dark-text);
}
.badge-robot-body {
font-size: 0.7rem;
font-weight: 700;
color: var(--dark-text);
}
/* Vision Formula */
.vision-formula {
margin: 4rem 0;
background: white;
border-radius: 20px;
padding: 3rem;
border: 2px solid var(--border-color);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
}
.formula-container {
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
flex-wrap: wrap;
}
.formula-item, .formula-result {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
max-width: 200px;
}
.formula-robot, .result-robot {
margin-bottom: 1rem;
position: relative;
}
.formula-robot .robot-head, .result-robot .robot-head {
width: 50px;
height: 50px;
border-radius: 12px;
border: 3px solid var(--dark-text);
margin: 0 auto 8px;
position: relative;
}
.formula-robot .robot-body, .result-robot .robot-body {
width: 60px;
height: 70px;
border-radius: 12px;
border: 3px solid var(--dark-text);
margin: 0 auto;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
/* Robot variations */
.models-robot .robot-head { background: var(--soft-pink); }
.models-robot .robot-body { background: var(--soft-pink); }
.app-robot .robot-head { background: var(--soft-green); }
.app-robot .robot-body { background: var(--soft-green); }
.tools-robot .robot-head { background: var(--warm-yellow); }
.tools-robot .robot-body { background: var(--warm-yellow); }
.result-robot .robot-head { background: var(--primary-blue); }
.result-robot .robot-body { background: var(--primary-blue); }
/* Robot details */
.robot-screen {
width: 30px;
height: 20px;
background: var(--dark-text);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
}
.screen-dots {
display: flex;
gap: 3px;
}
.dot {
width: 3px;
height: 3px;
background: var(--success-green);
border-radius: 50%;
animation: pulse 2s infinite;
}
.dot:nth-child(2) { animation-delay: 0.5s; }
.dot:nth-child(3) { animation-delay: 1s; }
.robot-interface {
display: flex;
flex-direction: column;
gap: 3px;
}
.interface-line {
height: 2px;
background: var(--dark-text);
border-radius: 1px;
width: 20px;
}
.interface-line.short {
width: 12px;
}
.robot-tools {
display: flex;
gap: 4px;
}
.tool {
width: 6px;
height: 6px;
background: var(--dark-text);
border-radius: 2px;
}
.result-glow {
width: 25px;
height: 25px;
background: white;
border-radius: 50%;
animation: pulse 2s infinite;
}
.robot-head.crown::after {
content: '';
position: absolute;
top: -8px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 10px;
background: var(--warning-amber);
border: 2px solid var(--dark-text);
border-radius: 4px 4px 0 0;
}
.robot-cape {
position: absolute;
top: 40px;
left: -10px;
right: -10px;
height: 30px;
background: var(--error-red);
border-radius: 0 0 8px 8px;
border: 2px solid var(--dark-text);
border-top: none;
z-index: -1;
}
.formula-operator, .formula-equals {
font-size: 2rem;
font-weight: 800;
color: var(--primary-blue);
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
background: white;
border: 2px solid var(--primary-blue);
border-radius: 50%;
}
.formula-label, .result-label {
font-size: 1.2rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 0.5rem;
}
.formula-desc, .result-desc {
font-size: 0.9rem;
color: var(--medium-gray);
line-height: 1.4;
}
/* Dual Modes */
.dual-modes {
margin: 4rem 0;
}
.modes-header {
text-align: center;
margin-bottom: 3rem;
}
.modes-header h3 {
font-size: 2rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 1rem;
}
.modes-header p {
font-size: 1.1rem;
color: var(--medium-gray);
max-width: 600px;
margin: 0 auto;
}
.modes-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 2rem;
}
.mode-card {
background: white;
border-radius: 16px;
border: 2px solid var(--border-color);
padding: 2rem;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.mode-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
}
.local-mode {
border-color: var(--success-green);
}
.local-mode::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--success-green);
}
.cloud-mode {
border-color: var(--primary-blue);
}
.cloud-mode::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--primary-blue);
}
.mode-robot {
text-align: center;
margin-bottom: 1.5rem;
position: relative;
}
.mode-robot .robot-head {
width: 60px;
height: 60px;
border-radius: 15px;
border: 3px solid var(--dark-text);
margin: 0 auto 10px;
}
.mode-robot .robot-body {
width: 70px;
height: 80px;
border-radius: 15px;
border: 3px solid var(--dark-text);
margin: 0 auto;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.local-mode .robot-head { background: var(--success-green); }
.local-mode .robot-body { background: var(--success-green); }
.cloud-mode .robot-head { background: var(--primary-blue); }
.cloud-mode .robot-body { background: var(--primary-blue); }
.mode-content h4 {
font-size: 1.5rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 1rem;
}
.mode-content p {
color: var(--medium-gray);
margin-bottom: 1.5rem;
line-height: 1.6;
}
.mode-features {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.feature-item {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 0.9rem;
color: var(--dark-text);
}
.feature-icon {
width: 20px;
height: 20px;
border-radius: 4px;
border: 2px solid var(--dark-text);
flex-shrink: 0;
}
.feature-icon.privacy { background: var(--success-green); }
.feature-icon.offline { background: var(--medium-gray); }
.feature-icon.hardware { background: var(--warning-amber); }
.feature-icon.local { background: var(--light-purple); }
.feature-icon.power { background: var(--primary-blue); }
.feature-icon.speed { background: var(--error-red); }
.feature-icon.selfhost { background: var(--success-green); }
.feature-icon.janai { background: var(--primary-blue); }
/* Product Principles */
.product-principles {
margin: 4rem 0;
}
.principles-header {
text-align: center;
margin-bottom: 3rem;
}
.principles-header h3 {
font-size: 2rem;
font-weight: 700;
color: var(--dark-text);
}
.principles-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
}
.principle-card {
background: white;
border-radius: 16px;
border: 2px solid var(--border-color);
padding: 2rem;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.principle-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
border-color: var(--primary-blue);
}
.principle-robot {
text-align: center;
margin-bottom: 1.5rem;
}
.principle-robot .robot-head {
width: 50px;
height: 50px;
background: var(--warm-yellow);
border-radius: 12px;
border: 3px solid var(--dark-text);
margin: 0 auto 8px;
}
.principle-robot .robot-body {
width: 60px;
height: 70px;
background: var(--gentle-orange);
border-radius: 12px;
border: 3px solid var(--dark-text);
margin: 0 auto;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.principle-content h4 {
font-size: 1.3rem;
font-weight: 700;
color: var(--dark-text);
margin-bottom: 1rem;
}
.principle-content p {
color: var(--medium-gray);
margin-bottom: 1rem;
line-height: 1.6;
}
.principle-steps {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
.step {
font-size: 0.9rem;
color: var(--dark-text);
padding-left: 1rem;
position: relative;
}
.step::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6px;
height: 6px;
background: var(--primary-blue);
border-radius: 50%;
}
.principle-quote, .principle-benefit {
font-style: italic;
color: var(--primary-blue);
font-weight: 600;
text-align: center;
padding: 1rem;
background: var(--light-blue);
border-radius: 8px;
border-left: 4px solid var(--primary-blue);
}
/* Responsive Design */
@media (max-width: 1024px) {
.formula-container {
gap: 1.5rem;
}
.modes-grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 768px) {
.vision-formula {
padding: 2rem;
}
.formula-container {
flex-direction: column;
gap: 1rem;
}
.formula-operator, .formula-equals {
transform: rotate(90deg);
}
.modes-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.mode-card {
padding: 1.5rem;
}
.principles-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.principle-card {
padding: 1.5rem;
}
}
@media (max-width: 480px) {
.vision-formula {
padding: 1.5rem;
}
.mode-card, .principle-card {
padding: 1.25rem;
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
.dot, .result-glow, .principle-card, .mode-card {
animation: none !important;
transition: none !important;
}
}
.robot-smile {
position: absolute;
bottom: 8px;
left: 50%;
transform: translateX(-50%);
width: 15px;
height: 8px;
border: 3px solid var(--dark-text);
border-top: none;
border-radius: 0 0 12px 12px;
}
</style>

View File

@ -0,0 +1,238 @@
---
export interface Props {
title?: string;
description?: string;
}
const { title = 'Jan', description = 'AI that runs where you need it, how you need it' } = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<title>{title}</title>
<style>
/* Reset and base styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 16px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
color: #000;
background: #fff;
padding-top: 4rem; /* Space for fixed nav */
}
/* Typography */
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
line-height: 1.2;
margin-top: 2rem;
margin-bottom: 1rem;
}
h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
h3 { font-size: 1.5rem; }
h4 { font-size: 1.25rem; }
h5 { font-size: 1.1rem; }
h6 { font-size: 1rem; }
p {
margin-bottom: 1.5rem;
}
/* Links */
a {
color: #0066cc;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* Lists */
ul, ol {
margin-bottom: 1.5rem;
padding-left: 2rem;
}
li {
margin-bottom: 0.5rem;
}
/* Tables */
table {
width: 100%;
border-collapse: collapse;
margin: 2rem 0;
}
th, td {
text-align: left;
padding: 0.75rem;
border: 1px solid #ddd;
}
th {
background: #f8f8f8;
font-weight: 600;
}
/* Code */
code {
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
font-size: 0.875em;
padding: 0.125rem 0.25rem;
background: #f4f4f4;
border-radius: 3px;
}
pre {
margin: 1.5rem 0;
padding: 1rem;
background: #f4f4f4;
border-radius: 4px;
overflow-x: auto;
}
pre code {
padding: 0;
background: none;
}
/* Blockquotes */
blockquote {
border-left: 4px solid #ddd;
padding-left: 1rem;
margin: 1.5rem 0;
color: #666;
}
/* Images */
img {
max-width: 100%;
height: auto;
margin: 2rem 0;
display: block;
}
/* HR */
hr {
border: none;
border-top: 1px solid #ddd;
margin: 3rem 0;
}
/* Main content area */
main {
min-height: calc(100vh - 4rem);
}
/* Print styles */
@media print {
body {
padding-top: 0;
}
.floating-nav,
.toc {
display: none !important;
}
}
/* Dark mode styles */
html[data-theme="dark"] {
color-scheme: dark;
}
html[data-theme="dark"] body {
background: #1a1a1a;
color: #fff;
}
html[data-theme="dark"] h1,
html[data-theme="dark"] h2,
html[data-theme="dark"] h3,
html[data-theme="dark"] h4,
html[data-theme="dark"] h5,
html[data-theme="dark"] h6 {
color: #fff;
}
html[data-theme="dark"] p,
html[data-theme="dark"] li {
color: #ccc;
}
html[data-theme="dark"] a {
color: #4a9eff;
}
html[data-theme="dark"] a:hover {
color: #6bb3ff;
}
html[data-theme="dark"] table {
background: #1a1a1a;
}
html[data-theme="dark"] th,
html[data-theme="dark"] td {
border-color: #444;
}
html[data-theme="dark"] th {
background: #2a2a2a;
color: #fff;
}
html[data-theme="dark"] td {
color: #ccc;
}
html[data-theme="dark"] code {
background: #2a2a2a;
color: #fff;
}
html[data-theme="dark"] pre {
background: #2a2a2a;
color: #fff;
}
html[data-theme="dark"] blockquote {
border-left-color: #444;
color: #999;
}
html[data-theme="dark"] hr {
border-top-color: #444;
}
html[data-theme="dark"] img {
opacity: 0.9;
}
</style>
</head>
<body>
<main>
<slot />
</main>
</body>
</html>

View File

@ -1,388 +0,0 @@
---
import Layout from '../layouts/Layout.astro';
import ProductsHero from '../components/products/ProductsHero.astro';
import ProductsTOC from '../components/products/ProductsTOC.astro';
import ProductsVision from '../components/products/ProductsVision.astro';
import ProductsArchitecture from '../components/products/ProductsArchitecture.astro';
import ProductsModels from '../components/products/ProductsModels.astro';
import ProductsPlatforms from '../components/products/ProductsPlatforms.astro';
import ProductsTools from '../components/products/ProductsTools.astro';
import ProductsPrinciples from '../components/products/ProductsPrinciples.astro';
import ProductsRoadmap from '../components/products/ProductsRoadmap.astro';
import DoodleBackground from '../components/DoodleBackground.astro';
---
<Layout title="Jan Products - Full Stack AI Solution You Can Self-Host">
<main class="products-page">
<!-- Playful doodle background -->
<DoodleBackground variant="colorful" density="medium" pattern="mixed" />
<!-- Table of Contents -->
<ProductsTOC />
<!-- Hero Section -->
<ProductsHero />
<!-- Product Vision -->
<ProductsVision />
<!-- Architecture Overview -->
<ProductsArchitecture />
<!-- Models Section -->
<ProductsModels />
<!-- Platforms Section -->
<ProductsPlatforms />
<!-- Tools Section -->
<ProductsTools />
<!-- Product Principles -->
<ProductsPrinciples />
<!-- Release Roadmap -->
<ProductsRoadmap />
</main>
</Layout>
<style>
@import '/src/styles/robot-personalities.css';
@import '/src/styles/hand-drawn.css';
/* Color Palette - Vibrant & Playful like PostHog */
:root {
--primary-blue: #3A86FF;
--light-blue: #E8F4FF;
--pastel-blue: #00F5FF;
--soft-green: #06FFA5;
--warm-yellow: #FFB700;
--gentle-orange: #FB5607;
--light-purple: #8338EC;
--soft-pink: #FF006E;
--cream-white: #FFF8E8;
--light-gray: #f8fafc;
--medium-gray: #4A4E69;
--dark-text: #1A1A2E;
--success-green: #06FFA5;
--warning-amber: #FFB700;
--error-red: #FF4365;
--border-color: #e2e8f0;
/* Robot-specific colors for consistency */
--robot-pink: #FF006E;
--robot-blue: #3A86FF;
--robot-green: #06FFA5;
--robot-yellow: #FFB700;
--robot-purple: #8338EC;
--robot-orange: #FB5607;
--robot-teal: #00F5FF;
--robot-red: #FF4365;
--robot-dark: #1A1A2E;
--robot-light: #FFFFFF;
--robot-gray: #4A4E69;
--robot-bg-purple: #F3E8FF;
--robot-bg-blue: #E8F4FF;
--robot-bg-pink: #FFE8F0;
--robot-bg-yellow: #FFF8E8;
--robot-bg-green: #E8FFEA;
/* Special Effects */
--robot-glow-pink: rgba(255, 0, 110, 0.4);
--robot-glow-blue: rgba(58, 134, 255, 0.4);
--robot-glow-green: rgba(6, 255, 165, 0.4);
--robot-shadow: rgba(26, 26, 46, 0.15);
}
.products-page {
background: var(--light-gray);
min-height: 100vh;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
line-height: 1.6;
color: var(--dark-text);
}
/* Global section styling */
:global(.products-section) {
padding: 4rem 0;
position: relative;
}
:global(.container) {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
:global(.section-header) {
text-align: center;
margin-bottom: 3rem;
}
:global(.section-title) {
font-size: 2.5rem;
font-weight: 800;
color: var(--dark-text);
margin-bottom: 1rem;
}
:global(.section-description) {
font-size: 1.2rem;
color: var(--medium-gray);
max-width: 600px;
margin: 0 auto;
}
/* Robot character base styles */
:global(.robot-character) {
position: relative;
display: inline-block;
}
:global(.robot-head) {
border-radius: 15px;
border: 3px solid var(--dark-text);
position: relative;
margin: 0 auto;
}
:global(.robot-eyes) {
display: flex;
justify-content: space-between;
padding: 8px;
}
:global(.robot-eye) {
width: 12px;
height: 12px;
background: var(--dark-text);
border-radius: 50%;
position: relative;
}
:global(.robot-eye::after) {
content: '';
position: absolute;
top: 2px;
right: 2px;
width: 3px;
height: 3px;
background: white;
border-radius: 50%;
}
:global(.robot-body) {
border-radius: 12px;
border: 3px solid var(--dark-text);
margin: 0 auto;
position: relative;
}
/* Card styling */
:global(.feature-card) {
background: white;
border-radius: 16px;
border: 2px solid var(--border-color);
padding: 2rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
:global(.feature-card:hover) {
transform: translateY(-4px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
border-color: var(--primary-blue);
}
/* Status indicators */
:global(.status-badge) {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 600;
border: 2px solid;
}
:global(.status-active) {
background: var(--success-green);
color: white;
border-color: var(--success-green);
}
:global(.status-beta) {
background: var(--warning-amber);
color: white;
border-color: var(--warning-amber);
}
:global(.status-coming) {
background: var(--light-gray);
color: var(--medium-gray);
border-color: var(--medium-gray);
border-style: dashed;
}
/* Button styling */
:global(.btn-primary) {
background: var(--primary-blue);
color: white;
padding: 1rem 2rem;
border-radius: 30px;
font-weight: 600;
text-decoration: none;
display: inline-block;
transition: all 0.3s ease;
border: 2px solid var(--primary-blue);
}
:global(.btn-primary:hover) {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3);
}
:global(.btn-secondary) {
background: white;
color: var(--primary-blue);
padding: 1rem 2rem;
border-radius: 30px;
font-weight: 600;
text-decoration: none;
display: inline-block;
transition: all 0.3s ease;
border: 2px solid var(--primary-blue);
}
:global(.btn-secondary:hover) {
background: var(--light-blue);
transform: translateY(-2px);
}
/* Animations */
:global(.bounce) {
animation: bounce 3s infinite ease-in-out;
}
:global(.wiggle) {
animation: wiggle 2s infinite ease-in-out;
}
:global(.pulse) {
animation: pulse 2s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-8px); }
}
@keyframes wiggle {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(-2deg); }
75% { transform: rotate(2deg); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.05); opacity: 0.9; }
}
/* Responsive design */
@media (max-width: 768px) {
:global(.container) {
padding: 0 1rem;
}
:global(.section-title) {
font-size: 2rem;
}
:global(.products-section) {
padding: 3rem 0;
}
}
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* High contrast mode */
@media (prefers-contrast: high) {
:global(.feature-card) {
border-width: 3px;
}
}
</style>
<script>
// Smooth scrolling for TOC links
document.addEventListener('DOMContentLoaded', () => {
const tocLinks = document.querySelectorAll('.toc-link');
tocLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetId = link.getAttribute('href')?.substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Highlight current section in TOC
const sections = document.querySelectorAll('[id]');
const observerOptions = {
threshold: 0.3,
rootMargin: '-100px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const id = entry.target.id;
const tocLink = document.querySelector(`[href="#${id}"]`);
// Remove active class from all TOC links
document.querySelectorAll('.toc-link').forEach(link => {
link.classList.remove('active');
});
// Add active class to current section
if (tocLink) {
tocLink.classList.add('active');
}
}
});
}, observerOptions);
sections.forEach(section => {
observer.observe(section);
});
// Robot hover interactions
const robots = document.querySelectorAll('.robot-character');
robots.forEach(robot => {
robot.addEventListener('mouseenter', () => {
robot.style.animation = 'wiggle 0.5s ease-in-out';
setTimeout(() => {
robot.style.animation = '';
}, 500);
});
});
});
// Import robot interactions for playful animations
import('/src/scripts/robot-interactions.js');
</script>

496
website/src/pages/prods.mdx Normal file
View File

@ -0,0 +1,496 @@
---
layout: ../layouts/BaseLayout.astro
title: Product
description: AI that runs where you need it, how you need it
---
import SimpleFloatingNav from '../components/SimpleFloatingNav.astro';
import SimpleTOC from '../components/SimpleTOC.astro';
import ReleaseDatabase from '../components/ReleaseDatabase.astro';
<SimpleFloatingNav currentPage="products" />
<SimpleTOC />
<div className="content-wrapper">
# Products
<p className="lead">
Jan is evolving from a local AI application to a complete full-stack AI solution that you can self-host. This includes models, applications, and tools to solve real problems.
</p>
## What We're Building
**Jan Agent** = Jan Models + Jan Application + Jan Tools
Unlike other AI assistants that do specific tasks with one model or have many models with a myriad of solutions, Jan provides:
- Our own models optimized for local and private use
- Applications that work across all your devices
- Tools that actually get things done
## Two Modes, One Experience
### Local (Incognito) Mode
Run AI models entirely on your device, giving you complete privacy with no internet required.
### Cloud Mode
Connect to more powerful models when needed - either self-hosted or via jan.ai.
Users shouldn't need to understand models, APIs, or technical details. Just choose Local for privacy or Cloud for power.
## Our Product Principles
### It Just Works
1. Open Jan, start chatting
2. Onboarding is fully available but optional
3. Setting up an API key is optional
4. Selecting a local model is optional
We handle the complexity.
### Privacy First, Cloud When Needed
Start with complete privacy by default. Add cloud capabilities only when you choose to.
### Solve Problems, Not Settings
Users want answers, not configuration options. Power users can dig deeper, but it's never required.
## Available on Every Device
### Jan Desktop
**Status:** Available Now
Your personal AI workstation that powers all other devices. Run models locally with optional cloud connection.
**Key Features:**
- Runs models locally on your hardware
- GPU acceleration support
- Powers other devices via network connection
- Complete privacy and control
- Windows, macOS, and Linux support
**Requirements:**
- Minimum 8GB RAM
- 10GB+ storage space
- Optional: NVIDIA GPU for acceleration
### Jan Web
**Status:** Beta Launch Soon
SaaS version of Jan Server with no setup required. Default cloud mode for mobile and desktop users.
**Key Features:**
- No installation needed
- Instant access from any browser
- Automatic updates and maintenance
- Default cloud backend for mobile apps
- Team collaboration features
**Pricing:**
- Free tier: 50 queries/day
- Pro tier: Unlimited usage
### Jan Mobile
**Status:** Coming Q1 2025
Connect to Desktop/Server, run local mode with Jan Nano, same experience everywhere. See detailed information below.
**Key Features:**
- iOS and Android support
- Three adaptive modes (Desktop, Server, Local)
- Voice-first interface
- Seamless device switching
- Jan Nano for on-device AI
### Jan Server
**Status:** Coming Q2 2025
Self-hosted solution for teams and enterprises. Your own private AI cloud.
**Key Features:**
- Support for 5-500+ concurrent users
- Enterprise authentication (SSO, LDAP)
- Docker and Kubernetes deployment
- Admin dashboard
- Team knowledge sharing
**Deployment Options:**
- Docker: Single command setup
- Kubernetes: Enterprise scale
- Bare metal: Maximum control
## Jan Mobile: Three Modes, One Experience
Jan Mobile brings the same AI experience to your phone. Connect to your desktop, your server, or run models locally.
### How It Works
Jan Mobile adapts to your situation:
**At Home** - Connect to your Jan Desktop over WiFi
Your Phone → WiFi → Your Desktop → Response
**At Work** - Connect to your company Jan Server
Your Phone → Internet → Company Server → Response
**On the Go** - Run Jan Nano on your phone or talk to your favorite cloud-based model
Your Phone → Jan Nano (6GB) → Response
No configuration needed. It just works.
### Key Features
- **Seamless Switching**: Move from home to office to airplane. One-click and Jan adapts immediately.
- **Voice First**: Talk to Jan naturally. Responses can be spoken too.
- **Sync Everything**: Conversations, settings, and preferences follow you across devices.
### Privacy & Security
**Your Data, Your Control**
- Local Mode: Everything stays on your phone
- Desktop Mode: Direct encrypted connection
- Server Mode: Your organization's policies apply
**No Compromises**
- Biometric app lock
- Encrypted storage
- No cloud backups without permission
- Clear data anytime
## What Makes Jan Different
<table className="simple-table">
<thead>
<tr>
<th>Feature</th>
<th>Other AI Assistants</th>
<th>Jan</th>
</tr>
</thead>
<tbody>
<tr>
<td>Models</td>
<td>Wrapper around Claude/GPT</td>
<td>Our own models + others</td>
</tr>
<tr>
<td>Dual mode</td>
<td>Your data on their servers</td>
<td>Your data stays yours</td>
</tr>
<tr>
<td>Deployment</td>
<td>Cloud only</td>
<td>Local, self-hosted, or cloud</td>
</tr>
<tr>
<td>Cost</td>
<td>Subscription forever</td>
<td>Free locally, pay for cloud</td>
</tr>
</tbody>
</table>
## Development Timeline
<ReleaseDatabase />
</div>
<style>{`
:root {
--text-primary: #000;
--text-secondary: #333;
--text-muted: #666;
--bg-primary: #fff;
--bg-secondary: #f8f8f8;
--border-color: #ddd;
--link-color: #0066cc;
}
html[data-theme="dark"] {
--text-primary: #fff;
--text-secondary: #ccc;
--text-muted: #999;
--bg-primary: #1a1a1a;
--bg-secondary: #2a2a2a;
--border-color: #444;
--link-color: #4a9eff;
}
body {
background: var(--bg-primary);
color: var(--text-primary);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
}
.content-wrapper {
max-width: 800px;
margin: 0 auto;
padding: 4rem 2rem;
}
h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
line-height: 1.2;
}
h2 {
font-size: 2rem;
font-weight: 700;
margin-top: 3rem;
margin-bottom: 1.5rem;
}
h3 {
font-size: 1.5rem;
font-weight: 600;
margin-top: 2rem;
margin-bottom: 1rem;
}
h4 {
font-size: 1.25rem;
font-weight: 600;
margin-top: 1.5rem;
margin-bottom: 0.75rem;
}
p {
margin-bottom: 1.5rem;
color: var(--text-secondary);
}
.lead {
font-size: 1.25rem;
color: var(--text-secondary);
margin-bottom: 2rem;
}
.simple-table {
width: 100%;
border-collapse: collapse;
margin: 2rem 0;
font-size: 0.95rem;
}
.simple-table th,
.simple-table td {
text-align: left;
padding: 0.75rem;
border: 1px solid var(--border-color);
}
.simple-table th {
background: var(--bg-secondary);
font-weight: 600;
}
.simple-table tr:hover {
background: var(--bg-secondary);
}
html[data-theme="dark"] .simple-table {
border-color: var(--border-color);
}
html[data-theme="dark"] .simple-table th,
html[data-theme="dark"] .simple-table td {
border-color: var(--border-color);
}
img {
max-width: 100%;
height: auto;
margin: 2rem 0;
}
ul, ol {
margin-bottom: 1.5rem;
padding-left: 2rem;
}
li {
margin-bottom: 0.5rem;
}
blockquote {
border-left: 4px solid var(--border-color);
padding-left: 1rem;
margin: 1.5rem 0;
color: var(--text-muted);
}
.floating-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
background: var(--bg-primary);
border-bottom: 1px solid var(--border-color);
z-index: 1000;
padding: 1rem 0;
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-links {
display: flex;
gap: 2rem;
}
.nav-links a {
color: var(--text-primary);
text-decoration: none;
font-weight: 500;
}
.nav-links a:hover {
color: var(--link-color);
}
.nav-links a.active {
color: var(--link-color);
}
.toc {
position: fixed;
right: 2rem;
top: 50%;
transform: translateY(-50%);
width: 250px;
max-height: 70vh;
overflow-y: auto;
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 1.5rem;
}
.toc h3 {
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 1rem;
color: var(--text-muted);
}
.toc ul {
list-style: none;
padding: 0;
margin: 0;
}
.toc li {
margin-bottom: 0.5rem;
}
.toc a {
color: var(--text-secondary);
text-decoration: none;
font-size: 0.9rem;
display: block;
padding: 0.25rem 0;
}
.toc a:hover {
color: var(--link-color);
}
.toc a.active {
color: var(--link-color);
font-weight: 600;
}
@media (max-width: 1280px) {
.toc {
display: none;
}
}
@media (max-width: 768px) {
.content-wrapper {
padding: 3rem 1rem;
}
h1 {
font-size: 2rem;
}
h2 {
font-size: 1.5rem;
}
}
/* Dark mode styles */
html[data-theme="dark"] body {
background: var(--bg-primary);
color: var(--text-primary);
}
html[data-theme="dark"] h1,
html[data-theme="dark"] h2,
html[data-theme="dark"] h3,
html[data-theme="dark"] h4,
html[data-theme="dark"] h5,
html[data-theme="dark"] h6 {
color: var(--text-primary);
}
html[data-theme="dark"] p,
html[data-theme="dark"] li {
color: var(--text-secondary);
}
html[data-theme="dark"] a {
color: var(--link-color);
}
html[data-theme="dark"] blockquote {
border-left-color: var(--border-color);
color: var(--text-muted);
}
html[data-theme="dark"] .lead {
color: var(--text-secondary);
}
html[data-theme="dark"] .content-wrapper {
background: var(--bg-primary);
}
/* Dark mode table styles */
html[data-theme="dark"] table {
background: var(--bg-primary);
}
html[data-theme="dark"] th {
background: var(--bg-secondary);
color: var(--text-primary);
}
html[data-theme="dark"] td {
color: var(--text-secondary);
}
html[data-theme="dark"] th,
html[data-theme="dark"] td {
border-color: var(--border-color);
}
`}</style>