interim product page layout
This commit is contained in:
parent
49de36cac8
commit
df5fac06b4
@ -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>
|
|
||||||
@ -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>
|
|
||||||
@ -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>
|
|
||||||
671
website/src/components/ReleaseDatabase.astro
Normal file
671
website/src/components/ReleaseDatabase.astro
Normal 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>
|
||||||
@ -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>
|
|
||||||
200
website/src/components/SimpleFloatingNav.astro
Normal file
200
website/src/components/SimpleFloatingNav.astro
Normal 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>
|
||||||
338
website/src/components/SimpleTOC.astro
Normal file
338
website/src/components/SimpleTOC.astro
Normal 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>
|
||||||
@ -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>
|
|
||||||
@ -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>
|
|
||||||
@ -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
@ -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>
|
|
||||||
@ -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>
|
|
||||||
@ -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
@ -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>
|
|
||||||
238
website/src/layouts/BaseLayout.astro
Normal file
238
website/src/layouts/BaseLayout.astro
Normal 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>
|
||||||
@ -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
496
website/src/pages/prods.mdx
Normal 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>
|
||||||
Loading…
x
Reference in New Issue
Block a user