refine: landing page and 404 for clean consistent look

Hero: Kit. title with primary dot, arrow-down CTA, minimal line scroll
indicator. Stats: rounded-2xl + icon border matching cards. ToolsGrid:
proper h2 with gradient accent word. ToolCard: visible rest border,
radial glow, bigger icon+arrow. Footer: visible Source label, consistent
border. 404: fade gradient number, divider line, rounded-xl CTA.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 16:48:04 +01:00
parent 20406c5dcf
commit 075aa0b6c5
7 changed files with 68 additions and 66 deletions

View File

@@ -11,27 +11,31 @@ export default function NotFound() {
<div className="flex-1 flex flex-col items-center justify-center px-6 py-20 relative z-10 text-center">
{/* Logo */}
<div style={{ animation: 'fadeIn 0.5s ease-out both' }}>
<Logo size={52} />
</div>
<Logo size={52} />
{/* 404 */}
<div
className="mt-8"
className="mt-10"
style={{ animation: 'slideUp 0.5s ease-out 0.15s both' }}
>
<span className="text-[80px] md:text-[120px] font-bold font-mono text-primary leading-none tabular-nums block">
<span className="text-[80px] md:text-[120px] font-bold font-mono leading-none tabular-nums block bg-gradient-to-b from-foreground to-foreground/25 bg-clip-text text-transparent">
404
</span>
</div>
{/* Divider */}
<div
className="mt-6 w-12 h-px bg-gradient-to-r from-transparent via-primary/50 to-transparent"
style={{ animation: 'fadeIn 0.5s ease-out 0.3s both' }}
/>
{/* Message */}
<div
className="mt-4 space-y-1"
style={{ animation: 'slideUp 0.5s ease-out 0.3s both' }}
className="mt-6 space-y-2"
style={{ animation: 'slideUp 0.5s ease-out 0.35s both' }}
>
<p className="text-sm font-medium text-foreground/70">Page not found</p>
<p className="text-[11px] text-muted-foreground/50 font-mono max-w-xs mx-auto leading-relaxed">
<p className="text-[11px] text-muted-foreground/45 font-mono max-w-xs mx-auto leading-relaxed">
The tool or page you&apos;re looking for doesn&apos;t exist or has been moved.
</p>
</div>
@@ -39,11 +43,11 @@ export default function NotFound() {
{/* CTA */}
<div
className="mt-8"
style={{ animation: 'slideUp 0.5s ease-out 0.45s both' }}
style={{ animation: 'slideUp 0.5s ease-out 0.5s both' }}
>
<Link
href="/"
className="inline-flex items-center gap-2 px-5 py-2.5 glass rounded-lg border border-primary/30 hover:border-primary/60 hover:bg-primary/10 text-sm font-medium text-foreground/70 hover:text-foreground transition-all duration-200"
className="inline-flex items-center gap-2 px-5 py-2.5 glass rounded-xl border border-white/[0.06] hover:border-primary/40 hover:bg-primary/[0.07] text-sm font-medium text-foreground/60 hover:text-foreground transition-all duration-200"
>
<ArrowLeft className="w-3.5 h-3.5 text-primary" />
Back to Home

View File

@@ -5,16 +5,16 @@ export default function Footer() {
return (
<footer className="relative py-10 px-6">
<div className="max-w-5xl mx-auto border-t border-border/20 pt-8">
<div className="max-w-5xl mx-auto border-t border-white/[0.06] pt-8">
<div className="flex items-center justify-between">
<p className="flex items-center gap-1 text-[9px] text-muted-foreground/40 font-mono">
© {currentYear} Kit
<Heart className="w-2 h-2 text-primary/70 shrink-0 animate-pulse" fill="currentColor" />
<p className="flex items-center gap-1.5 text-xs text-muted-foreground/35 font-mono">
<span>© {currentYear} Kit</span>
<Heart className="w-2.5 h-2.5 text-primary/60 shrink-0 animate-pulse" fill="currentColor" />
<a
href="https://pivoine.art"
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground/70 transition-colors"
className="hover:text-foreground/60 transition-colors duration-200"
>
Valknar
</a>
@@ -24,9 +24,10 @@ export default function Footer() {
target="_blank"
rel="noopener noreferrer"
title="View source"
className="text-muted-foreground/30 hover:text-primary transition-colors"
className="flex items-center gap-1.5 text-xs text-muted-foreground/30 font-mono hover:text-primary transition-colors duration-200"
>
<GitFork className="w-3.5 h-3.5" />
<span className="hidden sm:inline">Source</span>
</a>
</div>
</div>

View File

@@ -1,6 +1,6 @@
'use client';
import { Toolbox } from 'lucide-react';
import { ArrowDown } from 'lucide-react';
import Logo from './Logo';
export default function Hero() {
@@ -13,36 +13,35 @@ export default function Hero() {
<div className="flex flex-col items-center text-center max-w-2xl mx-auto">
{/* Logo */}
<div style={{ animation: 'fadeIn 0.6s ease-out both' }}>
<Logo size={64} />
</div>
<Logo size={72} />
{/* Badge */}
<div
className="mt-8 flex items-center gap-2 px-3 py-1 glass rounded-full"
className="mt-8 flex items-center gap-2 px-3 py-1.5 glass rounded-full border border-white/[0.06]"
style={{ animation: 'slideUp 0.5s ease-out 0.2s both' }}
>
<span className="w-1.5 h-1.5 rounded-full bg-primary animate-pulse" />
<span className="text-[10px] font-mono text-muted-foreground/60 tracking-widest uppercase">
Browser-first toolkit
<span className="w-1.5 h-1.5 rounded-full bg-primary animate-pulse shrink-0" />
<span className="text-[10px] font-mono text-muted-foreground/55 tracking-widest uppercase">
Browser-first developer toolkit
</span>
</div>
{/* Title */}
<h1
className="mt-5 text-6xl md:text-8xl font-bold text-foreground tracking-tight leading-none"
className="mt-6 font-bold tracking-tight leading-none"
style={{ animation: 'slideUp 0.5s ease-out 0.3s both' }}
>
Kit
<span className="text-6xl md:text-8xl text-foreground">Kit</span>
<span className="text-6xl md:text-8xl text-primary">.</span>
</h1>
{/* Description */}
<p
className="mt-5 text-sm text-muted-foreground/60 max-w-sm leading-relaxed"
className="mt-6 text-sm text-muted-foreground/55 max-w-xs leading-relaxed"
style={{ animation: 'slideUp 0.5s ease-out 0.4s both' }}
>
A curated collection of browser-based tools for developers and creators.
Everything runs locally.
Everything runs locally no data leaves your machine.
</p>
{/* CTA */}
@@ -52,28 +51,23 @@ export default function Hero() {
>
<button
onClick={scrollToTools}
className="flex items-center gap-2 px-5 py-2.5 rounded-lg border border-primary/30 bg-primary/[0.07] hover:border-primary/60 hover:bg-primary/[0.14] text-sm font-medium text-foreground/75 hover:text-foreground transition-all duration-200"
className="flex items-center gap-2 px-6 py-2.5 rounded-xl border border-primary/30 bg-primary/[0.07] hover:border-primary/55 hover:bg-primary/[0.13] text-sm font-medium text-foreground/70 hover:text-foreground transition-all duration-200"
>
<Toolbox className="w-3.5 h-3.5 text-primary" />
Explore Tools
<ArrowDown className="w-3.5 h-3.5 text-primary" />
</button>
</div>
{/* Scroll indicator */}
<button
onClick={scrollToTools}
className="mt-20 flex flex-col items-center gap-2 group"
className="mt-24 flex flex-col items-center gap-2 group"
style={{ animation: 'fadeIn 0.5s ease-out 0.9s both' }}
>
<div className="w-px h-8 bg-gradient-to-b from-transparent via-primary/30 to-primary/60 group-hover:via-primary/50 group-hover:to-primary transition-colors duration-300" />
<span className="text-[9px] font-mono text-muted-foreground/25 uppercase tracking-widest group-hover:text-muted-foreground/50 transition-colors">
Scroll
</span>
<div className="w-4 h-7 border border-muted-foreground/15 rounded-full flex items-start justify-center pt-1.5 group-hover:border-primary/30 transition-colors">
<div
className="w-0.5 h-1.5 bg-primary/50 rounded-full"
style={{ animation: 'float 1.5s ease-in-out infinite' }}
/>
</div>
</button>
</div>
</section>

View File

@@ -28,7 +28,7 @@ export default function Logo({ className = '', size = 120 }: { className?: strin
{/* Brush (Lucide) - horizontal flipped */}
<g
transform="translate(32, 30) rotate(90) scale(3.025) translate(-11.25, -11)"
style={{ animation: 'pathFlicker 0.9s ease-out 0.35s both' }}
style={{ animation: 'pathFlicker 0.9s ease-out 0.15s both' }}
>
<path
d="m11 10l3 3m-7.5 8A3.5 3.5 0 1 0 3 17.5a2.62 2.62 0 0 1-.708 1.792A1 1 0 0 0 3 21z"

View File

@@ -2,14 +2,14 @@ import { tools } from '@/lib/tools';
import { Box, Code2, Shield } from 'lucide-react';
const stats = [
{ value: tools.length, label: 'Tools', icon: Box },
{ value: '100%', label: 'Open Source', icon: Code2 },
{ value: '', label: 'Privacy First', icon: Shield },
{ value: tools.length, label: 'Tools available', icon: Box },
{ value: '100%', label: 'Open source', icon: Code2 },
{ value: '0', label: 'Data collected', icon: Shield },
];
export default function Stats() {
return (
<section className="relative py-8 px-6">
<section className="relative py-4 px-6">
<div className="max-w-5xl mx-auto">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{stats.map((stat, i) => {
@@ -17,14 +17,16 @@ export default function Stats() {
return (
<div
key={stat.label}
className="glass rounded-xl p-5 flex items-center gap-4"
className="glass rounded-2xl p-5 flex items-center gap-4 border border-white/[0.06]"
style={{ animation: `slideUp 0.5s ease-out ${0.1 + i * 0.1}s both` }}
>
<div className="w-9 h-9 rounded-xl bg-primary/10 flex items-center justify-center shrink-0">
<Icon className="w-4 h-4 text-primary" />
<div className="w-10 h-10 rounded-xl bg-primary/10 border border-primary/15 flex items-center justify-center shrink-0">
<Icon className="w-4.5 h-4.5 text-primary" />
</div>
<div>
<span className="text-2xl font-bold tabular-nums text-foreground block leading-none">{stat.value}</span>
<span className="text-2xl font-bold tabular-nums text-foreground block leading-none">
{stat.value}
</span>
<span className="text-[10px] font-mono text-muted-foreground/40 uppercase tracking-widest mt-1 block">
{stat.label}
</span>

View File

@@ -15,35 +15,38 @@ export default function ToolCard({ title, description, icon: Icon, url, index, b
return (
<Link
href={url}
className="group relative glass rounded-xl p-5 flex flex-col h-full transition-all duration-300 hover:border-primary/40 hover:shadow-[0_8px_32px_rgba(139,92,246,0.08)] overflow-hidden"
className="group relative glass rounded-2xl p-6 flex flex-col h-full transition-all duration-300 border border-white/[0.06] hover:border-primary/35 hover:shadow-[0_12px_48px_rgba(139,92,246,0.11)] overflow-hidden"
style={{ animation: `slideUp 0.5s ease-out ${0.05 * index}s both` }}
>
{/* Top shimmer accent on hover */}
<div className="absolute top-0 inset-x-0 h-px bg-gradient-to-r from-transparent via-primary/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none" />
<div className="absolute top-0 inset-x-0 h-px bg-gradient-to-r from-transparent via-primary/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none" />
{/* Radial glow on hover */}
<div className="absolute top-0 left-0 w-36 h-36 rounded-full bg-primary/[0.07] blur-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none -translate-x-6 -translate-y-6" />
{/* Icon */}
<div className="w-11 h-11 rounded-xl bg-primary/10 flex items-center justify-center mb-4 shrink-0 transition-all duration-300 group-hover:bg-primary/[0.18] group-hover:shadow-[0_0_20px_rgba(139,92,246,0.18)]">
<div className="w-12 h-12 rounded-2xl bg-primary/10 border border-primary/15 flex items-center justify-center mb-5 shrink-0 transition-all duration-300 group-hover:bg-primary/20 group-hover:border-primary/30 group-hover:shadow-[0_0_24px_rgba(139,92,246,0.22)]">
<Icon className="w-5 h-5 text-primary" />
</div>
{/* Title */}
<h3 className="text-[15px] font-semibold text-foreground/80 group-hover:text-foreground transition-colors duration-200 mb-2 leading-tight">
<h3 className="text-base font-semibold text-foreground/80 group-hover:text-foreground transition-colors duration-200 mb-2 leading-snug">
{title}
</h3>
{/* Description */}
<p className="text-xs text-muted-foreground/55 leading-relaxed flex-1 mb-4">
<p className="text-[13px] text-muted-foreground/50 leading-relaxed flex-1 mb-5">
{description}
</p>
{/* Footer: badges + arrow pill */}
{/* Footer: badges + arrow */}
<div className="flex items-end justify-between gap-2">
{badges && badges.length > 0 ? (
<div className="flex flex-wrap gap-1">
{badges.map((badge) => (
<span
key={badge}
className="text-[9px] font-mono px-1.5 py-0.5 rounded-md bg-primary/[0.07] border border-primary/20 text-primary/55 transition-colors duration-200 group-hover:border-primary/30 group-hover:text-primary/70"
className="text-[9px] font-mono px-1.5 py-0.5 rounded-md bg-primary/[0.07] border border-primary/20 text-primary/55 transition-colors duration-200 group-hover:border-primary/35 group-hover:text-primary/75"
>
{badge}
</span>
@@ -52,8 +55,8 @@ export default function ToolCard({ title, description, icon: Icon, url, index, b
) : (
<span />
)}
<div className="w-6 h-6 rounded-lg glass flex items-center justify-center shrink-0 transition-all duration-200 group-hover:border-primary/30 group-hover:bg-primary/10">
<ArrowRight className="w-3 h-3 text-muted-foreground/30 group-hover:text-primary group-hover:translate-x-0.5 transition-all duration-200" />
<div className="w-7 h-7 rounded-xl glass border border-white/[0.06] flex items-center justify-center shrink-0 transition-all duration-200 group-hover:border-primary/30 group-hover:bg-primary/10">
<ArrowRight className="w-3.5 h-3.5 text-muted-foreground/30 group-hover:text-primary group-hover:translate-x-0.5 transition-all duration-200" />
</div>
</div>
</Link>

View File

@@ -8,20 +8,18 @@ export default function ToolsGrid() {
{/* Section heading */}
<div
className="flex items-end justify-between mb-8"
className="mb-10"
style={{ animation: 'fadeIn 0.5s ease-out both' }}
>
<div>
<span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest block mb-1">
Available Tools
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight text-foreground">
Available{' '}
<span className="bg-gradient-to-r from-primary via-violet-400 to-pink-400 bg-clip-text text-transparent">
Tools
</span>
<p className="text-xs text-muted-foreground/40">
{tools.length} tools everything runs in your browser
</p>
</div>
<span className="text-[9px] font-mono text-muted-foreground/25 tabular-nums hidden sm:block">
{tools.length.toString().padStart(2, '0')} modules
</span>
</h2>
<p className="text-sm text-muted-foreground/40 mt-2">
{tools.length} tools &mdash; everything runs in your browser, no data leaves your machine
</p>
</div>
{/* Tools grid */}