Updated Frontend

This commit is contained in:
2026-02-21 15:02:57 +05:30
parent a8a756457f
commit 29fc82c104
12 changed files with 3767 additions and 72 deletions

75
app/components/CTA.tsx Normal file
View File

@@ -0,0 +1,75 @@
"use client";
import { motion } from "framer-motion";
import { ArrowRight, Sparkles } from "lucide-react";
import Link from "next/link";
export default function CTA() {
return (
<section className="py-24 bg-white relative overflow-hidden">
{/* Background Elements */}
<div className="absolute inset-0">
<div className="absolute top-0 left-1/4 w-96 h-96 bg-lime-100 rounded-full blur-3xl opacity-50" />
<div className="absolute bottom-0 right-1/4 w-96 h-96 bg-sky-100 rounded-full blur-3xl opacity-50" />
</div>
<div className="relative max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
>
<div className="inline-flex items-center gap-2 bg-black text-white px-4 py-2 text-xs font-medium tracking-wider rounded-full mb-8">
<Sparkles className="w-4 h-4 text-lime-400" />
LIMITED TIME
</div>
<h2 className="text-4xl sm:text-5xl lg:text-6xl font-black tracking-tight text-black mb-6 leading-tight">
Ready to Showcase
<br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-lime-400 to-lime-600">
Your Masterpiece?
</span>
</h2>
<p className="text-zinc-600 text-lg sm:text-xl max-w-2xl mx-auto mb-10">
Join hundreds of talented artists from SJEC in this creative
celebration. Submit your artwork and let the world vote for your
talent.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link
href="/register"
className="inline-flex items-center justify-center gap-2 bg-lime-400 text-black px-10 py-5 text-base font-bold tracking-wide hover:bg-lime-300 transition-all hover:scale-105 rounded-full shadow-xl shadow-lime-400/25"
>
REGISTER NOW
<ArrowRight className="w-5 h-5" />
</Link>
<Link
href="/rules"
className="inline-flex items-center justify-center gap-2 bg-white text-black px-10 py-5 text-base font-bold tracking-wide border-2 border-black hover:bg-black hover:text-white transition-all rounded-full"
>
VIEW RULES
</Link>
</div>
{/* Deadline Notice */}
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.3 }}
className="mt-12 inline-flex items-center gap-3 bg-zinc-100 px-6 py-3 rounded-full"
>
<span className="w-3 h-3 bg-red-500 rounded-full animate-pulse" />
<span className="text-zinc-700 font-medium">
Submissions close on <span className="text-black font-bold">February 28, 2026</span>
</span>
</motion.div>
</motion.div>
</div>
</section>
);
}

View File

@@ -0,0 +1,131 @@
"use client";
import { motion } from "framer-motion";
import { Palette, Monitor, FileImage, ArrowRight } from "lucide-react";
import Link from "next/link";
const categories = [
{
icon: Monitor,
title: "Digital Art",
description:
"Create stunning digital masterpieces using any software of your choice. From illustrations to photo manipulations.",
color: "from-violet-500 to-purple-600",
bgColor: "bg-violet-50",
},
{
icon: Palette,
title: "Paintings",
description:
"Traditional paintings in any medium - oil, acrylic, watercolor. Capture the essence of classic artistry.",
color: "from-orange-500 to-red-500",
bgColor: "bg-orange-50",
},
{
icon: FileImage,
title: "Poster Making",
description:
"Design impactful posters that communicate powerful messages. Blend creativity with purpose.",
color: "from-lime-500 to-green-500",
bgColor: "bg-lime-50",
},
];
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.2,
},
},
};
const itemVariants = {
hidden: { opacity: 0, y: 30 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.6,
},
},
};
export default function Categories() {
return (
<section className="py-24 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-16"
>
<span className="inline-block bg-lime-400 text-black px-4 py-1.5 text-xs font-bold tracking-wider rounded-full mb-4">
CATEGORIES
</span>
<h2 className="text-4xl sm:text-5xl font-black tracking-tight text-black mb-4">
Three Ways to
<span className="text-transparent bg-clip-text bg-gradient-to-r from-lime-400 to-lime-600">
{" "}
Express
</span>
</h2>
<p className="text-zinc-600 text-lg max-w-2xl mx-auto">
Choose your canvas, unleash your creativity. Each category offers a
unique way to showcase your artistic vision.
</p>
</motion.div>
{/* Categories Grid */}
<motion.div
variants={containerVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
className="grid md:grid-cols-3 gap-8"
>
{categories.map((category) => (
<motion.div
key={category.title}
variants={itemVariants}
className={`group relative ${category.bgColor} rounded-3xl p-8 hover:shadow-2xl transition-all duration-500 overflow-hidden`}
>
{/* Background Gradient on Hover */}
<div
className={`absolute inset-0 bg-gradient-to-br ${category.color} opacity-0 group-hover:opacity-10 transition-opacity duration-500`}
/>
{/* Icon */}
<div
className={`w-16 h-16 rounded-2xl bg-gradient-to-br ${category.color} flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300`}
>
<category.icon className="w-8 h-8 text-white" />
</div>
{/* Content */}
<h3 className="text-2xl font-bold text-black mb-3">
{category.title}
</h3>
<p className="text-zinc-600 mb-6 leading-relaxed">
{category.description}
</p>
{/* Link */}
<Link
href="/submit"
className="inline-flex items-center gap-2 text-black font-semibold group-hover:gap-4 transition-all"
>
Submit Now
<ArrowRight className="w-4 h-4" />
</Link>
</motion.div>
))}
</motion.div>
</div>
</section>
);
}

111
app/components/Footer.tsx Normal file
View File

@@ -0,0 +1,111 @@
"use client";
import Link from "next/link";
import { Diamond, Mail, Instagram, Twitter } from "lucide-react";
const footerLinks = {
competition: [
{ href: "/register", label: "Register" },
{ href: "/submit", label: "Submit Art" },
{ href: "/gallery", label: "Gallery" },
{ href: "/rules", label: "Rules" },
],
information: [
{ href: "/about", label: "About" },
{ href: "/faq", label: "FAQ" },
{ href: "/contact", label: "Contact" },
],
};
export default function Footer() {
return (
<footer className="bg-black text-white">
{/* Main Footer */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12">
{/* Brand */}
<div className="lg:col-span-2">
<Link href="/" className="flex items-center gap-2 mb-6">
<Diamond className="w-8 h-8 text-lime-400" />
<span className="text-2xl font-black tracking-tight">ARTSPLASH</span>
</Link>
<p className="text-zinc-400 max-w-md mb-6 leading-relaxed">
ArtSplash is SJEC's premier art competition celebrating creativity
across Digital Art, Paintings, and Poster Making. Join us in this
vibrant celebration of artistic expression.
</p>
<div className="flex gap-4">
<a
href="#"
className="w-10 h-10 rounded-full bg-zinc-800 flex items-center justify-center hover:bg-lime-400 hover:text-black transition-colors"
>
<Instagram className="w-5 h-5" />
</a>
<a
href="#"
className="w-10 h-10 rounded-full bg-zinc-800 flex items-center justify-center hover:bg-lime-400 hover:text-black transition-colors"
>
<Twitter className="w-5 h-5" />
</a>
<a
href="mailto:artsplash@sjec.ac.in"
className="w-10 h-10 rounded-full bg-zinc-800 flex items-center justify-center hover:bg-lime-400 hover:text-black transition-colors"
>
<Mail className="w-5 h-5" />
</a>
</div>
</div>
{/* Competition Links */}
<div>
<h3 className="text-lg font-bold mb-4">Competition</h3>
<ul className="space-y-3">
{footerLinks.competition.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-zinc-400 hover:text-lime-400 transition-colors"
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
{/* Information Links */}
<div>
<h3 className="text-lg font-bold mb-4">Information</h3>
<ul className="space-y-3">
{footerLinks.information.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-zinc-400 hover:text-lime-400 transition-colors"
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
</div>
</div>
{/* Bottom Bar */}
<div className="border-t border-zinc-800">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div className="flex flex-col sm:flex-row items-center justify-between gap-4">
<p className="text-zinc-500 text-sm">
© 2026 ArtSplash. All rights reserved.
</p>
<div className="flex items-center gap-2 text-zinc-500 text-sm">
<span>Powered by</span>
<span className="text-lime-400 font-bold">Sceptix</span>
</div>
</div>
</div>
</div>
</footer>
);
}

191
app/components/Hero.tsx Normal file
View File

@@ -0,0 +1,191 @@
"use client";
import { useEffect, useRef, useCallback } from "react";
import Link from "next/link";
import gsap from "gsap";
const GRID_COLS = 20;
const GRID_ROWS = 12;
function TileGrid() {
const gridRef = useRef<HTMLDivElement>(null);
const tilesRef = useRef<(HTMLDivElement | null)[]>([]);
const handleMouseEnter = useCallback((index: number) => {
const tile = tilesRef.current[index];
if (tile) {
gsap.to(tile, {
rotateY: 180,
duration: 0.4,
ease: "power2.out",
});
}
}, []);
const handleMouseLeave = useCallback((index: number) => {
const tile = tilesRef.current[index];
if (tile) {
gsap.to(tile, {
rotateY: 0,
duration: 0.4,
ease: "power2.out",
});
}
}, []);
return (
<div
ref={gridRef}
className="absolute inset-0 grid z-0"
style={{
gridTemplateColumns: `repeat(${GRID_COLS}, 1fr)`,
gridTemplateRows: `repeat(${GRID_ROWS}, 1fr)`,
}}
>
{Array.from({ length: GRID_COLS * GRID_ROWS }).map((_, index) => (
<div
key={index}
onMouseEnter={() => handleMouseEnter(index)}
onMouseLeave={() => handleMouseLeave(index)}
className="cursor-pointer"
style={{ perspective: "500px" }}
>
<div
ref={(el) => { tilesRef.current[index] = el; }}
className="w-full h-full relative"
style={{ transformStyle: "preserve-3d" }}
>
{/* Front - Black */}
<div
className="absolute inset-0 bg-black border border-zinc-900"
style={{ backfaceVisibility: "hidden" }}
/>
{/* Back - White */}
<div
className="absolute inset-0 bg-white"
style={{
backfaceVisibility: "hidden",
transform: "rotateY(180deg)",
}}
/>
</div>
</div>
))}
</div>
);
}
export default function Hero() {
const headingRef = useRef<HTMLHeadingElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Animate heading on mount
if (headingRef.current) {
gsap.fromTo(
headingRef.current,
{ opacity: 0, y: 50 },
{ opacity: 1, y: 0, duration: 1, ease: "power3.out", delay: 0.3 }
);
}
if (contentRef.current) {
gsap.fromTo(
contentRef.current.children,
{ opacity: 0, y: 30 },
{ opacity: 1, y: 0, duration: 0.8, stagger: 0.15, ease: "power3.out", delay: 0.5 }
);
}
}, []);
return (
<section className="relative min-h-screen bg-black overflow-hidden pt-28">
{/* Tile Grid Background */}
<TileGrid />
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-full pointer-events-none">
<div className="flex items-center justify-center min-h-[calc(100vh-12rem)] pb-20">
{/* Center Content */}
<div className="text-center relative z-10">
<div className="inline-flex items-center gap-2 bg-lime-400 text-black px-5 py-2.5 text-xs font-bold tracking-widest rounded-full mb-10 pointer-events-auto">
<span className="w-2 h-2 bg-black rounded-full animate-pulse" />
FEBRUARY 2026
</div>
<h1
ref={headingRef}
className="text-6xl sm:text-7xl lg:text-8xl xl:text-9xl font-black tracking-tighter text-white leading-[0.85] mb-8"
style={{
WebkitTextStroke: "2px black",
paintOrder: "stroke fill",
}}
>
<span className="block">UNLEASH</span>
<span
className="block text-lime-400 drop-shadow-[0_0_30px_rgba(163,230,53,0.5)]"
style={{
WebkitTextStroke: "2px black",
paintOrder: "stroke fill",
}}
>
YOUR ART
</span>
</h1>
<div ref={contentRef}>
<p className="text-zinc-400 text-base sm:text-lg max-w-lg mx-auto mb-10 leading-relaxed font-light">
From canvas to screen, showcase your creativity and let your
artwork speak to the world.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center pointer-events-auto">
<Link
href="/register"
className="inline-flex items-center justify-center gap-2 bg-lime-400 text-black px-10 py-4 text-sm font-bold tracking-wider hover:bg-lime-300 transition-all hover:scale-105 rounded-full shadow-[0_0_30px_rgba(163,230,53,0.3)]"
>
JOIN COMPETITION
</Link>
<Link
href="/gallery"
className="inline-flex items-center justify-center gap-2 bg-transparent text-white px-10 py-4 text-sm font-bold tracking-wider hover:bg-white/10 transition-all rounded-full border border-zinc-700 hover:border-zinc-500"
>
EXPLORE GALLERY
</Link>
</div>
</div>
</div>
</div>
{/* Scroll Indicator - positioned above the marquee */}
<div className="absolute bottom-28 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 text-zinc-500 z-10">
<span className="text-[10px] tracking-[0.3em] uppercase">Scroll</span>
<div className="w-px h-8 bg-gradient-to-b from-zinc-500 to-transparent" />
</div>
</div>
{/* Bottom Marquee */}
<div className="absolute bottom-0 left-0 right-0 bg-lime-400 text-black py-3 overflow-hidden z-10">
<div className="animate-marquee-slow whitespace-nowrap flex items-center">
{Array(8)
.fill(null)
.map((_, i) => (
<div key={i} className="flex items-center">
<span className="text-xl sm:text-2xl font-black tracking-tight mx-6 uppercase">
ArtSplash
</span>
<span className="text-black/40 mx-4"></span>
<span className="text-xl sm:text-2xl font-black tracking-tight mx-6 uppercase text-black/60">
SJEC
</span>
<span className="text-black/40 mx-4"></span>
<span className="text-xl sm:text-2xl font-black tracking-tight mx-6 uppercase">
2026
</span>
<span className="text-black/40 mx-4"></span>
</div>
))}
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,101 @@
"use client";
import { motion } from "framer-motion";
import { UserPlus, Upload, Shield, Vote, Trophy } from "lucide-react";
const steps = [
{
icon: UserPlus,
step: "01",
title: "Register",
description: "Sign up with your SJEC email to participate in the competition.",
},
{
icon: Upload,
step: "02",
title: "Submit",
description: "Upload your artwork with title, description, and category details.",
},
{
icon: Shield,
step: "03",
title: "Review",
description: "Moderators review submissions to ensure guidelines are met.",
},
{
icon: Vote,
step: "04",
title: "Public Voting",
description: "The public votes for their favorite artworks in each category.",
},
{
icon: Trophy,
step: "05",
title: "Results",
description: "Winners are announced and celebrated across all categories.",
},
];
export default function HowItWorks() {
return (
<section className="py-24 bg-black text-white overflow-hidden">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Section Header */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-16"
>
<span className="inline-block bg-lime-400 text-black px-4 py-1.5 text-xs font-bold tracking-wider rounded-full mb-4">
HOW IT WORKS
</span>
<h2 className="text-4xl sm:text-5xl font-black tracking-tight mb-4">
Your Journey to
<span className="text-lime-400"> Victory</span>
</h2>
<p className="text-zinc-400 text-lg max-w-2xl mx-auto">
From registration to winning, here's how ArtSplash works.
</p>
</motion.div>
{/* Steps Timeline */}
<div className="relative">
{/* Connection Line */}
<div className="absolute top-1/2 left-0 right-0 h-0.5 bg-zinc-800 hidden lg:block" />
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-8 lg:gap-4">
{steps.map((step, index) => (
<motion.div
key={step.step}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="relative"
>
{/* Card */}
<div className="bg-zinc-900 rounded-2xl p-6 h-full border border-zinc-800 hover:border-lime-400/50 transition-colors group">
{/* Step Number */}
<div className="relative z-10 w-12 h-12 rounded-full bg-lime-400 text-black font-black text-sm flex items-center justify-center mb-4 group-hover:scale-110 transition-transform">
{step.step}
</div>
{/* Icon */}
<step.icon className="w-8 h-8 text-lime-400 mb-4" />
{/* Content */}
<h3 className="text-xl font-bold mb-2">{step.title}</h3>
<p className="text-zinc-400 text-sm leading-relaxed">
{step.description}
</p>
</div>
</motion.div>
))}
</div>
</div>
</div>
</section>
);
}

112
app/components/Navbar.tsx Normal file
View File

@@ -0,0 +1,112 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { Menu, X, Diamond } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
const navLinks = [
{ href: "/gallery", label: "GALLERY" },
{ href: "/submit", label: "SUBMIT ART" },
{ href: "/about", label: "ABOUT" },
{ href: "/rules", label: "RULES" },
{ href: "/faq", label: "FAQ" },
{ href: "/contact", label: "CONTACT" },
];
export default function Navbar() {
const [isOpen, setIsOpen] = useState(false);
return (
<nav className="fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-md border-b border-zinc-200">
{/* Announcement Bar */}
<div className="bg-black text-white overflow-hidden">
<div className="animate-marquee whitespace-nowrap py-2 text-xs tracking-widest">
{Array(10)
.fill("✦ OPEN FOR SUBMISSIONS")
.map((text, i) => (
<span key={i} className="mx-8">
{text}
</span>
))}
</div>
</div>
{/* Main Navbar */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
{/* Logo */}
<Link href="/" className="flex items-center gap-2 group">
<Diamond className="w-6 h-6 text-lime-400 group-hover:rotate-12 transition-transform" />
<span className="text-xl font-bold tracking-tight">ARTSPLASH</span>
</Link>
{/* Desktop Navigation */}
<div className="hidden lg:flex items-center gap-8">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className="text-sm font-medium tracking-wide text-zinc-700 hover:text-black transition-colors relative group"
>
{link.label}
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-lime-400 group-hover:w-full transition-all duration-300" />
</Link>
))}
</div>
{/* CTA Button */}
<div className="hidden lg:block">
<Link
href="/register"
className="bg-lime-400 text-black px-6 py-2.5 text-sm font-bold tracking-wide hover:bg-lime-300 transition-colors rounded-full"
>
REGISTER NOW
</Link>
</div>
{/* Mobile Menu Button */}
<button
onClick={() => setIsOpen(!isOpen)}
className="lg:hidden p-2 hover:bg-zinc-100 rounded-lg transition-colors"
aria-label="Toggle menu"
>
{isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
</div>
</div>
{/* Mobile Menu */}
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
className="lg:hidden bg-white border-t border-zinc-200"
>
<div className="px-4 py-6 space-y-4">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
onClick={() => setIsOpen(false)}
className="block text-lg font-medium text-zinc-700 hover:text-black hover:pl-2 transition-all"
>
{link.label}
</Link>
))}
<Link
href="/register"
onClick={() => setIsOpen(false)}
className="block w-full text-center bg-lime-400 text-black px-6 py-3 text-sm font-bold tracking-wide hover:bg-lime-300 transition-colors rounded-full mt-6"
>
REGISTER NOW
</Link>
</div>
</motion.div>
)}
</AnimatePresence>
</nav>
);
}

38
app/components/Stats.tsx Normal file
View File

@@ -0,0 +1,38 @@
"use client";
import { motion } from "framer-motion";
const stats = [
{ value: "3", label: "Categories" },
{ value: "∞", label: "Possibilities" },
{ value: "1", label: "Winner Per Category" },
{ value: "100%", label: "Free Entry" },
];
export default function Stats() {
return (
<section className="py-16 bg-lime-400">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
{stats.map((stat, index) => (
<motion.div
key={stat.label}
initial={{ opacity: 0, scale: 0.8 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="text-center"
>
<div className="text-5xl sm:text-6xl font-black text-black mb-2">
{stat.value}
</div>
<div className="text-black/70 font-medium tracking-wide uppercase text-sm">
{stat.label}
</div>
</motion.div>
))}
</div>
</div>
</section>
);
}

View File

@@ -3,24 +3,89 @@
:root {
--background: #ffffff;
--foreground: #171717;
--lime: #c5ff00;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-lime-400: #c5ff00;
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif;
}
/* Custom Animations */
@keyframes marquee {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(-50%);
}
}
@keyframes marquee-slow {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(-50%);
}
}
.animate-marquee {
animation: marquee 20s linear infinite;
}
.animate-marquee-slow {
animation: marquee-slow 30s linear infinite;
}
/* Smooth scrolling */
html {
scroll-behavior: smooth;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #c5ff00;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #a8e000;
}
/* Selection color */
::selection {
background-color: #c5ff00;
color: #000000;
}
/* Focus styles */
*:focus-visible {
outline: 2px solid #c5ff00;
outline-offset: 2px;
}
/* Gradient text utility */
.gradient-text {
background: linear-gradient(135deg, #c5ff00 0%, #84cc16 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}

View File

@@ -13,8 +13,10 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "ArtSplash | SJEC Art Competition 2026",
description:
"Join SJEC's premier art competition featuring Digital Art, Paintings, and Poster Making. Register now and showcase your creativity!",
keywords: ["art competition", "SJEC", "digital art", "paintings", "poster making", "ArtSplash"],
};
export default function RootLayout({
@@ -24,9 +26,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
{children}
</body>
</html>

View File

@@ -1,65 +1,23 @@
import Image from "next/image";
import Navbar from "./components/Navbar";
import Hero from "./components/Hero";
import Categories from "./components/Categories";
import HowItWorks from "./components/HowItWorks";
import Stats from "./components/Stats";
import CTA from "./components/CTA";
import Footer from "./components/Footer";
export default function Home() {
return (
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={100}
height={20}
priority
/>
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
To get started, edit the page.tsx file.
</h1>
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
Looking for a starting point or more instructions? Head over to{" "}
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Templates
</a>{" "}
or the{" "}
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Learning
</a>{" "}
center.
</p>
</div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
<a
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
Deploy Now
</a>
<a
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
</div>
<>
<Navbar />
<main>
<Hero />
<Categories />
<Stats />
<HowItWorks />
<CTA />
</main>
</div>
<Footer />
</>
);
}

2910
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,9 @@
"check": "biome check ."
},
"dependencies": {
"framer-motion": "^12.34.3",
"gsap": "^3.14.2",
"lucide-react": "^0.575.0",
"next": "16.1.6",
"react": "19.2.3",
"react-dom": "19.2.3"