diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..2e9d6c3
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,8 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(yarn add:*)",
+ "Bash(yarn build)"
+ ]
+ }
+}
diff --git a/app/components/AnimatedButton.tsx b/app/components/AnimatedButton.tsx
new file mode 100644
index 0000000..2b81e9f
--- /dev/null
+++ b/app/components/AnimatedButton.tsx
@@ -0,0 +1,116 @@
+"use client";
+
+import { motion } from "framer-motion";
+import Link from "next/link";
+import { ReactNode } from "react";
+
+interface AnimatedButtonProps {
+ href?: string;
+ onClick?: () => void;
+ children: ReactNode;
+ variant?: "primary" | "secondary" | "accent" | "outline";
+ size?: "sm" | "md" | "lg";
+ className?: string;
+ external?: boolean;
+ icon?: ReactNode;
+ iconPosition?: "left" | "right";
+}
+
+export default function AnimatedButton({
+ href,
+ onClick,
+ children,
+ variant = "primary",
+ size = "md",
+ className = "",
+ external = false,
+ icon,
+ iconPosition = "right",
+}: AnimatedButtonProps) {
+ const baseStyles =
+ "relative inline-flex items-center justify-center gap-2 font-medium rounded-full overflow-hidden transition-all duration-300 cursor-pointer";
+
+ const variants = {
+ primary:
+ "bg-[hsl(0,100%,40%)] text-white hover:bg-[hsl(0,100%,35%)] shadow-lg hover:shadow-xl hover:shadow-[hsl(0,100%,40%)]/25",
+ secondary:
+ "bg-neutral-900 text-white hover:bg-neutral-800 dark:bg-white dark:text-neutral-900 dark:hover:bg-neutral-100",
+ accent:
+ "bg-gradient-to-r from-emerald-600 to-emerald-500 text-white hover:from-emerald-700 hover:to-emerald-600 shadow-lg hover:shadow-xl hover:shadow-emerald-500/25",
+ outline:
+ "bg-transparent border-2 border-neutral-200 text-neutral-900 hover:border-[hsl(0,100%,40%)] hover:text-[hsl(0,100%,40%)] dark:border-neutral-700 dark:text-white dark:hover:border-[hsl(0,100%,50%)] dark:hover:text-[hsl(0,100%,50%)]",
+ };
+
+ const sizes = {
+ sm: "px-4 py-2 text-sm",
+ md: "px-6 py-3 text-base",
+ lg: "px-8 py-4 text-lg",
+ };
+
+ const buttonContent = (
+ <>
+ {icon && iconPosition === "left" && (
+
+ {icon}
+
+ )}
+ {children}
+ {icon && iconPosition === "right" && (
+
+ {icon}
+
+ )}
+ >
+ );
+
+ const motionProps = {
+ whileHover: { scale: 1.02, y: -2 },
+ whileTap: { scale: 0.98 },
+ transition: { type: "spring" as const, stiffness: 400, damping: 17 },
+ };
+
+ if (href) {
+ if (external) {
+ return (
+
+ {buttonContent}
+
+ );
+ }
+
+ return (
+
+
+ {buttonContent}
+
+
+ );
+ }
+
+ return (
+
+ {buttonContent}
+
+ );
+}
diff --git a/app/components/FadeIn.tsx b/app/components/FadeIn.tsx
new file mode 100644
index 0000000..39fa120
--- /dev/null
+++ b/app/components/FadeIn.tsx
@@ -0,0 +1,112 @@
+"use client";
+
+import { motion } from "framer-motion";
+import { ReactNode } from "react";
+
+interface FadeInProps {
+ children: ReactNode;
+ delay?: number;
+ duration?: number;
+ direction?: "up" | "down" | "left" | "right" | "none";
+ distance?: number;
+ className?: string;
+ once?: boolean;
+}
+
+export default function FadeIn({
+ children,
+ delay = 0,
+ duration = 0.6,
+ direction = "up",
+ distance = 30,
+ className = "",
+ once = true,
+}: FadeInProps) {
+ const directions = {
+ up: { y: distance, x: 0 },
+ down: { y: -distance, x: 0 },
+ left: { x: distance, y: 0 },
+ right: { x: -distance, y: 0 },
+ none: { x: 0, y: 0 },
+ };
+
+ return (
+
+ {children}
+
+ );
+}
+
+interface StaggerContainerProps {
+ children: ReactNode;
+ className?: string;
+ staggerDelay?: number;
+}
+
+export function StaggerContainer({
+ children,
+ className = "",
+ staggerDelay = 0.1,
+}: StaggerContainerProps) {
+ return (
+
+ {children}
+
+ );
+}
+
+interface StaggerItemProps {
+ children: ReactNode;
+ className?: string;
+}
+
+export function StaggerItem({ children, className = "" }: StaggerItemProps) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/app/components/Footer.tsx b/app/components/Footer.tsx
new file mode 100644
index 0000000..e612894
--- /dev/null
+++ b/app/components/Footer.tsx
@@ -0,0 +1,231 @@
+"use client";
+
+import { motion } from "framer-motion";
+import Image from "next/image";
+import Link from "next/link";
+import { MapPinIcon, PhoneIcon, MailIcon } from "./Icons";
+
+const footerLinks = {
+ company: [
+ { href: "/what-we-do", label: "What We Do" },
+ { href: "/culture", label: "Our Culture" },
+ { href: "/contact", label: "Contact Us" },
+ ],
+ products: [
+ { href: "/products", label: "All Products" },
+ { href: "/sustainability", label: "Sustainability" },
+ { href: "/state-ordinances", label: "State Ordinances" },
+ ],
+ categories: [
+ { href: "/products#packaging", label: "Food Packaging" },
+ { href: "/products#green", label: "Green Products" },
+ { href: "/products#janitorial", label: "Janitorial" },
+ ],
+};
+
+const territories = [
+ "Colorado",
+ "Washington",
+ "Oregon",
+ "Idaho",
+ "Utah",
+ "Wyoming",
+ "Montana",
+ "New Mexico",
+ "Nebraska",
+ "Arizona",
+];
+
+export default function Footer() {
+ return (
+
+ );
+}
diff --git a/app/components/Icons.tsx b/app/components/Icons.tsx
new file mode 100644
index 0000000..294693a
--- /dev/null
+++ b/app/components/Icons.tsx
@@ -0,0 +1,310 @@
+interface IconProps {
+ className?: string;
+ size?: number;
+}
+
+export function ArrowRightIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+ );
+}
+
+export function CheckIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+ );
+}
+
+export function MapPinIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+ );
+}
+
+export function PhoneIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+ );
+}
+
+export function MailIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+ );
+}
+
+export function LeafIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+ );
+}
+
+export function PackageIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+
+ );
+}
+
+export function UsersIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+
+ );
+}
+
+export function TruckIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+
+
+ );
+}
+
+export function TargetIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+
+ );
+}
+
+export function HeartIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+ );
+}
+
+export function StarIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+ );
+}
+
+export function BuildingIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+ );
+}
+
+export function SparklesIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+ );
+}
+
+export function ChevronDownIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+ );
+}
+
+export function RecycleIcon({ className = "", size = 20 }: IconProps) {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/components/Navigation.tsx b/app/components/Navigation.tsx
new file mode 100644
index 0000000..ed4ac6f
--- /dev/null
+++ b/app/components/Navigation.tsx
@@ -0,0 +1,200 @@
+"use client";
+
+import { motion, AnimatePresence } from "framer-motion";
+import Image from "next/image";
+import Link from "next/link";
+import { useState, useEffect } from "react";
+import AnimatedButton from "./AnimatedButton";
+
+const navLinks = [
+ { href: "/", label: "Home" },
+ { href: "/what-we-do", label: "What We Do" },
+ { href: "/products", label: "Products" },
+ { href: "/sustainability", label: "Sustainability" },
+ { href: "/culture", label: "Our Culture" },
+];
+
+export default function Navigation() {
+ const [isScrolled, setIsScrolled] = useState(false);
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
+
+ useEffect(() => {
+ const handleScroll = () => {
+ setIsScrolled(window.scrollY > 20);
+ };
+
+ window.addEventListener("scroll", handleScroll);
+ return () => window.removeEventListener("scroll", handleScroll);
+ }, []);
+
+ return (
+ <>
+
+
+
+ {/* Logo */}
+
+
+
+
+
+ TCM
+
+
+ {" "}
+ Sales
+
+
+
+
+
+ {/* Desktop Navigation */}
+
+ {navLinks.map((link) => (
+
+
+ {link.label}
+
+
+
+ ))}
+
+
+ {/* CTA Button */}
+
+
+ {/* Mobile Menu Button */}
+
setIsMobileMenuOpen(!isMobileMenuOpen)}
+ className="lg:hidden relative z-10 p-2 text-neutral-900 dark:text-white"
+ >
+
+
+
+
+
+
+
+
+
+
+ {/* Mobile Menu */}
+
+ {isMobileMenuOpen && (
+
+ {/* Backdrop */}
+ setIsMobileMenuOpen(false)}
+ />
+
+ {/* Menu Panel */}
+
+
+
+ {navLinks.map((link, index) => (
+
+ setIsMobileMenuOpen(false)}
+ className="block py-4 text-2xl font-medium text-neutral-900 dark:text-white hover:text-[hsl(0,100%,40%)] transition-colors border-b border-neutral-100 dark:border-neutral-800"
+ >
+ {link.label}
+
+
+ ))}
+
+
+
+ setIsMobileMenuOpen(false)}
+ >
+ Contact Us
+
+
+
+
+
+ )}
+
+ >
+ );
+}
diff --git a/app/globals.css b/app/globals.css
index a2dc41e..42662b2 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,8 +1,75 @@
@import "tailwindcss";
:root {
+ /* Brand colors - TCM Red (hsl(0, 100%, 40%) as base) */
+ --brand-50: hsl(0, 100%, 97%);
+ --brand-100: hsl(0, 100%, 94%);
+ --brand-200: hsl(0, 100%, 87%);
+ --brand-300: hsl(0, 100%, 75%);
+ --brand-400: hsl(0, 100%, 60%);
+ --brand-500: hsl(0, 100%, 50%);
+ --brand-600: hsl(0, 100%, 40%);
+ --brand-700: hsl(0, 100%, 33%);
+ --brand-800: hsl(0, 100%, 27%);
+ --brand-900: hsl(0, 100%, 22%);
+ --brand-950: hsl(0, 100%, 12%);
+
+ /* Accent colors - Vibrant emerald for sustainability */
+ --accent-50: #ecfdf5;
+ --accent-100: #d1fae5;
+ --accent-200: #a7f3d0;
+ --accent-300: #6ee7b7;
+ --accent-400: #34d399;
+ --accent-500: #10b981;
+ --accent-600: #059669;
+ --accent-700: #047857;
+ --accent-800: #065f46;
+ --accent-900: #064e3b;
+
+ /* Neutral colors */
+ --neutral-50: #fafafa;
+ --neutral-100: #f5f5f5;
+ --neutral-200: #e5e5e5;
+ --neutral-300: #d4d4d4;
+ --neutral-400: #a3a3a3;
+ --neutral-500: #737373;
+ --neutral-600: #525252;
+ --neutral-700: #404040;
+ --neutral-800: #262626;
+ --neutral-900: #171717;
+ --neutral-950: #0a0a0a;
+
+ /* Semantic colors */
--background: #ffffff;
--foreground: #171717;
+ --muted: #f5f5f5;
+ --muted-foreground: #737373;
+ --border: #e5e5e5;
+ --ring: hsl(0, 100%, 40%);
+
+ /* Gradients */
+ --gradient-brand: linear-gradient(135deg, hsl(0, 100%, 33%) 0%, hsl(0, 100%, 40%) 50%, hsl(0, 100%, 50%) 100%);
+ --gradient-brand-reverse: linear-gradient(135deg, hsl(0, 100%, 50%) 0%, hsl(0, 100%, 40%) 100%);
+ --gradient-accent: linear-gradient(135deg, #047857 0%, #10b981 50%, #34d399 100%);
+ --gradient-dark: linear-gradient(135deg, #0a0a0a 0%, #262626 100%);
+ --gradient-hero: linear-gradient(180deg, hsl(0, 50%, 98%) 0%, #ffffff 50%, hsl(0, 20%, 97%) 100%);
+ --gradient-warm: linear-gradient(135deg, hsl(0, 100%, 40%) 0%, hsl(20, 100%, 50%) 100%);
+
+ /* Shadows */
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
+ --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
+ --shadow-glow: 0 0 40px -10px hsl(0, 100%, 40%);
+ --shadow-glow-accent: 0 0 40px -10px rgb(16 185 129 / 0.5);
+ --shadow-brand: 0 4px 14px 0 hsl(0 100% 40% / 0.35);
+
+ /* Animation timing */
+ --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
+ --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
+ --ease-in-out-circ: cubic-bezier(0.85, 0, 0.15, 1);
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}
@theme inline {
@@ -15,12 +82,373 @@
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
- --foreground: #ededed;
+ --foreground: #fafafa;
+ --muted: #262626;
+ --muted-foreground: #a3a3a3;
+ --border: #404040;
}
}
+* {
+ box-sizing: border-box;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
body {
background: var(--background);
color: var(--foreground);
- font-family: Arial, Helvetica, sans-serif;
+ font-family: var(--font-sans), system-ui, -apple-system, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ overflow-x: hidden;
+}
+
+/* Selection styling */
+::selection {
+ background-color: hsl(0, 100%, 40%);
+ color: white;
+}
+
+/* Focus styling */
+:focus-visible {
+ outline: 2px solid var(--ring);
+ outline-offset: 2px;
+}
+
+/* Custom scrollbar */
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--muted);
+}
+
+::-webkit-scrollbar-thumb {
+ background: linear-gradient(180deg, hsl(0, 100%, 50%) 0%, hsl(0, 100%, 40%) 100%);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: linear-gradient(180deg, hsl(0, 100%, 55%) 0%, hsl(0, 100%, 45%) 100%);
+}
+
+/* Utility classes for animations */
+.animate-fade-in {
+ animation: fadeIn 0.6s var(--ease-out-expo) forwards;
+}
+
+.animate-slide-up {
+ animation: slideUp 0.6s var(--ease-out-expo) forwards;
+}
+
+.animate-scale-in {
+ animation: scaleIn 0.5s var(--ease-out-expo) forwards;
+}
+
+.animate-float {
+ animation: float 6s ease-in-out infinite;
+}
+
+.animate-pulse-glow {
+ animation: pulseGlow 2s ease-in-out infinite;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes slideUp {
+ from {
+ opacity: 0;
+ transform: translateY(30px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes scaleIn {
+ from {
+ opacity: 0;
+ transform: scale(0.95);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+@keyframes float {
+ 0%, 100% {
+ transform: translateY(0px);
+ }
+ 50% {
+ transform: translateY(-20px);
+ }
+}
+
+@keyframes pulseGlow {
+ 0%, 100% {
+ box-shadow: 0 0 20px hsl(0 100% 40% / 0.3);
+ }
+ 50% {
+ box-shadow: 0 0 40px hsl(0 100% 40% / 0.6);
+ }
+}
+
+@keyframes shimmer {
+ 0% {
+ background-position: -200% 0;
+ }
+ 100% {
+ background-position: 200% 0;
+ }
+}
+
+/* Gradient text utility */
+.gradient-text {
+ background: var(--gradient-brand);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+.gradient-text-accent {
+ background: var(--gradient-accent);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+/* Glass morphism effect */
+.glass {
+ background: rgba(255, 255, 255, 0.8);
+ backdrop-filter: blur(20px);
+ -webkit-backdrop-filter: blur(20px);
+ border: 1px solid rgba(255, 255, 255, 0.3);
+}
+
+@media (prefers-color-scheme: dark) {
+ .glass {
+ background: rgba(10, 10, 10, 0.8);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ }
+}
+
+/* Noise texture overlay */
+.noise-overlay::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
+ opacity: 0.02;
+ pointer-events: none;
+ z-index: 1;
+}
+
+/* Animated underline for links */
+.animated-underline {
+ position: relative;
+ display: inline-block;
+}
+
+.animated-underline::after {
+ content: "";
+ position: absolute;
+ bottom: -2px;
+ left: 0;
+ width: 0;
+ height: 2px;
+ background: var(--gradient-brand);
+ transition: width 0.3s var(--ease-out-expo);
+}
+
+.animated-underline:hover::after {
+ width: 100%;
+}
+
+/* Shimmer effect for loading states */
+.shimmer {
+ background: linear-gradient(
+ 90deg,
+ transparent 0%,
+ rgba(255, 255, 255, 0.4) 50%,
+ transparent 100%
+ );
+ background-size: 200% 100%;
+ animation: shimmer 1.5s infinite;
+}
+
+/* Card hover effect */
+.card-hover {
+ transition: all 0.4s var(--ease-out-expo);
+}
+
+.card-hover:hover {
+ transform: translateY(-8px);
+ box-shadow: var(--shadow-2xl);
+}
+
+/* Interactive card with border glow */
+.card-glow {
+ position: relative;
+ transition: all 0.4s var(--ease-out-expo);
+}
+
+.card-glow::before {
+ content: "";
+ position: absolute;
+ inset: -2px;
+ background: var(--gradient-brand);
+ border-radius: inherit;
+ opacity: 0;
+ z-index: -1;
+ transition: opacity 0.4s var(--ease-out-expo);
+}
+
+.card-glow:hover::before {
+ opacity: 1;
+}
+
+.card-glow:hover {
+ transform: translateY(-4px);
+}
+
+/* Magnetic button effect helper */
+.magnetic {
+ transition: transform 0.3s var(--ease-out-expo);
+}
+
+/* Icon hover rotation */
+.icon-spin {
+ transition: transform 0.5s var(--ease-spring);
+}
+
+.icon-spin:hover {
+ transform: rotate(360deg);
+}
+
+/* Section padding utility */
+.section-padding {
+ padding: 5rem 1.5rem;
+}
+
+@media (min-width: 768px) {
+ .section-padding {
+ padding: 7rem 2rem;
+ }
+}
+
+@media (min-width: 1024px) {
+ .section-padding {
+ padding: 8rem 4rem;
+ }
+}
+
+/* Container max width */
+.container-max {
+ max-width: 1400px;
+ margin: 0 auto;
+}
+
+/* Decorative blob shapes */
+.blob {
+ position: absolute;
+ border-radius: 50%;
+ filter: blur(60px);
+ opacity: 0.4;
+ pointer-events: none;
+}
+
+.blob-brand {
+ background: hsl(0, 100%, 70%);
+}
+
+.blob-accent {
+ background: hsl(150, 80%, 60%);
+}
+
+/* Line decoration */
+.line-decoration {
+ width: 60px;
+ height: 4px;
+ background: var(--gradient-brand);
+ border-radius: 2px;
+}
+
+/* Stagger animation helper */
+.stagger > * {
+ opacity: 0;
+ animation: slideUp 0.6s var(--ease-out-expo) forwards;
+}
+
+.stagger > *:nth-child(1) { animation-delay: 0.1s; }
+.stagger > *:nth-child(2) { animation-delay: 0.2s; }
+.stagger > *:nth-child(3) { animation-delay: 0.3s; }
+.stagger > *:nth-child(4) { animation-delay: 0.4s; }
+.stagger > *:nth-child(5) { animation-delay: 0.5s; }
+.stagger > *:nth-child(6) { animation-delay: 0.6s; }
+
+/* Text shadow for headings */
+.text-shadow {
+ text-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+/* Hover lift effect */
+.hover-lift {
+ transition: transform 0.3s var(--ease-out-expo), box-shadow 0.3s var(--ease-out-expo);
+}
+
+.hover-lift:hover {
+ transform: translateY(-4px);
+ box-shadow: var(--shadow-lg);
+}
+
+/* Scale on hover */
+.hover-scale {
+ transition: transform 0.3s var(--ease-spring);
+}
+
+.hover-scale:hover {
+ transform: scale(1.05);
+}
+
+/* Rotate on hover */
+.hover-rotate {
+ transition: transform 0.4s var(--ease-spring);
+}
+
+.hover-rotate:hover {
+ transform: rotate(3deg);
+}
+
+/* Border gradient effect */
+.border-gradient {
+ position: relative;
+ background: var(--background);
+}
+
+.border-gradient::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ padding: 2px;
+ background: var(--gradient-brand);
+ border-radius: inherit;
+ mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
+ mask-composite: exclude;
+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
+ -webkit-mask-composite: xor;
+ pointer-events: none;
}
diff --git a/app/layout.tsx b/app/layout.tsx
index f7fa87e..f6503fd 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,20 +1,38 @@
import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
+import { Inter, Outfit } from "next/font/google";
import "./globals.css";
-const geistSans = Geist({
+const inter = Inter({
variable: "--font-geist-sans",
subsets: ["latin"],
+ display: "swap",
});
-const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
+const outfit = Outfit({
+ variable: "--font-outfit",
subsets: ["latin"],
+ display: "swap",
});
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "TCM Sales & Marketing | Foodservice & Janitorial Experts",
+ description:
+ "With over 100 years of combined experience, TCM Sales & Marketing provides expert foodservice and janitorial solutions across the Rocky Mountain and Northwest regions.",
+ keywords: [
+ "foodservice",
+ "janitorial",
+ "sales",
+ "marketing",
+ "Rocky Mountain",
+ "food packaging",
+ "sustainability",
+ "green products",
+ ],
+ openGraph: {
+ title: "TCM Sales & Marketing",
+ description: "Your Foodservice and Janitorial Sales Experts",
+ type: "website",
+ },
};
export default function RootLayout({
@@ -23,10 +41,8 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
-
-
+
+
{children}
diff --git a/app/page.tsx b/app/page.tsx
index 295f8fd..6b9ef3d 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,65 +1,781 @@
+"use client";
+
+import { motion, useScroll, useTransform } from "framer-motion";
import Image from "next/image";
+import { useRef } from "react";
+import Navigation from "./components/Navigation";
+import Footer from "./components/Footer";
+import AnimatedButton from "./components/AnimatedButton";
+import FadeIn, { StaggerContainer, StaggerItem } from "./components/FadeIn";
+import {
+ ArrowRightIcon,
+ PackageIcon,
+ LeafIcon,
+ UsersIcon,
+ TruckIcon,
+ TargetIcon,
+ HeartIcon,
+ SparklesIcon,
+ MapPinIcon,
+ CheckIcon,
+ RecycleIcon,
+} from "./components/Icons";
+
+const stats = [
+ { value: "100+", label: "Years Combined Experience" },
+ { value: "10", label: "States Covered" },
+ { value: "2005", label: "Industry Trusted Since" },
+ { value: "5", label: "Product Categories" },
+];
+
+const productCategories = [
+ {
+ icon: PackageIcon,
+ title: "Food Packaging",
+ description:
+ "Premium containers, cutlery, and packaging solutions for every foodservice need.",
+ color: "from-orange-500 to-red-500",
+ },
+ {
+ icon: LeafIcon,
+ title: "Green Products",
+ description:
+ "Sustainable, compostable, and eco-friendly alternatives for conscious businesses.",
+ color: "from-emerald-500 to-teal-500",
+ },
+ {
+ icon: SparklesIcon,
+ title: "Specialty Products",
+ description:
+ "Custom printed containers, wraps, and premium catering solutions.",
+ color: "from-purple-500 to-pink-500",
+ },
+ {
+ icon: TruckIcon,
+ title: "Janitorial",
+ description:
+ "Complete range of cleaning supplies and janitorial essentials.",
+ color: "from-blue-500 to-cyan-500",
+ },
+];
+
+const values = [
+ {
+ icon: HeartIcon,
+ title: "Family First",
+ description:
+ "Building character, strengthening individuals, and nurturing families.",
+ },
+ {
+ icon: UsersIcon,
+ title: "Integrity",
+ description: "Selflessness, servanthood, and confident humility in all we do.",
+ },
+ {
+ icon: TargetIcon,
+ title: "Purpose Driven",
+ description: "Professional, ethical representation with symbiotic growth.",
+ },
+];
+
+const territories = [
+ "Colorado",
+ "Washington",
+ "Oregon",
+ "Idaho",
+ "Utah",
+ "Wyoming",
+ "Montana",
+ "New Mexico",
+ "Nebraska",
+ "Arizona",
+];
export default function Home() {
+ const heroRef = useRef(null);
+ const { scrollYProgress } = useScroll({
+ target: heroRef,
+ offset: ["start start", "end start"],
+ });
+
+ const heroY = useTransform(scrollYProgress, [0, 1], ["0%", "30%"]);
+ const heroOpacity = useTransform(scrollYProgress, [0, 0.5], [1, 0]);
+
return (
-
-
-
+
+
+ {/* Hero Section */}
+
+ {/* Animated background elements */}
+
+
+
+
+
+
+ {/* Grid pattern overlay */}
+
-
-
- To get started, edit the page.tsx file.
-
-
- Looking for a starting point or more instructions? Head over to{" "}
-
- Templates
- {" "}
- or the{" "}
-
- Learning
- {" "}
- center.
-
-
-
+
+
+
+
+
+
+
+ Our Coverage
+
+
+
+
+ Serving the{" "}
+ Rocky Mountain {" "}
+ & Northwest {" "}
+ Regions
+
+
+
+
+ Our head office is in Denver, Colorado, but our dedicated team
+ works across ten states to provide exceptional service and
+ support.
+
+
+
+ {/* Territory grid */}
+
+
+ {territories.map((territory, index) => (
+
+
+ {territory}
+
+ ))}
+
+
+
+
+
+
+
+
+ {/* Decorative Map Visual */}
+
+
+
+
+ {/* Floating location dots */}
+ {[
+ { top: "20%", left: "30%" },
+ { top: "40%", left: "60%" },
+ { top: "60%", left: "25%" },
+ { top: "75%", left: "70%" },
+ { top: "30%", left: "75%" },
+ ].map((pos, i) => (
+
+ ))}
+
+
+
+
+
+
+ {/* Sustainability CTA */}
+
+ {/* Background decoration */}
+
+
+
+
+
+
+
+
+
+
+
+ Committed to{" "}
+ Sustainability
+
+
+
+
+ Go green and find the perfect sustainable product options for
+ your business. We offer a comprehensive range of eco-friendly,
+ compostable, and recyclable alternatives.
+
+
+
+
+
}
+ >
+ Explore Green Products
+
+
+ State Ordinances
+
+
+
+
+
+
+
+ {/* Final CTA */}
+
+ {/* Background pattern */}
+
+
+
+
+
+ Ready to Get Started?
+
+
+
+
+ Let's talk about your foodservice and janitorial needs. Our team
+ is here to help you find the perfect solutions.
+
+
+
+
+ }
+ >
+ Contact Us Today
+
+
+
+
+
+
+
+
);
}
diff --git a/package.json b/package.json
index d5a5976..8d36086 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"lint": "eslint"
},
"dependencies": {
+ "framer-motion": "^12.23.26",
"next": "16.1.0",
"react": "19.2.3",
"react-dom": "19.2.3"
diff --git a/yarn.lock b/yarn.lock
index b46c18f..0d03287 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1713,6 +1713,15 @@ for-each@^0.3.3, for-each@^0.3.5:
dependencies:
is-callable "^1.2.7"
+framer-motion@^12.23.26:
+ version "12.23.26"
+ resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-12.23.26.tgz#2a684e9b156118e1c4989d7fc9327def83480391"
+ integrity sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==
+ dependencies:
+ motion-dom "^12.23.23"
+ motion-utils "^12.23.6"
+ tslib "^2.4.0"
+
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
@@ -2356,6 +2365,18 @@ minimist@^1.2.0, minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+motion-dom@^12.23.23:
+ version "12.23.23"
+ resolved "https://registry.yarnpkg.com/motion-dom/-/motion-dom-12.23.23.tgz#8f874333ea1a04ee3a89eb928f518b463d589e0e"
+ integrity sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==
+ dependencies:
+ motion-utils "^12.23.6"
+
+motion-utils@^12.23.6:
+ version "12.23.6"
+ resolved "https://registry.yarnpkg.com/motion-utils/-/motion-utils-12.23.6.tgz#fafef80b4ea85122dd0d6c599a0c63d72881f312"
+ integrity sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==
+
ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"