Initialized repository for chat Anime artist website

Co-authored-by: Jeff Emmett <46964190+Jeff-Emmett@users.noreply.github.com>
This commit is contained in:
v0 2025-11-02 17:17:45 +00:00
commit a375997423
27 changed files with 4670 additions and 0 deletions

27
.gitignore vendored Normal file
View File

@ -0,0 +1,27 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
# next.js
/.next/
/out/
# production
/build
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

30
README.md Normal file
View File

@ -0,0 +1,30 @@
# Anime artist website
*Automatically synced with your [v0.app](https://v0.app) deployments*
[![Deployed on Vercel](https://img.shields.io/badge/Deployed%20on-Vercel-black?style=for-the-badge&logo=vercel)](https://vercel.com/jeff-emmetts-projects/v0-anime-artist-website)
[![Built with v0](https://img.shields.io/badge/Built%20with-v0.app-black?style=for-the-badge)](https://v0.app/chat/k5UihhYT4Il)
## Overview
This repository will stay in sync with your deployed chats on [v0.app](https://v0.app).
Any changes you make to your deployed app will be automatically pushed to this repository from [v0.app](https://v0.app).
## Deployment
Your project is live at:
**[https://vercel.com/jeff-emmetts-projects/v0-anime-artist-website](https://vercel.com/jeff-emmetts-projects/v0-anime-artist-website)**
## Build your app
Continue building your app on:
**[https://v0.app/chat/k5UihhYT4Il](https://v0.app/chat/k5UihhYT4Il)**
## How It Works
1. Create and modify your project using [v0.app](https://v0.app)
2. Deploy your chats from the v0 interface
3. Changes are automatically pushed to this repository
4. Vercel deploys the latest version from this repository

132
app/about/page.tsx Normal file
View File

@ -0,0 +1,132 @@
import { Navigation } from "@/components/navigation"
import { SparkleEffect } from "@/components/sparkle-effect"
import { Card } from "@/components/ui/card"
import { Sparkles, Palette, Heart, Star, Smile } from "lucide-react"
export default function AboutPage() {
return (
<div className="min-h-screen">
<Navigation />
<SparkleEffect />
<main className="container px-4 py-12">
<div className="max-w-4xl mx-auto">
{/* Header */}
<div className="text-center mb-12">
<div className="float mb-6">
<Star className="h-16 w-16 mx-auto text-primary" />
</div>
<h1 className="text-5xl md:text-6xl font-bold mb-4 rainbow-text text-balance">About Banksy</h1>
<p className="text-xl text-muted-foreground text-pretty">The artist behind Paint Spark </p>
</div>
{/* Main Content */}
<Card className="p-8 md:p-12 mb-8 border-2">
<div className="prose prose-lg max-w-none">
<div className="flex items-center gap-3 mb-6">
<Smile className="h-8 w-8 text-primary flex-shrink-0" />
<h2 className="text-3xl font-bold m-0 text-card-foreground">Hi! I'm Banksy! 👋</h2>
</div>
<p className="text-lg leading-relaxed text-card-foreground">
I'm a 10-year-old artist who absolutely LOVES anime! Ever since I was little, I've been drawing my
favorite characters and creating my own magical worlds filled with colors, sparkles, and adventure.
</p>
<div className="flex items-center gap-3 mb-4 mt-8">
<Palette className="h-8 w-8 text-secondary flex-shrink-0" />
<h3 className="text-2xl font-bold m-0 text-card-foreground">My Art Journey</h3>
</div>
<p className="text-lg leading-relaxed text-card-foreground">
I started drawing when I was 6 years old, and I haven't stopped since! My favorite things to draw are
anime characters with big expressive eyes, colorful hair, and magical powers. I love adding rainbows,
sparkles, and special anime effect symbols like sweat drops, stars, and speed lines to make my art come
alive!
</p>
<div className="flex items-center gap-3 mb-4 mt-8">
<Heart className="h-8 w-8 text-accent flex-shrink-0" />
<h3 className="text-2xl font-bold m-0 text-card-foreground">What I Love</h3>
</div>
<ul className="space-y-3 text-lg text-card-foreground">
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Drawing anime characters with unique personalities</span>
</li>
<li className="flex items-start gap-2">
<span className="text-secondary">🌈</span>
<span>Using ALL the colors - especially rainbows!</span>
</li>
<li className="flex items-start gap-2">
<span className="text-accent"></span>
<span>Adding magical effects and sparkles to everything</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary">💫</span>
<span>Creating stories for each character I draw</span>
</li>
<li className="flex items-start gap-2">
<span className="text-secondary">🎨</span>
<span>Experimenting with different art styles and techniques</span>
</li>
</ul>
<div className="flex items-center gap-3 mb-4 mt-8">
<Sparkles className="h-8 w-8 text-primary flex-shrink-0" />
<h3 className="text-2xl font-bold m-0 text-card-foreground">My Dream</h3>
</div>
<p className="text-lg leading-relaxed text-card-foreground">
My biggest dream is to become a professional anime artist and maybe even create my own manga series one
day! I want to share my art with people all around the world and make them smile. Every drawing I create
is a step closer to that dream!
</p>
<p className="text-lg leading-relaxed text-card-foreground mt-6">
Thank you so much for visiting Paint Spark and supporting my art journey! Your encouragement means the
world to me! 💖
</p>
</div>
</Card>
{/* Fun Facts */}
<div className="grid md:grid-cols-2 gap-6">
<Card className="p-6 border-2">
<h3 className="text-xl font-bold mb-3 text-card-foreground">🎨 Favorite Tools</h3>
<p className="text-muted-foreground leading-relaxed">
Colored pencils, markers, and digital drawing tablets. I love mixing traditional and digital art!
</p>
</Card>
<Card className="p-6 border-2">
<h3 className="text-xl font-bold mb-3 text-card-foreground"> Drawing Time</h3>
<p className="text-muted-foreground leading-relaxed">
I draw every day after school and on weekends. Art is my favorite hobby!
</p>
</Card>
<Card className="p-6 border-2">
<h3 className="text-xl font-bold mb-3 text-card-foreground">🌟 Inspiration</h3>
<p className="text-muted-foreground leading-relaxed">
My favorite anime shows, nature, and my imagination. I find inspiration everywhere!
</p>
</Card>
<Card className="p-6 border-2">
<h3 className="text-xl font-bold mb-3 text-card-foreground">💫 Special Style</h3>
<p className="text-muted-foreground leading-relaxed">
Lots of sparkles, rainbows, and anime expressions. Every piece has its own magic!
</p>
</Card>
</div>
</div>
</main>
<footer className="border-t border-border py-8 text-center text-muted-foreground mt-12">
<p>© 2025 Paint Spark by Banksy Made with and 🌈</p>
</footer>
</div>
)
}

100
app/gallery/page.tsx Normal file
View File

@ -0,0 +1,100 @@
import { Navigation } from "@/components/navigation"
import { SparkleEffect } from "@/components/sparkle-effect"
import { Card } from "@/components/ui/card"
import { Palette } from "lucide-react"
export default function GalleryPage() {
const artworks = [
{
id: 1,
title: "Magical Girl Transformation",
description: "A magical girl in the middle of her transformation sequence with sparkles everywhere!",
query: "anime magical girl transformation with sparkles and rainbow effects",
},
{
id: 2,
title: "Dragon Spirit",
description: "A cute dragon spirit with colorful scales and glowing eyes",
query: "cute anime dragon spirit with rainbow scales and sparkles",
},
{
id: 3,
title: "Cherry Blossom Dreams",
description: "An anime character surrounded by cherry blossoms and petals",
query: "anime character with cherry blossoms and pink petals floating",
},
{
id: 4,
title: "Star Guardian",
description: "A hero protecting the stars with magical powers",
query: "anime star guardian with magical staff and celestial effects",
},
{
id: 5,
title: "Rainbow Warrior",
description: "A brave warrior with rainbow-colored armor and weapons",
query: "anime warrior with rainbow armor and colorful magical effects",
},
{
id: 6,
title: "Fairy Friend",
description: "A tiny fairy with glittering wings and a big smile",
query: "cute anime fairy with sparkly wings and magical dust",
},
]
return (
<div className="min-h-screen">
<Navigation />
<SparkleEffect />
<main className="container px-4 py-12">
<div className="max-w-6xl mx-auto">
{/* Header */}
<div className="text-center mb-12">
<div className="float mb-6">
<Palette className="h-16 w-16 mx-auto text-primary" />
</div>
<h1 className="text-5xl md:text-6xl font-bold mb-4 rainbow-text text-balance">Art Gallery</h1>
<p className="text-xl text-muted-foreground text-pretty">Explore my magical anime creations! 🎨</p>
</div>
{/* Gallery Grid */}
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{artworks.map((artwork) => (
<Card key={artwork.id} className="overflow-hidden hover:shadow-xl transition-shadow border-2 group">
<div className="aspect-square bg-gradient-to-br from-primary/20 via-secondary/20 to-accent/20 relative overflow-hidden">
<img
src={`/.jpg?height=400&width=400&query=${encodeURIComponent(artwork.query)}`}
alt={artwork.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
</div>
<div className="p-6">
<h3 className="text-xl font-bold mb-2 text-card-foreground text-balance">{artwork.title}</h3>
<p className="text-muted-foreground text-pretty">{artwork.description}</p>
</div>
</Card>
))}
</div>
{/* Coming Soon */}
<div className="mt-12 text-center">
<Card className="p-8 border-2 bg-gradient-to-r from-primary/5 via-secondary/5 to-accent/5">
<h2 className="text-2xl font-bold mb-3 text-card-foreground">More Art Coming Soon! 🌟</h2>
<p className="text-muted-foreground text-pretty">
I'm always creating new pieces! Check back often to see my latest anime artwork filled with rainbows and
sparkles!
</p>
</Card>
</div>
</div>
</main>
<footer className="border-t border-border py-8 text-center text-muted-foreground mt-12">
<p>© 2025 Paint Spark by Banksy Made with and 🌈</p>
</footer>
</div>
)
}

219
app/globals.css Normal file
View File

@ -0,0 +1,219 @@
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
:root {
--background: oklch(0.98 0.02 280);
--foreground: oklch(0.25 0.05 280);
--card: oklch(1 0 0);
--card-foreground: oklch(0.25 0.05 280);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.25 0.05 280);
--primary: oklch(0.65 0.25 320);
--primary-foreground: oklch(1 0 0);
--secondary: oklch(0.75 0.2 200);
--secondary-foreground: oklch(0.25 0.05 280);
--muted: oklch(0.95 0.02 280);
--muted-foreground: oklch(0.5 0.05 280);
--accent: oklch(0.85 0.15 60);
--accent-foreground: oklch(0.25 0.05 280);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(1 0 0);
--border: oklch(0.9 0.05 280);
--input: oklch(0.9 0.05 280);
--ring: oklch(0.65 0.25 320);
--chart-1: oklch(0.65 0.25 320);
--chart-2: oklch(0.75 0.2 200);
--chart-3: oklch(0.85 0.15 60);
--chart-4: oklch(0.7 0.22 350);
--chart-5: oklch(0.6 0.18 180);
--radius: 1rem;
--sidebar: oklch(0.98 0.02 280);
--sidebar-foreground: oklch(0.25 0.05 280);
--sidebar-primary: oklch(0.65 0.25 320);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.95 0.02 280);
--sidebar-accent-foreground: oklch(0.25 0.05 280);
--sidebar-border: oklch(0.9 0.05 280);
--sidebar-ring: oklch(0.65 0.25 320);
}
@theme inline {
--font-sans: "Geist", "Geist Fallback";
--font-mono: "Geist Mono", "Geist Mono Fallback";
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
position: relative;
}
/* Made rainbow gradient stronger with higher opacity */
body::before {
content: "";
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
135deg,
rgba(255, 0, 0, 0.25) 0%,
rgba(255, 154, 0, 0.25) 10%,
rgba(208, 222, 33, 0.25) 20%,
rgba(79, 220, 74, 0.25) 30%,
rgba(63, 218, 216, 0.25) 40%,
rgba(47, 201, 226, 0.25) 50%,
rgba(28, 127, 238, 0.25) 60%,
rgba(95, 21, 242, 0.25) 70%,
rgba(186, 12, 248, 0.25) 80%,
rgba(251, 7, 217, 0.25) 90%,
rgba(255, 0, 0, 0.25) 100%
);
background-size: 400% 400%;
animation: rainbow-flow 15s ease infinite;
pointer-events: none;
z-index: -1;
}
}
@keyframes sparkle {
0%,
100% {
opacity: 0;
transform: scale(0);
}
50% {
opacity: 1;
transform: scale(1);
}
}
@keyframes float {
0%,
100% {
transform: translateY(0px);
}
50% {
transform: translateY(-20px);
}
}
@keyframes rainbow {
0% {
filter: hue-rotate(0deg);
}
100% {
filter: hue-rotate(360deg);
}
}
@keyframes rainbow-flow {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
/* Updated sparkle animation to shoot outward */
@keyframes cursor-spark {
0% {
opacity: 1;
transform: translate(0, 0) scale(1) rotate(0deg);
}
100% {
opacity: 0;
transform: translate(calc(var(--vx) * 30px), calc(var(--vy) * 30px)) scale(0.3) rotate(360deg);
}
}
/* New arc animation that shoots outward */
@keyframes cursor-arc {
0% {
opacity: 0.9;
transform: translate(0, 0) scale(1);
}
100% {
opacity: 0;
transform: translate(calc(var(--vx) * 40px), calc(var(--vy) * 40px)) scale(0.5);
}
}
@keyframes cursor-rainbow {
0% {
opacity: 0.8;
transform: scale(0);
}
100% {
opacity: 0;
transform: scale(2);
}
}
.sparkle {
animation: sparkle 1.5s ease-in-out infinite;
}
.float {
animation: float 3s ease-in-out infinite;
}
.rainbow-text {
background: linear-gradient(
90deg,
oklch(0.65 0.25 320),
oklch(0.75 0.2 200),
oklch(0.85 0.15 60),
oklch(0.7 0.22 350),
oklch(0.6 0.18 180)
);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: rainbow 3s linear infinite;
}

31
app/layout.tsx Normal file
View File

@ -0,0 +1,31 @@
import type React from "react"
import type { Metadata } from "next"
import { Geist, Geist_Mono } from "next/font/google"
import { Analytics } from "@vercel/analytics/next"
import "./globals.css"
import { CursorEffects } from "@/components/cursor-effects"
const _geist = Geist({ subsets: ["latin"] })
const _geistMono = Geist_Mono({ subsets: ["latin"] })
export const metadata: Metadata = {
title: "Paint Spark - by Banksy",
description: "Amazing anime art by Banksy, a talented 10-year-old artist",
generator: "v0.app",
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className={`font-sans antialiased`}>
<CursorEffects />
{children}
<Analytics />
</body>
</html>
)
}

103
app/page.tsx Normal file
View File

@ -0,0 +1,103 @@
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { Navigation } from "@/components/navigation"
import { SparkleEffect } from "@/components/sparkle-effect"
import { Sparkles, Palette, Heart, Star } from "lucide-react"
export default function HomePage() {
return (
<div className="min-h-screen">
<Navigation />
<SparkleEffect />
<main className="container px-4 py-12">
{/* Hero Section */}
<section className="text-center py-20 relative">
<div className="float mb-8">
<Sparkles className="h-20 w-20 mx-auto text-primary" />
</div>
<h1 className="text-6xl md:text-8xl font-bold mb-6 rainbow-text text-balance">Paint Spark</h1>
<p className="text-2xl md:text-3xl mb-4 text-foreground font-semibold">by Banksy</p>
<p className="text-xl text-muted-foreground mb-8 max-w-2xl mx-auto text-pretty">
Welcome to my magical world of anime art! I'm a 10-year-old artist who loves bringing characters to life
with colors and sparkles!
</p>
<div className="flex gap-4 justify-center flex-wrap">
<Button asChild size="lg" className="text-lg">
<Link href="/gallery">
<Palette className="mr-2 h-5 w-5" />
View Gallery
</Link>
</Button>
<Button asChild size="lg" variant="outline" className="text-lg bg-transparent">
<Link href="/about">
<Star className="mr-2 h-5 w-5" />
About Me
</Link>
</Button>
</div>
</section>
{/* Features Section */}
<section className="py-12 grid md:grid-cols-3 gap-6">
<Card className="p-6 text-center hover:shadow-lg transition-shadow border-2">
<div className="mb-4 flex justify-center">
<div className="p-4 bg-primary/10 rounded-full">
<Palette className="h-8 w-8 text-primary" />
</div>
</div>
<h3 className="text-xl font-bold mb-2 text-card-foreground">Anime Art</h3>
<p className="text-muted-foreground text-pretty">
Beautiful anime characters with vibrant colors and expressive emotions
</p>
</Card>
<Card className="p-6 text-center hover:shadow-lg transition-shadow border-2">
<div className="mb-4 flex justify-center">
<div className="p-4 bg-secondary/10 rounded-full">
<Sparkles className="h-8 w-8 text-secondary" />
</div>
</div>
<h3 className="text-xl font-bold mb-2 text-card-foreground">Magical Effects</h3>
<p className="text-muted-foreground text-pretty">
Every piece is filled with sparkles, rainbows, and special anime symbols
</p>
</Card>
<Card className="p-6 text-center hover:shadow-lg transition-shadow border-2">
<div className="mb-4 flex justify-center">
<div className="p-4 bg-accent/10 rounded-full">
<Heart className="h-8 w-8 text-accent" />
</div>
</div>
<h3 className="text-xl font-bold mb-2 text-card-foreground">Made with Love</h3>
<p className="text-muted-foreground text-pretty">
Each artwork is created with passion and lots of imagination
</p>
</Card>
</section>
{/* Call to Action */}
<section className="py-20 text-center">
<div className="max-w-3xl mx-auto bg-gradient-to-r from-primary/10 via-secondary/10 to-accent/10 rounded-2xl p-12 border-2 border-border">
<h2 className="text-4xl font-bold mb-4 text-foreground text-balance">Support My Art Journey! 🌟</h2>
<p className="text-lg text-muted-foreground mb-6 text-pretty">
Help me continue creating amazing anime art and bring more magical characters to life!
</p>
<Button asChild size="lg" className="text-lg">
<Link href="/sponsor">
<Heart className="mr-2 h-5 w-5" />
Become a Sponsor
</Link>
</Button>
</div>
</section>
</main>
<footer className="border-t border-border py-8 text-center text-muted-foreground">
<p>© 2025 Paint Spark by Banksy Made with and 🌈</p>
</footer>
</div>
)
}

171
app/sponsor/page.tsx Normal file
View File

@ -0,0 +1,171 @@
import { Navigation } from "@/components/navigation"
import { SparkleEffect } from "@/components/sparkle-effect"
import { Card } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Heart, Star, Sparkles, Gift } from "lucide-react"
export default function SponsorPage() {
const tiers = [
{
name: "Sparkle Friend",
icon: Sparkles,
amount: "$5/month",
color: "text-primary",
benefits: [
"Thank you message on social media",
"Early access to new artwork",
"Monthly digital wallpaper",
"Supporter badge on website",
],
},
{
name: "Rainbow Supporter",
icon: Star,
amount: "$15/month",
color: "text-secondary",
benefits: [
"Everything from Sparkle Friend",
"Exclusive behind-the-scenes content",
"Monthly art process videos",
"Vote on next artwork themes",
"Personalized thank you card",
],
},
{
name: "Magic Patron",
icon: Heart,
amount: "$30/month",
color: "text-accent",
benefits: [
"Everything from Rainbow Supporter",
"Custom artwork request once per year",
"Physical print of your favorite piece",
"Video call to see art process live",
"Name in special supporters gallery",
],
},
]
return (
<div className="min-h-screen">
<Navigation />
<SparkleEffect />
<main className="container px-4 py-12">
<div className="max-w-6xl mx-auto">
{/* Header */}
<div className="text-center mb-12">
<div className="float mb-6">
<Heart className="h-16 w-16 mx-auto text-primary" />
</div>
<h1 className="text-5xl md:text-6xl font-bold mb-4 rainbow-text text-balance">Become a Sponsor</h1>
<p className="text-xl text-muted-foreground mb-6 text-pretty">
Help support my art journey and get amazing rewards! 💖
</p>
</div>
{/* Why Sponsor Section */}
<Card className="p-8 md:p-12 mb-12 border-2">
<div className="flex items-center gap-3 mb-6">
<Gift className="h-8 w-8 text-primary flex-shrink-0" />
<h2 className="text-3xl font-bold m-0 text-card-foreground">Why Sponsor Me?</h2>
</div>
<p className="text-lg leading-relaxed text-card-foreground mb-4">
Your support helps me continue creating amazing anime art and pursuing my dream of becoming a professional
artist! With your help, I can:
</p>
<ul className="space-y-3 text-lg text-card-foreground">
<li className="flex items-start gap-2">
<span className="text-primary">🎨</span>
<span>Buy better art supplies and tools</span>
</li>
<li className="flex items-start gap-2">
<span className="text-secondary">📚</span>
<span>Take art classes and learn new techniques</span>
</li>
<li className="flex items-start gap-2">
<span className="text-accent">💻</span>
<span>Get digital art software and equipment</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Create more artwork to share with everyone</span>
</li>
<li className="flex items-start gap-2">
<span className="text-secondary">🌟</span>
<span>Attend art workshops and conventions</span>
</li>
</ul>
</Card>
{/* Sponsorship Tiers */}
<div className="mb-12">
<h2 className="text-3xl font-bold text-center mb-8 text-foreground">Choose Your Support Level</h2>
<div className="grid md:grid-cols-3 gap-6">
{tiers.map((tier) => {
const Icon = tier.icon
return (
<Card key={tier.name} className="p-6 border-2 hover:shadow-xl transition-shadow flex flex-col">
<div className="text-center mb-6">
<div className="mb-4 flex justify-center">
<div className="p-4 bg-primary/10 rounded-full">
<Icon className={`h-10 w-10 ${tier.color}`} />
</div>
</div>
<h3 className="text-2xl font-bold mb-2 text-card-foreground">{tier.name}</h3>
<p className="text-3xl font-bold text-primary">{tier.amount}</p>
</div>
<ul className="space-y-3 mb-6 flex-grow">
{tier.benefits.map((benefit, index) => (
<li key={index} className="flex items-start gap-2 text-muted-foreground">
<span className="text-primary mt-1"></span>
<span className="text-sm leading-relaxed">{benefit}</span>
</li>
))}
</ul>
<Button className="w-full" size="lg">
<Heart className="mr-2 h-4 w-4" />
Support Now
</Button>
</Card>
)
})}
</div>
</div>
{/* One-Time Support */}
<Card className="p-8 border-2 bg-gradient-to-r from-primary/5 via-secondary/5 to-accent/5">
<div className="text-center">
<h2 className="text-3xl font-bold mb-4 text-card-foreground">Prefer a One-Time Gift?</h2>
<p className="text-lg text-muted-foreground mb-6 text-pretty">
You can also support my art with a one-time contribution of any amount! Every bit helps me continue
creating magical anime art! 🌈
</p>
<Button size="lg" variant="outline">
<Sparkles className="mr-2 h-5 w-5" />
Make a One-Time Gift
</Button>
</div>
</Card>
{/* Thank You Message */}
<div className="mt-12 text-center">
<Card className="p-8 border-2">
<h2 className="text-2xl font-bold mb-3 text-card-foreground">Thank You! 💖</h2>
<p className="text-lg text-muted-foreground text-pretty">
Your support means everything to me and helps me keep creating art that brings joy to others. Together,
we can make the world more colorful and magical! Thank you for believing in my dreams! 🌟
</p>
</Card>
</div>
</div>
</main>
<footer className="border-t border-border py-8 text-center text-muted-foreground mt-12">
<p>© 2025 Paint Spark by Banksy Made with and 🌈</p>
</footer>
</div>
)
}

21
components.json Normal file
View File

@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}

View File

@ -0,0 +1,130 @@
"use client"
import type React from "react"
import { useEffect, useState } from "react"
interface Particle {
id: number
x: number
y: number
type: "sparkle" | "rainbow"
color?: string
vx?: number
vy?: number
angle?: number
}
export function CursorEffects() {
const [particles, setParticles] = useState<Particle[]>([])
useEffect(() => {
let particleId = 0
let lastTime = Date.now()
const handleMouseMove = (e: MouseEvent) => {
const now = Date.now()
// Throttle particle creation to every 50ms
if (now - lastTime < 50) return
lastTime = now
const newParticles: Particle[] = []
for (let i = 0; i < 3; i++) {
const angle = Math.random() * Math.PI * 2
const speed = 2 + Math.random() * 3
newParticles.push({
id: particleId++,
x: e.clientX,
y: e.clientY,
type: "sparkle",
color: [
"#ff0000",
"#ff9a00",
"#d0de21",
"#4fdc4a",
"#3fdad8",
"#2fc9e2",
"#1c7fee",
"#5f15f2",
"#ba0cf8",
"#fb07d9",
][Math.floor(Math.random() * 10)],
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
angle: angle,
})
}
for (let i = 0; i < 2; i++) {
const angle = Math.random() * Math.PI * 2
const speed = 3 + Math.random() * 2
newParticles.push({
id: particleId++,
x: e.clientX,
y: e.clientY,
type: "rainbow",
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
angle: angle,
})
}
setParticles((prev) => [...prev, ...newParticles])
// Remove old particles after animation
setTimeout(() => {
setParticles((prev) => prev.filter((p) => !newParticles.find((np) => np.id === p.id)))
}, 1000)
}
window.addEventListener("mousemove", handleMouseMove)
return () => window.removeEventListener("mousemove", handleMouseMove)
}, [])
return (
<div className="pointer-events-none fixed inset-0 z-50">
{particles.map((particle) => (
<div
key={particle.id}
className="absolute"
style={{
left: particle.x,
top: particle.y,
}}
>
{particle.type === "sparkle" ? (
<div
className="h-3 w-3 -translate-x-1/2 -translate-y-1/2"
style={
{
animation: "cursor-spark 0.8s ease-out forwards",
"--vx": particle.vx,
"--vy": particle.vy,
} as React.CSSProperties
}
>
<svg viewBox="0 0 24 24" fill={particle.color}>
<path d="M12 0L14.59 9.41L24 12L14.59 14.59L12 24L9.41 14.59L0 12L9.41 9.41L12 0Z" />
</svg>
</div>
) : (
<div
className="h-12 w-2 -translate-x-1/2 -translate-y-1/2 rounded-full"
style={
{
background:
"linear-gradient(to bottom, #ff0000, #ff9a00, #d0de21, #4fdc4a, #3fdad8, #2fc9e2, #1c7fee, #5f15f2, #ba0cf8, #fb07d9)",
animation: "cursor-arc 0.7s ease-out forwards",
transform: `rotate(${(particle.angle || 0) * (180 / Math.PI)}deg)`,
"--vx": particle.vx,
"--vy": particle.vy,
} as React.CSSProperties
}
/>
)}
</div>
))}
</div>
)
}

43
components/navigation.tsx Normal file
View File

@ -0,0 +1,43 @@
"use client"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { Sparkles } from "lucide-react"
import { cn } from "@/lib/utils"
export function Navigation() {
const pathname = usePathname()
const links = [
{ href: "/", label: "Home" },
{ href: "/about", label: "About Banksy" },
{ href: "/gallery", label: "Gallery" },
{ href: "/sponsor", label: "Sponsor" },
]
return (
<nav className="sticky top-0 z-50 w-full border-b border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center justify-between px-4">
<Link href="/" className="flex items-center gap-2 font-bold text-xl">
<Sparkles className="h-6 w-6 text-primary" />
<span className="rainbow-text">Paint Spark</span>
</Link>
<div className="flex items-center gap-6">
{links.map((link) => (
<Link
key={link.href}
href={link.href}
className={cn(
"text-sm font-medium transition-colors hover:text-primary",
pathname === link.href ? "text-primary" : "text-muted-foreground",
)}
>
{link.label}
</Link>
))}
</div>
</div>
</nav>
)
}

View File

@ -0,0 +1,33 @@
"use client"
import { useEffect, useState } from "react"
export function SparkleEffect() {
const [sparkles, setSparkles] = useState<Array<{ id: number; x: number; y: number; delay: number }>>([])
useEffect(() => {
const newSparkles = Array.from({ length: 20 }, (_, i) => ({
id: i,
x: Math.random() * 100,
y: Math.random() * 100,
delay: Math.random() * 2,
}))
setSparkles(newSparkles)
}, [])
return (
<div className="fixed inset-0 pointer-events-none overflow-hidden">
{sparkles.map((sparkle) => (
<div
key={sparkle.id}
className="absolute w-2 h-2 bg-primary rounded-full sparkle"
style={{
left: `${sparkle.x}%`,
top: `${sparkle.y}%`,
animationDelay: `${sparkle.delay}s`,
}}
/>
))}
</div>
)
}

View File

@ -0,0 +1,11 @@
'use client'
import * as React from 'react'
import {
ThemeProvider as NextThemesProvider,
type ThemeProviderProps,
} from 'next-themes'
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

60
components/ui/button.tsx Normal file
View File

@ -0,0 +1,60 @@
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive:
'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
outline:
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost:
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
icon: 'size-9',
'icon-sm': 'size-8',
'icon-lg': 'size-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
},
)
function Button({
className,
variant,
size,
asChild = false,
...props
}: React.ComponentProps<'button'> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : 'button'
return (
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }

92
components/ui/card.tsx Normal file
View File

@ -0,0 +1,92 @@
import * as React from 'react'
import { cn } from '@/lib/utils'
function Card({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card"
className={cn(
'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm',
className,
)}
{...props}
/>
)
}
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-header"
className={cn(
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
className,
)}
{...props}
/>
)
}
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-title"
className={cn('leading-none font-semibold', className)}
{...props}
/>
)
}
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-description"
className={cn('text-muted-foreground text-sm', className)}
{...props}
/>
)
}
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-action"
className={cn(
'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
className,
)}
{...props}
/>
)
}
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-content"
className={cn('px-6', className)}
{...props}
/>
)
}
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-footer"
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
{...props}
/>
)
}
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
}

6
lib/utils.ts Normal file
View File

@ -0,0 +1,6 @@
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

14
next.config.mjs Normal file
View File

@ -0,0 +1,14 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
images: {
unoptimized: true,
},
}
export default nextConfig

73
package.json Normal file
View File

@ -0,0 +1,73 @@
{
"name": "my-v0-project",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "next build",
"dev": "next dev",
"lint": "eslint .",
"start": "next start"
},
"dependencies": {
"@hookform/resolvers": "^3.10.0",
"@radix-ui/react-accordion": "1.2.2",
"@radix-ui/react-alert-dialog": "1.1.4",
"@radix-ui/react-aspect-ratio": "1.1.1",
"@radix-ui/react-avatar": "1.1.2",
"@radix-ui/react-checkbox": "1.1.3",
"@radix-ui/react-collapsible": "1.1.2",
"@radix-ui/react-context-menu": "2.2.4",
"@radix-ui/react-dialog": "1.1.4",
"@radix-ui/react-dropdown-menu": "2.1.4",
"@radix-ui/react-hover-card": "1.1.4",
"@radix-ui/react-label": "2.1.1",
"@radix-ui/react-menubar": "1.1.4",
"@radix-ui/react-navigation-menu": "1.2.3",
"@radix-ui/react-popover": "1.1.4",
"@radix-ui/react-progress": "1.1.1",
"@radix-ui/react-radio-group": "1.2.2",
"@radix-ui/react-scroll-area": "1.2.2",
"@radix-ui/react-select": "2.1.4",
"@radix-ui/react-separator": "1.1.1",
"@radix-ui/react-slider": "1.2.2",
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-switch": "1.1.2",
"@radix-ui/react-tabs": "1.1.2",
"@radix-ui/react-toast": "1.2.4",
"@radix-ui/react-toggle": "1.1.1",
"@radix-ui/react-toggle-group": "1.1.1",
"@radix-ui/react-tooltip": "1.1.6",
"@vercel/analytics": "latest",
"autoprefixer": "^10.4.20",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "1.0.4",
"date-fns": "4.1.0",
"embla-carousel-react": "8.5.1",
"input-otp": "1.4.1",
"lucide-react": "^0.454.0",
"next": "16.0.0",
"next-themes": "^0.4.6",
"react": "19.2.0",
"react-day-picker": "9.8.0",
"react-dom": "19.2.0",
"react-hook-form": "^7.60.0",
"react-resizable-panels": "^2.1.7",
"recharts": "2.15.4",
"sonner": "^1.7.4",
"tailwind-merge": "^2.5.5",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.9",
"zod": "3.25.76"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.9",
"@types/node": "^22",
"@types/react": "^19",
"@types/react-dom": "^19",
"postcss": "^8.5",
"tailwindcss": "^4.1.9",
"tw-animate-css": "1.3.3",
"typescript": "^5"
}
}

3212
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

8
postcss.config.mjs Normal file
View File

@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
'@tailwindcss/postcss': {},
},
}
export default config

BIN
public/placeholder-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="215" height="48" fill="none"><path fill="#000" d="M57.588 9.6h6L73.828 38h-5.2l-2.36-6.88h-11.36L52.548 38h-5.2l10.24-28.4Zm7.16 17.16-4.16-12.16-4.16 12.16h8.32Zm23.694-2.24c-.186-1.307-.706-2.32-1.56-3.04-.853-.72-1.866-1.08-3.04-1.08-1.68 0-2.986.613-3.92 1.84-.906 1.227-1.36 2.947-1.36 5.16s.454 3.933 1.36 5.16c.934 1.227 2.24 1.84 3.92 1.84 1.254 0 2.307-.373 3.16-1.12.854-.773 1.387-1.867 1.6-3.28l5.12.24c-.186 1.68-.733 3.147-1.64 4.4-.906 1.227-2.08 2.173-3.52 2.84-1.413.667-2.986 1-4.72 1-2.08 0-3.906-.453-5.48-1.36-1.546-.907-2.76-2.2-3.64-3.88-.853-1.68-1.28-3.627-1.28-5.84 0-2.24.427-4.187 1.28-5.84.88-1.68 2.094-2.973 3.64-3.88 1.574-.907 3.4-1.36 5.48-1.36 1.68 0 3.227.32 4.64.96 1.414.64 2.56 1.56 3.44 2.76.907 1.2 1.454 2.6 1.64 4.2l-5.12.28Zm11.486-7.72.12 3.4c.534-1.227 1.307-2.173 2.32-2.84 1.04-.693 2.267-1.04 3.68-1.04 1.494 0 2.76.387 3.8 1.16 1.067.747 1.827 1.813 2.28 3.2.507-1.44 1.294-2.52 2.36-3.24 1.094-.747 2.414-1.12 3.96-1.12 1.414 0 2.64.307 3.68.92s1.84 1.52 2.4 2.72c.56 1.2.84 2.667.84 4.4V38h-4.96V25.92c0-1.813-.293-3.187-.88-4.12-.56-.96-1.413-1.44-2.56-1.44-.906 0-1.68.213-2.32.64-.64.427-1.133 1.053-1.48 1.88-.32.827-.48 1.84-.48 3.04V38h-4.56V25.92c0-1.2-.133-2.213-.4-3.04-.24-.827-.626-1.453-1.16-1.88-.506-.427-1.133-.64-1.88-.64-.906 0-1.68.227-2.32.68-.64.427-1.133 1.053-1.48 1.88-.32.827-.48 1.827-.48 3V38h-4.96V16.8h4.48Zm26.723 10.6c0-2.24.427-4.187 1.28-5.84.854-1.68 2.067-2.973 3.64-3.88 1.574-.907 3.4-1.36 5.48-1.36 1.84 0 3.494.413 4.96 1.24 1.467.827 2.64 2.08 3.52 3.76.88 1.653 1.347 3.693 1.4 6.12v1.32h-15.08c.107 1.813.614 3.227 1.52 4.24.907.987 2.134 1.48 3.68 1.48.987 0 1.88-.253 2.68-.76a4.803 4.803 0 0 0 1.84-2.2l5.08.36c-.64 2.027-1.84 3.64-3.6 4.84-1.733 1.173-3.733 1.76-6 1.76-2.08 0-3.906-.453-5.48-1.36-1.573-.907-2.786-2.2-3.64-3.88-.853-1.68-1.28-3.627-1.28-5.84Zm15.16-2.04c-.213-1.733-.76-3.013-1.64-3.84-.853-.827-1.893-1.24-3.12-1.24-1.44 0-2.6.453-3.48 1.36-.88.88-1.44 2.12-1.68 3.72h9.92ZM163.139 9.6V38h-5.04V9.6h5.04Zm8.322 7.2.24 5.88-.64-.36c.32-2.053 1.094-3.56 2.32-4.52 1.254-.987 2.787-1.48 4.6-1.48 2.32 0 4.107.733 5.36 2.2 1.254 1.44 1.88 3.387 1.88 5.84V38h-4.96V25.92c0-1.253-.12-2.28-.36-3.08-.24-.8-.64-1.413-1.2-1.84-.533-.427-1.253-.64-2.16-.64-1.44 0-2.573.48-3.4 1.44-.8.933-1.2 2.307-1.2 4.12V38h-4.96V16.8h4.48Zm30.003 7.72c-.186-1.307-.706-2.32-1.56-3.04-.853-.72-1.866-1.08-3.04-1.08-1.68 0-2.986.613-3.92 1.84-.906 1.227-1.36 2.947-1.36 5.16s.454 3.933 1.36 5.16c.934 1.227 2.24 1.84 3.92 1.84 1.254 0 2.307-.373 3.16-1.12.854-.773 1.387-1.867 1.6-3.28l5.12.24c-.186 1.68-.733 3.147-1.64 4.4-.906 1.227-2.08 2.173-3.52 2.84-1.413.667-2.986 1-4.72 1-2.08 0-3.906-.453-5.48-1.36-1.546-.907-2.76-2.2-3.64-3.88-.853-1.68-1.28-3.627-1.28-5.84 0-2.24.427-4.187 1.28-5.84.88-1.68 2.094-2.973 3.64-3.88 1.574-.907 3.4-1.36 5.48-1.36 1.68 0 3.227.32 4.64.96 1.414.64 2.56 1.56 3.44 2.76.907 1.2 1.454 2.6 1.64 4.2l-5.12.28Zm11.443 8.16V38h-5.6v-5.32h5.6Z"/><path fill="#171717" fill-rule="evenodd" d="m7.839 40.783 16.03-28.054L20 6 0 40.783h7.839Zm8.214 0H40L27.99 19.894l-4.02 7.032 3.976 6.914H20.02l-3.967 6.943Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
public/placeholder-user.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
public/placeholder.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

1
public/placeholder.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1200" fill="none"><rect width="1200" height="1200" fill="#EAEAEA" rx="3"/><g opacity=".5"><g opacity=".5"><path fill="#FAFAFA" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/></g><path stroke="url(#a)" stroke-width="2.418" d="M0-1.209h553.581" transform="scale(1 -1) rotate(45 1163.11 91.165)"/><path stroke="url(#b)" stroke-width="2.418" d="M404.846 598.671h391.726"/><path stroke="url(#c)" stroke-width="2.418" d="M599.5 795.742V404.017"/><path stroke="url(#d)" stroke-width="2.418" d="m795.717 796.597-391.441-391.44"/><path fill="#fff" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/><g clip-path="url(#e)"><path fill="#666" fill-rule="evenodd" d="M616.426 586.58h-31.434v16.176l3.553-3.554.531-.531h9.068l.074-.074 8.463-8.463h2.565l7.18 7.181V586.58Zm-15.715 14.654 3.698 3.699 1.283 1.282-2.565 2.565-1.282-1.283-5.2-5.199h-6.066l-5.514 5.514-.073.073v2.876a2.418 2.418 0 0 0 2.418 2.418h26.598a2.418 2.418 0 0 0 2.418-2.418v-8.317l-8.463-8.463-7.181 7.181-.071.072Zm-19.347 5.442v4.085a6.045 6.045 0 0 0 6.046 6.045h26.598a6.044 6.044 0 0 0 6.045-6.045v-7.108l1.356-1.355-1.282-1.283-.074-.073v-17.989h-38.689v23.43l-.146.146.146.147Z" clip-rule="evenodd"/></g><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/></g><defs><linearGradient id="a" x1="554.061" x2="-.48" y1=".083" y2=".087" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="796.912" x2="404.507" y1="599.963" y2="599.965" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="c" x1="600.792" x2="600.794" y1="403.677" y2="796.082" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="d" x1="404.85" x2="796.972" y1="403.903" y2="796.02" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><clipPath id="e"><path fill="#fff" d="M581.364 580.535h38.689v38.689h-38.689z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

125
styles/globals.css Normal file
View File

@ -0,0 +1,125 @@
@import 'tailwindcss';
@import 'tw-animate-css';
@custom-variant dark (&:is(.dark *));
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--radius: 0.625rem;
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.145 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.145 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.396 0.141 25.723);
--destructive-foreground: oklch(0.637 0.237 25.331);
--border: oklch(0.269 0 0);
--input: oklch(0.269 0 0);
--ring: oklch(0.439 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(0.269 0 0);
--sidebar-ring: oklch(0.439 0 0);
}
@theme inline {
--font-sans: 'Geist', 'Geist Fallback';
--font-mono: 'Geist Mono', 'Geist Mono Fallback';
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}

27
tsconfig.json Normal file
View File

@ -0,0 +1,27 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"target": "ES6",
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}