From 8b9721bc5fb1ce4d0befd0c5df9f08ae7f583afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mora?= Date: Fri, 19 Dec 2025 04:52:48 -0500 Subject: [PATCH] Added home page. --- .claude/settings.local.json | 8 + app/components/AnimatedButton.tsx | 116 +++++ app/components/FadeIn.tsx | 112 ++++ app/components/Footer.tsx | 231 +++++++++ app/components/Icons.tsx | 310 +++++++++++ app/components/Navigation.tsx | 200 ++++++++ app/globals.css | 432 +++++++++++++++- app/layout.tsx | 36 +- app/page.tsx | 826 ++++++++++++++++++++++++++++-- package.json | 1 + yarn.lock | 21 + 11 files changed, 2226 insertions(+), 67 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 app/components/AnimatedButton.tsx create mode 100644 app/components/FadeIn.tsx create mode 100644 app/components/Footer.tsx create mode 100644 app/components/Icons.tsx create mode 100644 app/components/Navigation.tsx 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 ( + <> + + + + + {/* Mobile Menu */} + + {isMobileMenuOpen && ( + + {/* Backdrop */} + setIsMobileMenuOpen(false)} + /> + + {/* Menu Panel */} + +
+ + + + 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 ( -
-
- Next.js logo + + + {/* Hero Section */} +
+ {/* Animated background elements */} +
+ + + +
+ + {/* Grid pattern overlay */} +
+ + {/* Stats Section */} +
+
+
+
+ {stats.map((stat, index) => ( + + + + {stat.value} + + + {stat.label} + + + + ))} +
+
+
+ + {/* About Section */} +
+
+
+ {/* Content */} +
+ + + About Us + + + +

+ Driving Growth Through{" "} + + Strategic Partnership + +

+
+ +

+ We believe in “pull thru” selling, using key operators to + direct distribution. Our integrated, end-user focused sales + approach ensures we exceed growth goals for our manufacturers. +

+
+ +

+ We maintain continuity with our distributor's sales force, + providing them with the tools they need to successfully sell + our products day-to-day. +

+
+ + } + > + Discover Our Approach + + +
+ + {/* Image/Visual */} + +
+
+ {/* Decorative elements */} +
+ + {[...Array(8)].map((_, i) => ( + + ))} + +
+
+ + TCM Sales + +
+
+ {/* Floating badge */} + + 20+ + Years of Excellence + +
+
+
+
+
+ + {/* Values Section */} +
+
+
+ + + Our Philosophy + + + +

+ Built on{" "} + Strong Values +

+
+ +

+ Our mission is to glorify God by being faithful stewards, + serving our employees and families, and making a positive impact. +

+
+
+ + + {values.map((value) => ( + + + + + +

+ {value.title} +

+

+ {value.description} +

+ + +
+ ))} +
+
+
+ + {/* Products Section */} +
+
+
+
+ + + Our Products + + + +

+ Everything You{" "} + Need +

+
+
+ + } + > + View All Products + + +
+ + + {productCategories.map((category) => ( + + + {/* Gradient overlay on hover */} + + + + + + +

+ {category.title} +

+

+ {category.description} +

+ + + + +
+
+ ))} +
+
+
+ + {/* Territory Section */} +
+ {/* Background map pattern */} + -
-
+ +
+
+
+ + + + 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} + + ))} +
+
+ + +
+ } + > + Contact Us + +
+
+
+ + {/* 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 + + + +
+
+ +