diff --git a/holly-knight/.gitignore b/holly-knight/.gitignore
new file mode 100755
index 0000000..f9ba7f8
--- /dev/null
+++ b/holly-knight/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+dist
+.DS_Store
+server/public
+vite.config.ts.*
+*.tar.gz
\ No newline at end of file
diff --git a/holly-knight/AuroraDash-demo-gameplay.mp4 b/holly-knight/AuroraDash-demo-gameplay.mp4
new file mode 100755
index 0000000..32e6615
Binary files /dev/null and b/holly-knight/AuroraDash-demo-gameplay.mp4 differ
diff --git a/holly-knight/README.md b/holly-knight/README.md
new file mode 100755
index 0000000..cc34276
--- /dev/null
+++ b/holly-knight/README.md
@@ -0,0 +1,114 @@
+# âī¸ AuroraDash
+
+
+
+
+
+> **"It works on my machine... and it flows in my mind."**
+
+## đ The Story: A Developer's Escape
+**AuroraDash** is a high-fidelity, atmospheric endless runner inspired by the meditative vibes of *Alto's Adventure*.
+
+We know the struggle: The sprint is ending, the `console` is full of red text, and burnout is creeping in. AuroraDash was built for that exact moment. It is a procedural winter sanctuary where you trade high-pressure deadlines for shimmering auroras and soothing soundscapes.
+
+Steer your rubber-duck-powered sleigh through a world of `syntax errors` and `404` boulders. It isn't just a game; it's a rhythmic, chill escape designed to help developers find their "flow state."
+
+---
+
+## đŽ Theme Interpretation: "Games o|x"
+**Theme:** Architecting a game-themed experience.
+
+We interpreted the theme by architecting a digital cure for developer fatigue.
+* **Visual Architecture:** We engineered a custom rendering engine that prioritizes hypnotic, fluid motion (parallax snow, aurora gradients) to act as a visual palate cleanser.
+* **The Metaphor:** The gameplay mirrors the developer experience. The obstacles are the bugs we fight daily, but the movement is the grace we strive for. We didn't just build a runner; we architected a **Zen Mode** for your browser.
+
+---
+
+### đĨ Gameplay Demo
+
+[Watch the AuroraDash Gameplay Video](./AuroraDash-demo-gameplay.mp4)
+
+[Youtube](https://youtu.be/C3NT7L_8EvA)
+
+---
+## đšī¸ Gameplay Mechanics & Power-ups
+
+Navigate the snowy terrain and use your developer toolkit to survive:
+
+### â The Boost: `Coffee`
+> *Signifies: The Flow State*
+Collecting a `Coffee` cup triggers a temporary speed boost. It simulates that caffeine-induced burst of productivity where code writes itself, allowing you to glide effortlessly past obstacles.
+
+### đĄī¸ The Protection: `Firewall`
+> *Signifies: Security & Stability*
+Picking up the shield item activates a `Firewall`. This protective layer wraps your character in a secure shell, allowing you to crash through exactly one `404 Boulder` or `Syntax Error` without breaking the build (ending the run).
+
+### đž The Obstacles
+* **`404` Boulders:** Large, immovable rocks representing missing resources.
+* **Syntax Spikes:** Sharp coding errors that must be jumped over.
+
+---
+
+## đ Tech Stack
+
+We utilized a modern, type-safe stack to ensure performance and developer experience:
+
+* **Frontend:** `React 18`, `TypeScript`, `Vite`
+* **Game Engine:** `HTML5 Canvas API` (Custom implementation for fluid physics)
+* **Styling:** `Tailwind CSS`
+* **Animations:** `Framer Motion` (UI Transitions)
+* **State Management:** `TanStack React Query`
+* **Icons:** `Lucide React`
+
+---
+
+## âī¸ Installation & Setup
+
+Follow these steps to get the game running locally.
+
+**Prerequisites:** Node.js (`v18+`)
+
+1. **Clone the Repository**
+ ```bash
+ git clone https://github.com/codev-aryan/codejam-v6.git
+ ```
+
+2. **Navigate to the Project Directory**
+ The game lives inside the `holly-knight` folder.
+ ```bash
+ cd codejam-v6/holly-knight
+ ```
+
+3. **Install Dependencies**
+ ```bash
+ npm install
+ ```
+
+4. **Start the Development Server**
+ ```bash
+ npm run dev
+ ```
+
+5. **Launch**
+ Open your browser and navigate to `http://localhost:5173`.
+
+---
+
+## đĨ The Team
+
+* **Aryan Mehta (Team Leader)**
+ * *Role:* Project Architect & Lead Developer
+ * *Contrib:* Core game loop, `Canvas` physics engine, and procedural generation logic.
+
+* **Ishaan Sahi**
+ * *Role:* UI/UX & Game Logic
+ * *Contrib:* Interface design, power-up mechanics (`Coffee`/`Firewall` logic), and developer-themed assets.
+
+---
+
+## đ License
+
+This project is Open Source under the **MIT License**.
+
+* **Audio:** Custom procedural audio via `Web Audio API`.
+* **Inspiration:** *Alto's Adventure*.
\ No newline at end of file
diff --git a/holly-knight/client/index.html b/holly-knight/client/index.html
new file mode 100755
index 0000000..f657986
--- /dev/null
+++ b/holly-knight/client/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+ AuroraDash
+
+
+
+
+
+
\ No newline at end of file
diff --git a/holly-knight/client/public/favicon.png b/holly-knight/client/public/favicon.png
new file mode 100755
index 0000000..625caff
Binary files /dev/null and b/holly-knight/client/public/favicon.png differ
diff --git a/holly-knight/client/requirements.md b/holly-knight/client/requirements.md
new file mode 100755
index 0000000..e91e7d0
--- /dev/null
+++ b/holly-knight/client/requirements.md
@@ -0,0 +1,8 @@
+## Packages
+framer-motion | Smooth UI transitions for game states and overlays
+
+## Notes
+Game logic uses HTML5 Canvas API in a React component
+Game runs at 60fps using requestAnimationFrame
+Audio assets are procedurally generated or standard HTML5 Audio
+High scores are persisted via /api/scores
diff --git a/holly-knight/client/src/App.tsx b/holly-knight/client/src/App.tsx
new file mode 100755
index 0000000..6ac1f4b
--- /dev/null
+++ b/holly-knight/client/src/App.tsx
@@ -0,0 +1,29 @@
+import { Switch, Route } from "wouter";
+import { queryClient } from "./lib/queryClient";
+import { QueryClientProvider } from "@tanstack/react-query";
+import { Toaster } from "@/components/ui/toaster";
+import { TooltipProvider } from "@/components/ui/tooltip";
+import Home from "@/pages/Home";
+import NotFound from "@/pages/not-found";
+
+function Router() {
+ return (
+
+
+
+
+ );
+}
+
+function App() {
+ return (
+
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/holly-knight/client/src/components/GameCanvas.tsx b/holly-knight/client/src/components/GameCanvas.tsx
new file mode 100755
index 0000000..1658431
--- /dev/null
+++ b/holly-knight/client/src/components/GameCanvas.tsx
@@ -0,0 +1,239 @@
+import { useEffect, useRef, useState } from 'react';
+import { GameEngine } from '@/game/engine';
+import { motion, AnimatePresence } from 'framer-motion';
+import { Button } from '@/components/ui/button';
+import { Volume2, VolumeX, Play, RotateCcw } from 'lucide-react';
+
+export default function GameCanvas() {
+ const canvasRef = useRef(null);
+ const engineRef = useRef(null);
+ const requestRef = useRef();
+
+ const [gameState, setGameState] = useState<'start' | 'playing' | 'gameover'>('start');
+ const [score, setScore] = useState(0);
+ const [isMuted, setIsMuted] = useState(false);
+ const audioContextRef = useRef(null);
+ const bgMusicRef = useRef(null);
+
+ // Audio System
+ const playSound = (type: 'jump' | 'hit') => {
+ if (isMuted) return;
+ if (!audioContextRef.current) audioContextRef.current = new (window.AudioContext || (window as any).webkitAudioContext)();
+ const ctx = audioContextRef.current;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+
+ if (type === 'jump') {
+ osc.type = 'triangle';
+ osc.frequency.setValueAtTime(150, ctx.currentTime);
+ osc.frequency.exponentialRampToValueAtTime(400, ctx.currentTime + 0.1);
+ gain.gain.setValueAtTime(0.1, ctx.currentTime);
+ gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.2);
+ } else {
+ // Zen-like chime for crash/reset
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(523.25, ctx.currentTime); // C5
+ osc.frequency.exponentialRampToValueAtTime(261.63, ctx.currentTime + 0.5); // Slide down to C4
+ gain.gain.setValueAtTime(0.1, ctx.currentTime);
+ gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.8);
+ }
+
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start();
+ osc.stop(ctx.currentTime + 0.3);
+ };
+
+ const startBackgroundMusic = () => {
+ if (!audioContextRef.current) audioContextRef.current = new (window.AudioContext || (window as any).webkitAudioContext)();
+ const ctx = audioContextRef.current;
+
+ // Richer synth pad for background
+ const masterGain = ctx.createGain();
+ masterGain.gain.setValueAtTime(0.04, ctx.currentTime);
+ masterGain.connect(ctx.destination);
+
+ const playNote = (freq: number, startTime: number, duration: number = 6) => {
+ const osc = ctx.createOscillator();
+ const g = ctx.createGain();
+ osc.type = 'triangle';
+ osc.frequency.setValueAtTime(freq, startTime);
+
+ // Soft envelope
+ g.gain.setValueAtTime(0, startTime);
+ g.gain.linearRampToValueAtTime(0.3, startTime + duration * 0.4);
+ g.gain.linearRampToValueAtTime(0, startTime + duration);
+
+ osc.connect(g);
+ g.connect(masterGain);
+ osc.start(startTime);
+ osc.stop(startTime + duration);
+ };
+
+ const scheduleMusic = () => {
+ const scales = [
+ [261.63, 329.63, 392.00, 523.25], // C Major
+ [349.23, 440.00, 523.25, 698.46], // F Major
+ [392.00, 493.88, 587.33, 783.99] // G Major
+ ];
+
+ const playLoop = () => {
+ if (!isMuted && gameState !== 'gameover') {
+ const scale = scales[Math.floor(Date.now() / 10000) % scales.length];
+ const note = scale[Math.floor(Math.random() * scale.length)];
+ playNote(note, ctx.currentTime);
+ // Add a low fifth for depth
+ playNote(note * 0.66, ctx.currentTime, 8);
+ }
+ setTimeout(playLoop, 4000);
+ };
+ playLoop();
+ };
+ scheduleMusic();
+ };
+
+ // Initialize Engine
+ useEffect(() => {
+ if (!canvasRef.current) return;
+
+ // Start music early
+ if (!audioContextRef.current) startBackgroundMusic();
+
+ const engine = new GameEngine(canvasRef.current);
+ engineRef.current = engine;
+
+ engine.onScoreUpdate = (s) => setScore(s);
+ engine.onGameOver = (finalScore) => {
+ setScore(finalScore);
+ setGameState('gameover');
+ playSound('hit');
+ };
+
+ const animate = () => {
+ engine.update();
+ engine.draw();
+ requestRef.current = requestAnimationFrame(animate);
+ };
+
+ requestRef.current = requestAnimationFrame(animate);
+
+ const handleResize = () => engine.resize();
+ window.addEventListener('resize', handleResize);
+
+ return () => {
+ if (requestRef.current) cancelAnimationFrame(requestRef.current);
+ window.removeEventListener('resize', handleResize);
+ };
+ }, []);
+
+ // Input Handling
+ useEffect(() => {
+ const handleKeyDown = (e: KeyboardEvent) => {
+ if (e.code === 'Space') {
+ e.preventDefault();
+ if (gameState === 'playing') {
+ const jumped = engineRef.current?.jump();
+ if (jumped) {
+ playSound('jump');
+ }
+ }
+ }
+ };
+
+ const handleMouseDown = (e: MouseEvent) => {
+ if (gameState === 'playing') {
+ const jumped = engineRef.current?.jump();
+ if (jumped) {
+ playSound('jump');
+ }
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ window.addEventListener('mousedown', handleMouseDown);
+
+ return () => {
+ window.removeEventListener('keydown', handleKeyDown);
+ window.removeEventListener('mousedown', handleMouseDown);
+ };
+ }, [gameState]);
+
+ const startGame = () => {
+ if (!audioContextRef.current) startBackgroundMusic();
+ engineRef.current?.start();
+ setGameState('playing');
+ setScore(0);
+ };
+
+ return (
+
+
+
+ {/* HUD - Score */}
+
+
+
+ {gameState === 'start' && (
+
+
+
+ AuroraDash
+
+
+
+
+ Welcome to the chill zone. No deadlines here.{"\n"}
+ Tap or Spacebar to debug.
+
+
+ Start Journey
+
+
+
+
+ )}
+
+ {gameState === 'gameover' && (
+
+
+
+
Uncaught ReferenceError
+
{score}
+
Skill not found. Drink more coffee.
+
+
+
+
+ git reset --hard
+
+
+
+
+ )}
+
+
+ );
+}
diff --git a/holly-knight/client/src/components/ui/accordion.tsx b/holly-knight/client/src/components/ui/accordion.tsx
new file mode 100755
index 0000000..e6a723d
--- /dev/null
+++ b/holly-knight/client/src/components/ui/accordion.tsx
@@ -0,0 +1,56 @@
+import * as React from "react"
+import * as AccordionPrimitive from "@radix-ui/react-accordion"
+import { ChevronDown } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const Accordion = AccordionPrimitive.Root
+
+const AccordionItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AccordionItem.displayName = "AccordionItem"
+
+const AccordionTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+ svg]:rotate-180",
+ className
+ )}
+ {...props}
+ >
+ {children}
+
+
+
+))
+AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
+
+const AccordionContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+ {children}
+
+))
+
+AccordionContent.displayName = AccordionPrimitive.Content.displayName
+
+export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
diff --git a/holly-knight/client/src/components/ui/alert-dialog.tsx b/holly-knight/client/src/components/ui/alert-dialog.tsx
new file mode 100755
index 0000000..8722561
--- /dev/null
+++ b/holly-knight/client/src/components/ui/alert-dialog.tsx
@@ -0,0 +1,139 @@
+import * as React from "react"
+import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
+
+import { cn } from "@/lib/utils"
+import { buttonVariants } from "@/components/ui/button"
+
+const AlertDialog = AlertDialogPrimitive.Root
+
+const AlertDialogTrigger = AlertDialogPrimitive.Trigger
+
+const AlertDialogPortal = AlertDialogPrimitive.Portal
+
+const AlertDialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
+
+const AlertDialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+
+))
+AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
+
+const AlertDialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+AlertDialogHeader.displayName = "AlertDialogHeader"
+
+const AlertDialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+AlertDialogFooter.displayName = "AlertDialogFooter"
+
+const AlertDialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
+
+const AlertDialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogDescription.displayName =
+ AlertDialogPrimitive.Description.displayName
+
+const AlertDialogAction = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
+
+const AlertDialogCancel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
+
+export {
+ AlertDialog,
+ AlertDialogPortal,
+ AlertDialogOverlay,
+ AlertDialogTrigger,
+ AlertDialogContent,
+ AlertDialogHeader,
+ AlertDialogFooter,
+ AlertDialogTitle,
+ AlertDialogDescription,
+ AlertDialogAction,
+ AlertDialogCancel,
+}
diff --git a/holly-knight/client/src/components/ui/alert.tsx b/holly-knight/client/src/components/ui/alert.tsx
new file mode 100755
index 0000000..41fa7e0
--- /dev/null
+++ b/holly-knight/client/src/components/ui/alert.tsx
@@ -0,0 +1,59 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const alertVariants = cva(
+ "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
+ {
+ variants: {
+ variant: {
+ default: "bg-background text-foreground",
+ destructive:
+ "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+const Alert = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes & VariantProps
+>(({ className, variant, ...props }, ref) => (
+
+))
+Alert.displayName = "Alert"
+
+const AlertTitle = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+AlertTitle.displayName = "AlertTitle"
+
+const AlertDescription = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+AlertDescription.displayName = "AlertDescription"
+
+export { Alert, AlertTitle, AlertDescription }
diff --git a/holly-knight/client/src/components/ui/aspect-ratio.tsx b/holly-knight/client/src/components/ui/aspect-ratio.tsx
new file mode 100755
index 0000000..c4abbf3
--- /dev/null
+++ b/holly-knight/client/src/components/ui/aspect-ratio.tsx
@@ -0,0 +1,5 @@
+import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
+
+const AspectRatio = AspectRatioPrimitive.Root
+
+export { AspectRatio }
diff --git a/holly-knight/client/src/components/ui/avatar.tsx b/holly-knight/client/src/components/ui/avatar.tsx
new file mode 100755
index 0000000..fc7f964
--- /dev/null
+++ b/holly-knight/client/src/components/ui/avatar.tsx
@@ -0,0 +1,51 @@
+"use client"
+
+import * as React from "react"
+import * as AvatarPrimitive from "@radix-ui/react-avatar"
+
+import { cn } from "@/lib/utils"
+
+const Avatar = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+Avatar.displayName = AvatarPrimitive.Root.displayName
+
+const AvatarImage = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AvatarImage.displayName = AvatarPrimitive.Image.displayName
+
+const AvatarFallback = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
+
+export { Avatar, AvatarImage, AvatarFallback }
diff --git a/holly-knight/client/src/components/ui/badge.tsx b/holly-knight/client/src/components/ui/badge.tsx
new file mode 100755
index 0000000..b59d7ad
--- /dev/null
+++ b/holly-knight/client/src/components/ui/badge.tsx
@@ -0,0 +1,38 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const badgeVariants = cva(
+ // Whitespace-nowrap: Badges should never wrap.
+ "whitespace-nowrap inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2" +
+ " hover-elevate " ,
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground shadow-xs",
+ secondary: "border-transparent bg-secondary text-secondary-foreground",
+ destructive:
+ "border-transparent bg-destructive text-destructive-foreground shadow-xs",
+
+ outline: " border [border-color:var(--badge-outline)] shadow-xs",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ },
+)
+
+export interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return (
+
+ );
+}
+
+export { Badge, badgeVariants }
diff --git a/holly-knight/client/src/components/ui/breadcrumb.tsx b/holly-knight/client/src/components/ui/breadcrumb.tsx
new file mode 100755
index 0000000..60e6c96
--- /dev/null
+++ b/holly-knight/client/src/components/ui/breadcrumb.tsx
@@ -0,0 +1,115 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { ChevronRight, MoreHorizontal } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const Breadcrumb = React.forwardRef<
+ HTMLElement,
+ React.ComponentPropsWithoutRef<"nav"> & {
+ separator?: React.ReactNode
+ }
+>(({ ...props }, ref) => )
+Breadcrumb.displayName = "Breadcrumb"
+
+const BreadcrumbList = React.forwardRef<
+ HTMLOListElement,
+ React.ComponentPropsWithoutRef<"ol">
+>(({ className, ...props }, ref) => (
+
+))
+BreadcrumbList.displayName = "BreadcrumbList"
+
+const BreadcrumbItem = React.forwardRef<
+ HTMLLIElement,
+ React.ComponentPropsWithoutRef<"li">
+>(({ className, ...props }, ref) => (
+
+))
+BreadcrumbItem.displayName = "BreadcrumbItem"
+
+const BreadcrumbLink = React.forwardRef<
+ HTMLAnchorElement,
+ React.ComponentPropsWithoutRef<"a"> & {
+ asChild?: boolean
+ }
+>(({ asChild, className, ...props }, ref) => {
+ const Comp = asChild ? Slot : "a"
+
+ return (
+
+ )
+})
+BreadcrumbLink.displayName = "BreadcrumbLink"
+
+const BreadcrumbPage = React.forwardRef<
+ HTMLSpanElement,
+ React.ComponentPropsWithoutRef<"span">
+>(({ className, ...props }, ref) => (
+
+))
+BreadcrumbPage.displayName = "BreadcrumbPage"
+
+const BreadcrumbSeparator = ({
+ children,
+ className,
+ ...props
+}: React.ComponentProps<"li">) => (
+ svg]:w-3.5 [&>svg]:h-3.5", className)}
+ {...props}
+ >
+ {children ?? }
+
+)
+BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
+
+const BreadcrumbEllipsis = ({
+ className,
+ ...props
+}: React.ComponentProps<"span">) => (
+
+
+ More
+
+)
+BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
+
+export {
+ Breadcrumb,
+ BreadcrumbList,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ BreadcrumbPage,
+ BreadcrumbSeparator,
+ BreadcrumbEllipsis,
+}
diff --git a/holly-knight/client/src/components/ui/button.tsx b/holly-knight/client/src/components/ui/button.tsx
new file mode 100755
index 0000000..75f8a8c
--- /dev/null
+++ b/holly-knight/client/src/components/ui/button.tsx
@@ -0,0 +1,56 @@
+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-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default:
+ "bg-primary text-primary-foreground shadow hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-9 px-4 py-2",
+ sm: "h-8 rounded-md px-3 text-xs",
+ lg: "h-10 rounded-md px-8",
+ icon: "h-9 w-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button"
+ return (
+
+ )
+ }
+)
+Button.displayName = "Button"
+
+export { Button, buttonVariants }
diff --git a/holly-knight/client/src/components/ui/calendar.tsx b/holly-knight/client/src/components/ui/calendar.tsx
new file mode 100755
index 0000000..2174f71
--- /dev/null
+++ b/holly-knight/client/src/components/ui/calendar.tsx
@@ -0,0 +1,68 @@
+import * as React from "react"
+import { ChevronLeft, ChevronRight } from "lucide-react"
+import { DayPicker } from "react-day-picker"
+
+import { cn } from "@/lib/utils"
+import { buttonVariants } from "@/components/ui/button"
+
+export type CalendarProps = React.ComponentProps
+
+function Calendar({
+ className,
+ classNames,
+ showOutsideDays = true,
+ ...props
+}: CalendarProps) {
+ return (
+ (
+
+ ),
+ IconRight: ({ className, ...props }) => (
+
+ ),
+ }}
+ {...props}
+ />
+ )
+}
+Calendar.displayName = "Calendar"
+
+export { Calendar }
diff --git a/holly-knight/client/src/components/ui/card.tsx b/holly-knight/client/src/components/ui/card.tsx
new file mode 100755
index 0000000..c65c4c6
--- /dev/null
+++ b/holly-knight/client/src/components/ui/card.tsx
@@ -0,0 +1,85 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardDescription,
+ CardContent,
+}
diff --git a/holly-knight/client/src/components/ui/carousel.tsx b/holly-knight/client/src/components/ui/carousel.tsx
new file mode 100755
index 0000000..9c2b9bf
--- /dev/null
+++ b/holly-knight/client/src/components/ui/carousel.tsx
@@ -0,0 +1,260 @@
+import * as React from "react"
+import useEmblaCarousel, {
+ type UseEmblaCarouselType,
+} from "embla-carousel-react"
+import { ArrowLeft, ArrowRight } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+
+type CarouselApi = UseEmblaCarouselType[1]
+type UseCarouselParameters = Parameters
+type CarouselOptions = UseCarouselParameters[0]
+type CarouselPlugin = UseCarouselParameters[1]
+
+type CarouselProps = {
+ opts?: CarouselOptions
+ plugins?: CarouselPlugin
+ orientation?: "horizontal" | "vertical"
+ setApi?: (api: CarouselApi) => void
+}
+
+type CarouselContextProps = {
+ carouselRef: ReturnType[0]
+ api: ReturnType[1]
+ scrollPrev: () => void
+ scrollNext: () => void
+ canScrollPrev: boolean
+ canScrollNext: boolean
+} & CarouselProps
+
+const CarouselContext = React.createContext(null)
+
+function useCarousel() {
+ const context = React.useContext(CarouselContext)
+
+ if (!context) {
+ throw new Error("useCarousel must be used within a ")
+ }
+
+ return context
+}
+
+const Carousel = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes & CarouselProps
+>(
+ (
+ {
+ orientation = "horizontal",
+ opts,
+ setApi,
+ plugins,
+ className,
+ children,
+ ...props
+ },
+ ref
+ ) => {
+ const [carouselRef, api] = useEmblaCarousel(
+ {
+ ...opts,
+ axis: orientation === "horizontal" ? "x" : "y",
+ },
+ plugins
+ )
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false)
+ const [canScrollNext, setCanScrollNext] = React.useState(false)
+
+ const onSelect = React.useCallback((api: CarouselApi) => {
+ if (!api) {
+ return
+ }
+
+ setCanScrollPrev(api.canScrollPrev())
+ setCanScrollNext(api.canScrollNext())
+ }, [])
+
+ const scrollPrev = React.useCallback(() => {
+ api?.scrollPrev()
+ }, [api])
+
+ const scrollNext = React.useCallback(() => {
+ api?.scrollNext()
+ }, [api])
+
+ const handleKeyDown = React.useCallback(
+ (event: React.KeyboardEvent) => {
+ if (event.key === "ArrowLeft") {
+ event.preventDefault()
+ scrollPrev()
+ } else if (event.key === "ArrowRight") {
+ event.preventDefault()
+ scrollNext()
+ }
+ },
+ [scrollPrev, scrollNext]
+ )
+
+ React.useEffect(() => {
+ if (!api || !setApi) {
+ return
+ }
+
+ setApi(api)
+ }, [api, setApi])
+
+ React.useEffect(() => {
+ if (!api) {
+ return
+ }
+
+ onSelect(api)
+ api.on("reInit", onSelect)
+ api.on("select", onSelect)
+
+ return () => {
+ api?.off("select", onSelect)
+ }
+ }, [api, onSelect])
+
+ return (
+
+
+ {children}
+
+
+ )
+ }
+)
+Carousel.displayName = "Carousel"
+
+const CarouselContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const { carouselRef, orientation } = useCarousel()
+
+ return (
+
+ )
+})
+CarouselContent.displayName = "CarouselContent"
+
+const CarouselItem = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const { orientation } = useCarousel()
+
+ return (
+
+ )
+})
+CarouselItem.displayName = "CarouselItem"
+
+const CarouselPrevious = React.forwardRef<
+ HTMLButtonElement,
+ React.ComponentProps
+>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel()
+
+ return (
+
+
+ Previous slide
+
+ )
+})
+CarouselPrevious.displayName = "CarouselPrevious"
+
+const CarouselNext = React.forwardRef<
+ HTMLButtonElement,
+ React.ComponentProps
+>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
+ const { orientation, scrollNext, canScrollNext } = useCarousel()
+
+ return (
+
+
+ Next slide
+
+ )
+})
+CarouselNext.displayName = "CarouselNext"
+
+export {
+ type CarouselApi,
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselPrevious,
+ CarouselNext,
+}
diff --git a/holly-knight/client/src/components/ui/chart.tsx b/holly-knight/client/src/components/ui/chart.tsx
new file mode 100755
index 0000000..39fba6d
--- /dev/null
+++ b/holly-knight/client/src/components/ui/chart.tsx
@@ -0,0 +1,365 @@
+"use client"
+
+import * as React from "react"
+import * as RechartsPrimitive from "recharts"
+
+import { cn } from "@/lib/utils"
+
+// Format: { THEME_NAME: CSS_SELECTOR }
+const THEMES = { light: "", dark: ".dark" } as const
+
+export type ChartConfig = {
+ [k in string]: {
+ label?: React.ReactNode
+ icon?: React.ComponentType
+ } & (
+ | { color?: string; theme?: never }
+ | { color?: never; theme: Record }
+ )
+}
+
+type ChartContextProps = {
+ config: ChartConfig
+}
+
+const ChartContext = React.createContext(null)
+
+function useChart() {
+ const context = React.useContext(ChartContext)
+
+ if (!context) {
+ throw new Error("useChart must be used within a ")
+ }
+
+ return context
+}
+
+const ChartContainer = React.forwardRef<
+ HTMLDivElement,
+ React.ComponentProps<"div"> & {
+ config: ChartConfig
+ children: React.ComponentProps<
+ typeof RechartsPrimitive.ResponsiveContainer
+ >["children"]
+ }
+>(({ id, className, children, config, ...props }, ref) => {
+ const uniqueId = React.useId()
+ const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
+
+ return (
+
+
+
+
+ {children}
+
+
+
+ )
+})
+ChartContainer.displayName = "Chart"
+
+const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
+ const colorConfig = Object.entries(config).filter(
+ ([, config]) => config.theme || config.color
+ )
+
+ if (!colorConfig.length) {
+ return null
+ }
+
+ return (
+