<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Mab • Basement Bar | Erie, PA</title>
<meta name="description" content="The Mab - Private basement bar in Erie, PA. View our menu, upcoming events, and live inventory. Perfect for game days, gatherings, and good times.">
<!-- Tailwind CSS via CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<!-- PapaParse for reliable CSV parsing -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Playfair+Display:wght@700&display=swap');
:root {
--mab-gold: #d4af37;
}
body {
font-family: 'Inter', system_ui, sans-serif;
}
.heading-serif {
font-family: 'Playfair Display', Georgia, serif;
font-weight: 700;
letter-spacing: -0.02em;
}
.bar-bg {
background: linear-gradient(135deg, #0f172a 0%, #020617 100%);
}
.section-header {
position: relative;
display: inline-block;
}
.section-header:after {
content: '';
position: absolute;
bottom: -8px;
left: 0;
width: 60%;
height: 3px;
background: linear-gradient(to right, #d4af37, transparent);
border-radius: 3px;
}
.nav-link {
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.nav-link:hover {
color: #d4af37;
transform: translateY(-1px);
}
.drink-card, .event-card, .stock-card {
transition: transform 0.2s cubic-bezier(0.4, 0.0, 0.2, 1),
box-shadow 0.2s cubic-bezier(0.4, 0.0, 0.2, 1);
}
.drink-card:hover, .event-card:hover, .stock-card:hover {
transform: translateY(-4px);
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
}
.stock-low {
border-color: #f87171;
background-color: #450a0a;
}
.status-badge {
font-size: 0.75rem;
padding: 0.125rem 0.625rem;
border-radius: 9999px;
font-weight: 600;
letter-spacing: 0.025em;
}
.mab-gold {
color: #d4af37;
}
.glass {
backdrop-filter: blur(12px);
}
.menu-tab {
transition: all 0.2s ease;
}
.menu-tab.active {
background-color: #d4af37;
color: #0f172a;
font-weight: 600;
}
.inventory-grid {
scrollbar-width: thin;
scrollbar-color: #475569 #1e2937;
}
.nav-active {
color: #d4af37;
position: relative;
}
.nav-active:after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
right: 0;
height: 2px;
background: #d4af37;
}
.hero-overlay {
background: linear-gradient(
to bottom,
rgba(15, 23, 42, 0.65) 0%,
rgba(2, 6, 23, 0.85) 60%,
rgba(2, 6, 23, 0.95) 100%
);
}
.bar-shadow {
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.3),
0 4px 6px -4px rgb(0 0 0 / 0.3);
}
</style>
</head>
<body class="bg-slate-950 text-slate-200">
<!-- NAVBAR -->
<nav class="bg-slate-900/95 border-b border-slate-800 sticky top-0 z-50 backdrop-blur-lg">
<div class="max-w-screen-2xl mx-auto">
<div class="px-6 py-5 flex items-center justify-between">
<!-- Logo -->
<div class="flex items-center gap-x-3">
<div class="w-11 h-11 bg-gradient-to-br from-amber-400 to-yellow-600 rounded-2xl flex items-center justify-center shadow-inner">
<i class="fa-solid fa-glass-martini text-slate-950 text-3xl"></i>
</div>
<div>
<div class="font-bold text-3xl tracking-tighter heading-serif">THE MAB</div>
<div class="text-[10px] text-slate-500 -mt-1 tracking-[3px]">BASEMENT BAR</div>
</div>
</div>
<!-- Desktop Navigation -->
<div class="hidden md:flex items-center gap-x-8 text-sm font-medium">
<a href="#events" class="nav-link px-3 py-2 text-slate-300 hover:text-white">Events</a>
<a href="#menu" class="nav-link px-3 py-2 text-slate-300 hover:text-white">Menu</a>
<a href="#inventory" class="nav-link px-3 py-2 text-slate-300 hover:text-white">Live Stock</a>
<a href="#order" class="nav-link px-3 py-2 text-slate-300 hover:text-white">Order Drinks</a>
</div>
<!-- Right side actions -->
<div class="flex items-center gap-x-3">
<a href="#order"
class="hidden sm:flex items-center gap-x-2 px-5 py-2.5 bg-white text-slate-900 hover:bg-amber-400 transition-colors text-sm font-semibold rounded-3xl">
<i class="fa-solid fa-glass-cheers mr-2"></i>
<span>Pre-Order Drinks</span>
</a>
<!-- Mobile menu button -->
<button id="mobile-menu-btn"
class="md:hidden w-11 h-11 flex items-center justify-center text-slate-400 hover:text-white hover:bg-slate-800 rounded-2xl transition-colors"
aria-label="Toggle menu">
<i class="fa-solid fa-bars text-xl"></i>
</button>
</div>
</div>
</div>
<!-- Mobile Menu -->
<div id="mobile-menu" class="hidden md:hidden border-t border-slate-800 bg-slate-900 px-6 py-4">
<div class="flex flex-col gap-y-1 text-sm">
<a href="#events" class="mobile-nav-link px-4 py-3 rounded-2xl hover:bg-slate-800">Upcoming Events</a>
<a href="#menu" class="mobile-nav-link px-4 py-3 rounded-2xl hover:bg-slate-800">Drink Menu</a>
<a href="#inventory" class="mobile-nav-link px-4 py-3 rounded-2xl hover:bg-slate-800">Live Inventory</a>
<a href="#order" class="mobile-nav-link px-4 py-3 rounded-2xl hover:bg-slate-800">Pre-Order Drinks</a>
<div class="pt-3 mt-2 border-t border-slate-800">
<a href="#order"
class="flex items-center justify-center gap-x-2 w-full px-5 py-3 bg-white text-slate-900 font-semibold rounded-3xl text-sm">
<i class="fa-solid fa-glass-cheers"></i>
<span>Pre-Order for an Event</span>
</a>
</div>
</div>
</div>
</nav>
<!-- HERO SECTION -->
<header class="relative h-[100dvh] min-h-[620px] flex items-center justify-center overflow-hidden">
<!-- Background -->
<div class="absolute inset-0 bg-[radial-gradient(#334155_0.8px,transparent_1px)] bg-[length:5px_5px] opacity-40"></div>
<div class="absolute inset-0 bar-bg"></div>
<!-- Hero image overlay (replace with your actual bar photo) -->
<div class="absolute inset-0 bg-cover bg-center opacity-40"
style="background-image: url('https://picsum.photos/id/1015/2000/1400')"></div>
<div class="hero-overlay absolute inset-0"></div>
<div class="relative z-10 max-w-5xl px-6 text-center">
<div class="inline-flex items-center gap-x-2 px-4 py-1.5 rounded-full bg-white/10 backdrop-blur-md border border-white/20 mb-6">
<div class="w-2 h-2 bg-emerald-400 rounded-full animate-pulse"></div>
<span class="text-xs font-medium tracking-widest text-emerald-300">ERIE, PENNSYLVANIA • EST. 2026</span>
</div>
<h1 class="text-7xl md:text-8xl font-bold tracking-tighter heading-serif mb-4">THE MAB</h1>
<p class="text-2xl md:text-3xl text-slate-300 max-w-md mx-auto mb-3">Your private basement bar.</p>
<p class="text-lg text-slate-400 max-w-lg mx-auto mb-10">Game days. Gatherings. Great drinks. Even better company.</p>
<div class="flex flex-col sm:flex-row items-center justify-center gap-4">
<a href="#menu"
class="group inline-flex items-center justify-center gap-x-3 px-8 py-4 bg-white hover:bg-amber-400 active:bg-amber-500 transition-all text-slate-950 font-semibold rounded-3xl text-base shadow-xl w-full sm:w-auto">
<span>Explore the Menu</span>
<i class="fa-solid fa-arrow-right group-hover:translate-x-0.5 transition-transform"></i>
</a>
<a href="#inventory"
class="inline-flex items-center justify-center gap-x-3 px-8 py-4 border border-white/40 hover:bg-white/10 transition-all font-medium rounded-3xl text-base w-full sm:w-auto">
<i class="fa-solid fa-boxes mr-2"></i>
<span>Check Live Stock</span>
</a>
</div>
<div class="mt-12 flex items-center justify-center gap-x-8 text-xs text-slate-500">
<div class="flex items-center gap-x-2">
<i class="fa-solid fa-users"></i>
<span>Private venue</span>
</div>
<div class="flex items-center gap-x-2">
<i class="fa-solid fa-futbol"></i>
<span>Michigan themed</span>
</div>
<div class="flex items-center gap-x-2">
<i class="fa-solid fa-music"></i>
<span>JBL PartyBox + Karaoke</span>
</div>
</div>
</div>
<div class="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center text-xs tracking-widest text-slate-500">
<span>SCROLL TO BEGIN</span>
<i class="fa-solid fa-chevron-down mt-1.5 animate-bounce"></i>
</div>
</header>
<!-- ABOUT / INTRO -->
<div class="max-w-screen-2xl mx-auto px-6 pt-16 pb-8">
<div class="max-w-3xl mx-auto text-center">
<div class="uppercase tracking-[3px] text-xs font-semibold text-amber-400 mb-3">Welcome to our little slice of heaven</div>
<h2 class="text-4xl md:text-5xl font-semibold tracking-tight heading-serif mb-6">A basement bar built for memories.</h2>
<p class="text-lg text-slate-400 leading-relaxed">
Tucked away in Erie, Pennsylvania, The Mab is our custom-built basement bar — complete with a live-edge bar top,
kegerator, 75" TV for game days, Michigan Wolverines pride, and a killer sound system.
It's where we host friends, watch football, celebrate birthdays, and unwind after long weeks.
</p>
</div>
</div>
<!-- UPCOMING EVENTS -->
<section id="events" class="max-w-screen-2xl mx-auto px-6 pt-12 pb-16">
<div class="flex items-end justify-between mb-8">
<div>
<div class="flex items-center gap-x-3 mb-2">
<i class="fa-solid fa-calendar-check text-amber-400 text-2xl"></i>
<h2 class="section-header text-4xl font-semibold tracking-tight">Upcoming Events</h2>
</div>
<p class="text-slate-400">Pull up a stool. Here's what's on the calendar.</p>
</div>
<a href="#order" class="hidden md:flex items-center text-sm font-medium text-amber-400 hover:text-amber-300 transition-colors">
Want to host something? <span class="ml-1">→</span>
</a>
</div>
<!-- Events Grid - Populated by JS from Google Sheet -->
<div id="events-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- JS injected event cards -->
</div>
<div id="events-loading" class="hidden py-8 text-center text-slate-500">
<i class="fa-solid fa-spinner fa-spin mr-2"></i> Loading events...
</div>
<div class="mt-6 text-center">
<p class="text-xs text-slate-500">Events are managed in our shared Google Sheet • Updates appear here automatically</p>
</div>
</section>
<!-- MENU SECTION -->
<section id="menu" class="bg-slate-900 py-16 border-y border-slate-800">
<div class="max-w-screen-2xl mx-auto px-6">
<div class="flex flex-col md:flex-row md:items-end md:justify-between gap-y-4 mb-10">
<div>
<div class="flex items-center gap-x-3 mb-2">
<i class="fa-solid fa-book text-amber-400 text-2xl"></i>
<h2 class="section-header text-4xl font-semibold tracking-tight">Drink Menu</h2>
</div>
<p class="text-slate-400 max-w-md">Signature cocktails, cold beer on tap, and all the classics. No pretension — just good drinks.</p>
</div>
<div class="flex items-center gap-x-2 text-sm">
<div class="px-3 py-1.5 bg-slate-950 border border-slate-700 rounded-2xl text-xs flex items-center gap-x-2">
<i class="fa-solid fa-beer-mug-empty text-amber-400"></i>
<span>Kegerator always flowing</span>
</div>
</div>
</div>
<!-- Menu Category Tabs -->
<div class="flex flex-wrap gap-2 mb-8 border-b border-slate-700 pb-1" id="menu-tabs">
<button onclick="filterMenu('all')" class="menu-tab active px-5 py-2 text-sm font-medium rounded-2xl bg-amber-400 text-slate-950" data-filter="all">All Drinks</button>
<button onclick="filterMenu('cocktail')" class="menu-tab px-5 py-2 text-sm font-medium rounded-2xl hover:bg-slate-800" data-filter="cocktail">Signature Cocktails</button>
<button onclick="filterMenu('beer')" class="menu-tab px-5 py-2 text-sm font-medium rounded-2xl hover:bg-slate-800" data-filter="beer">Beer & Draft</button>
<button onclick="filterMenu('classic')" class="menu-tab px-5 py-2 text-sm font-medium rounded-2xl hover:bg-slate-800" data-filter="classic">Classics & Shots</button>
<button onclick="filterMenu('nonalc')" class="menu-tab px-5 py-2 text-sm font-medium rounded-2xl hover:bg-slate-800" data-filter="nonalc">Non-Alcoholic</button>
</div>
<!-- Menu Items Grid -->
<div id="menu-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
<!-- Populated by JS on load -->
</div>
<div class="mt-8 text-center text-xs text-slate-500">
Prices not listed — this is a private bar. Tips & bottle contributions always appreciated for big groups.
</div>
</div>
</section>
<!-- LIVE INVENTORY / SUPPLIES -->
<section id="inventory" class="max-w-screen-2xl mx-auto px-6 py-16">
<div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-y-4 mb-8">
<div>
<div class="flex items-center gap-x-3 mb-2">
<i class="fa-solid fa-boxes-stacked text-amber-400 text-2xl"></i>
<h2 class="section-header text-4xl font-semibold tracking-tight">Live Stock & Supplies</h2>
</div>
<p class="text-slate-400">Real-time inventory pulled from our Google Sheet. Updated whenever we restock.</p>
</div>
<div class="flex items-center gap-x-3">
<button onclick="refreshInventory()"
class="flex items-center gap-x-2 px-4 py-2 text-sm font-medium border border-slate-700 hover:bg-slate-800 transition-colors rounded-2xl">
<i class="fa-solid fa-sync-alt"></i>
<span>Refresh</span>
</button>
<div id="last-updated" class="text-xs text-slate-500 px-3 py-2 bg-slate-900 rounded-2xl border border-slate-800 hidden md:block">
<!-- JS populated -->
</div>
</div>
</div>
<!-- Stats Row -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-5">
<div class="text-xs uppercase tracking-widest text-slate-500">Items Tracked</div>
<div id="stat-total" class="text-4xl font-semibold mt-1 text-white">—</div>
</div>
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-5">
<div class="text-xs uppercase tracking-widest text-emerald-400">Fully Stocked</div>
<div id="stat-good" class="text-4xl font-semibold mt-1 text-emerald-400">—</div>
</div>
<div class="bg-slate-900 border border-rose-900/60 rounded-3xl p-5">
<div class="text-xs uppercase tracking-widest text-rose-400">Running Low</div>
<div id="stat-low" class="text-4xl font-semibold mt-1 text-rose-400">—</div>
</div>
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-5 flex flex-col justify-between">
<div>
<div class="text-xs uppercase tracking-widest text-slate-500">Last Synced</div>
<div id="stat-time" class="font-mono text-sm mt-1 text-slate-300">Just now</div>
</div>
<div class="text-[10px] text-emerald-400 flex items-center gap-x-1">
<i class="fa-solid fa-check-circle"></i>
<span>Connected to Google Sheets</span>
</div>
</div>
</div>
<!-- Search + Filters -->
<div class="flex flex-col md:flex-row gap-3 mb-6">
<div class="flex-1 relative">
<i class="fa-solid fa-search absolute left-4 top-3.5 text-slate-500"></i>
<input id="inventory-search"
type="text"
placeholder="Search items (vodka, limes, beer...)"
onkeyup="filterInventory()"
class="w-full bg-slate-900 border border-slate-700 focus:border-amber-400 transition-colors pl-11 pr-4 py-3 rounded-2xl text-sm placeholder:text-slate-500">
</div>
<select id="category-filter" onchange="filterInventory()"
class="bg-slate-900 border border-slate-700 focus:border-amber-400 transition-colors px-4 py-3 rounded-2xl text-sm w-full md:w-56">
<option value="">All Categories</option>
<!-- Populated dynamically by JS -->
</select>
</div>
<!-- Inventory Grid -->
<div id="inventory-grid"
class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-4 inventory-grid">
<!-- Populated dynamically via JS -->
</div>
<!-- What We Need Section -->
<div class="mt-12">
<div class="flex items-center gap-x-3 mb-5">
<i class="fa-solid fa-exclamation-triangle text-rose-400"></i>
<h3 class="font-semibold text-xl tracking-tight">What We Need Right Now</h3>
</div>
<div id="needed-grid" class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4">
<!-- Populated by JS from low-stock items -->
</div>
<div id="needed-empty" class="hidden bg-emerald-950/40 border border-emerald-900 rounded-3xl p-6 text-center">
<i class="fa-solid fa-check-double text-emerald-400 text-2xl mb-3"></i>
<p class="font-medium text-emerald-300">The bar is fully stocked! 🎉</p>
<p class="text-sm text-emerald-400/70 mt-1">Thanks to everyone who contributes. You guys are the best.</p>
</div>
</div>
<div class="mt-8 text-center">
<p class="text-xs text-slate-500 max-w-md mx-auto">
Stock levels update automatically from our Google Sheet.
Running low on something? Bring a bottle to your next visit or let us know!
</p>
</div>
</section>
<!-- ORDER / PRE-ORDER CTA -->
<section id="order" class="bg-gradient-to-b from-slate-900 to-slate-950 border-t border-slate-800 py-16">
<div class="max-w-2xl mx-auto px-6 text-center">
<div class="mx-auto w-16 h-16 bg-gradient-to-br from-amber-300 to-yellow-600 rounded-2xl flex items-center justify-center mb-6 shadow-inner">
<i class="fa-solid fa-glass-cheers text-4xl text-slate-950"></i>
</div>
<h2 class="text-4xl font-semibold tracking-tight mb-4 heading-serif">Planning a night at The Mab?</h2>
<p class="text-lg text-slate-400 mb-8 max-w-md mx-auto">
Use our simple order form to pre-order drinks for your group or upcoming event.
We'll have everything ready when you arrive.
</p>
<a href="https://docs.google.com/forms/d/1_NML39mh4uxo9C8o2m9UwMdpGIPZ7SaDQmF7r3J-koU/viewform" target="_blank"
class="inline-flex items-center justify-center gap-x-3 px-10 py-4 bg-white hover:bg-amber-400 active:bg-amber-500 transition-all text-slate-950 font-bold text-lg rounded-3xl shadow-2xl w-full sm:w-auto">
<span>Open Drink Order Form</span>
<i class="fa-solid fa-external-link-alt text-sm"></i>
</a>
<div class="mt-6 text-xs text-slate-500 flex items-center justify-center gap-x-2">
<i class="fa-solid fa-info-circle"></i>
<span>Responses go straight to our shared spreadsheet</span>
</div>
</div>
</section>
<!-- FOOTER -->
<footer class="bg-black border-t border-slate-800 py-10">
<div class="max-w-screen-2xl mx-auto px-6 text-center text-xs text-slate-500">
<div class="flex flex-col md:flex-row items-center justify-center gap-x-6 gap-y-2 mb-4">
<div>THE MAB • Private Basement Bar</div>
<div class="hidden md:block">•</div>
<div>Erie, Pennsylvania</div>
<div class="hidden md:block">•</div>
<div>Not open to the public • By invitation or request only</div>
</div>
<div class="text-[10px] opacity-60">
Built with ❤️ and too many late nights. Stock data powered by Google Sheets.
</div>
</div>
</footer>
<!-- Demo Mode Banner (shown only when using sample data) -->
<div id="demo-banner" class="hidden fixed bottom-4 left-4 right-4 md:left-auto md:right-4 md:w-96 bg-slate-900 border border-amber-900/60 rounded-3xl p-4 shadow-2xl z-[60]">
<div class="flex gap-x-3">
<div class="text-amber-400 mt-0.5">
<i class="fa-solid fa-exclamation-triangle"></i>
</div>
<div class="flex-1 text-xs">
<div class="font-semibold text-amber-300">Demo Mode Active</div>
<div class="text-slate-400 mt-0.5 leading-snug">This page is showing sample data. Replace the Google Sheet URLs in the code to connect your live inventory and events.</div>
</div>
<button onclick="hideDemoBanner()" class="text-slate-500 hover:text-white self-start text-xl leading-none">×</button>
</div>
</div>
<script>
// ============================================
// TAILWIND CONFIG
// ============================================
function initTailwind() {
document.documentElement.style.setProperty('--accent', '#d4af37');
tailwind.config = {
theme: {
extend: {
fontFamily: {
'serif-custom': ['Playfair Display', 'Georgia', 'serif']
}
}
}
};
}
// ============================================
// GOOGLE SHEETS CONFIGURATION
// ============================================
const INVENTORY_CSV_URL = "https://docs.google.com/spreadsheets/d/e/2PACX-1vSjwQkdWqW1InhF4KzOp62goKQUVYQ_gCpO55Js0FmrKH7DyyMMvHIYSViWFWQ8CPjb8u9edguCPCvk/pub?gid=621662953&output=csv";
const EVENTS_CSV_URL = "https://docs.google.com/spreadsheets/d/e/2PACX-1vSjwQkdWqW1InhF4KzOp62goKQUVYQ_gCpO55Js0FmrKH7DyyMMvHIYSViWFWQ8CPjb8u9edguCPCvk/pub?gid=662147836&output=csv";
const GOOGLE_FORM_URL = "https://docs.google.com/forms/d/1_NML39mh4uxo9C8o2m9UwMdpGIPZ7SaDQmF7r3J-koU/viewform";
// ============================================
// SAMPLE / DEMO DATA (used if live fetch fails or URLs not replaced)
// ============================================
const sampleEvents = [
{
Date: "2026-07-04",
Title: "Independence Day Bash",
Description: "BBQ on the Blackstone, cold beers, fireworks viewing from the yard, and the JBL cranked. Kids welcome until 9pm.",
Time: "4:00 PM – 11:00 PM",
Status: "Open for RSVP"
},
{
Date: "2026-07-18",
Title: "Summer Sips & Vinyl Night",
Description: "Bring your favorite record or just come chill. Signature summer cocktails on special + yard games.",
Time: "7:00 PM – 12:00 AM",
Status: "Open for RSVP"
},
{
Date: "2026-08-30",
Title: "Michigan Football Season Opener Watch Party",
Description: "The boys are back. Big screen, kegerator flowing, and the Block M on full display. Maize & Blue mandatory.",
Time: "TBD (Game time)",
Status: "Invite Only"
}
];
const sampleInventory = [
{ Item: "Tito's Vodka", Category: "Liquor", Quantity: "4", Unit: "750ml bottles", Threshold: "2", Notes: "Well vodka staple" },
{ Item: "Maker's Mark", Category: "Liquor", Quantity: "2", Unit: "750ml bottles", Threshold: "1", Notes: "Bourbon" },
{ Item: "Captain Morgan Spiced", Category: "Liquor", Quantity: "1", Unit: "1L bottle", Threshold: "1", Notes: "Rum" },
{ Item: "Tanqueray Gin", Category: "Liquor", Quantity: "3", Unit: "750ml bottles", Threshold: "1", Notes: "" },
{ Item: "Jose Cuervo Gold", Category: "Liquor", Quantity: "2", Unit: "750ml bottles", Threshold: "1", Notes: "Tequila" },
{ Item: "Bud Light (Keg)", Category: "Beer", Quantity: "1", Unit: "1/6 barrel", Threshold: "0.5", Notes: "Current on tap" },
{ Item: "Miller Lite Cans", Category: "Beer", Quantity: "18", Unit: "cans", Threshold: "12", Notes: "Backup for big groups" },
{ Item: "Local IPA (Rotating)", Category: "Beer", Quantity: "8", Unit: "cans", Threshold: "6", Notes: "Ask what's on tap" },
{ Item: "Chardonnay (Box)", Category: "Wine", Quantity: "1", Unit: "3L box", Threshold: "0.5", Notes: "House white" },
{ Item: "Cabernet Sauvignon", Category: "Wine", Quantity: "3", Unit: "bottles", Threshold: "2", Notes: "" },
{ Item: "Coca-Cola", Category: "Mixers", Quantity: "6", Unit: "2L bottles", Threshold: "3", Notes: "" },
{ Item: "Tonic Water", Category: "Mixers", Quantity: "4", Unit: "1L bottles", Threshold: "2", Notes: "Fever-Tree preferred" },
{ Item: "Limes (Fresh)", Category: "Garnishes", Quantity: "6", Unit: "pieces", Threshold: "10", Notes: "Running low — please bring more!" },
{ Item: "Maraschino Cherries", Category: "Garnishes", Quantity: "1", Unit: "jar", Threshold: "1", Notes: "" },
{ Item: "Olives", Category: "Garnishes", Quantity: "2", Unit: "jars", Threshold: "1", Notes: "" },
{ Item: "Solo Cups (Red)", Category: "Other", Quantity: "42", Unit: "cups", Threshold: "24", Notes: "Party pack" },
{ Item: "Cocktail Napkins", Category: "Other", Quantity: "80", Unit: "napkins", Threshold: "50", Notes: "" },
{ Item: "Ice (Bags)", Category: "Other", Quantity: "2", Unit: "10lb bags", Threshold: "2", Notes: "Buy fresh before events" }
];
// ============================================
// MENU DATA (static for now — easy to edit)
// ============================================
const menuItems = [
// Signature Cocktails
{ name: "The Block M Old Fashioned", type: "cocktail", desc: "Maker's Mark, Angostura bitters, orange peel, Luxardo cherry. Michigan strong.", badge: "Signature" },
{ name: "Wolverine Whiskey Sour", type: "cocktail", desc: "Bourbon, fresh lemon, simple syrup, egg white (optional). Shaken hard.", badge: "Signature" },
{ name: "Ann Arbor Mule", type: "cocktail", desc: "Tito's, ginger beer, lime, mint. Served in a copper mug with a Block M stamp.", badge: "Popular" },
{ name: "The Mab Manhattan", type: "cocktail", desc: "Rye or bourbon, sweet vermouth, bitters. Classic, stirred, with a cherry.", badge: "" },
{ name: "Blue & Gold Margarita", type: "cocktail", desc: "Tequila, blue curaçao, lime, agave. Bright, fun, and dangerously drinkable.", badge: "Signature" },
// Beer & Draft
{ name: "Kegerator Tap (Rotating)", type: "beer", desc: "Currently featuring a local IPA + Bud Light. Ask what's flowing tonight.", badge: "On Tap" },
{ name: "Miller Lite", type: "beer", desc: "The reliable backup. Ice cold cans always in the fridge.", badge: "" },
{ name: "Local Craft Selection", type: "beer", desc: "Rotating cans from Erie-area and Pennsylvania breweries. Ask for the current lineup.", badge: "" },
// Classics & Shots
{ name: "Classic Old Fashioned", type: "classic", desc: "The gold standard. Bourbon or rye, bitters, sugar, orange.", badge: "" },
{ name: "Lemon Drop Shot", type: "classic", desc: "Vodka, triple sec, fresh lemon. Sugared rim. Dangerous in groups.", badge: "" },
{ name: "Kamikaze", type: "classic", desc: "Vodka, triple sec, lime. Simple, tart, and effective.", badge: "" },
{ name: "Jägerbomb", type: "classic", desc: "Jägermeister dropped into Red Bull. For when the night needs a boost.", badge: "" },
// Non-Alcoholic
{ name: "Virgin Mule", type: "nonalc", desc: "Ginger beer, fresh lime, mint, splash of soda. All the flavor, none of the buzz.", badge: "" },
{ name: "Shirley Temple", type: "nonalc", desc: "Ginger ale, grenadine, maraschino cherry. Classic and nostalgic.", badge: "" },
{ name: "Soda & Bitters", type: "nonalc", desc: "Club soda or ginger ale with a few dashes of Angostura. Surprisingly complex.", badge: "" }
];
// ============================================
// RENDER MENU
// ============================================
function renderMenu(filteredItems = null) {
const container = document.getElementById('menu-grid');
container.innerHTML = '';
const itemsToShow = filteredItems || menuItems;
itemsToShow.forEach(item => {
const card = document.createElement('div');
card.className = `drink-card bg-slate-900 border border-slate-700 hover:border-amber-400/40 rounded-3xl p-5 flex flex-col h-full`;
let badgeHTML = '';
if (item.badge) {
const badgeColor = item.badge === 'Signature' || item.badge === 'Popular' || item.badge === 'On Tap'
? 'bg-amber-400 text-slate-950'
: 'bg-slate-700 text-slate-300';
badgeHTML = `<span class="inline-block text-[10px] font-bold px-3 py-0.5 rounded-full ${badgeColor} mb-3 tracking-wider">${item.badge}</span>`;
}
card.innerHTML = `
<div>
${badgeHTML}
<h4 class="font-semibold text-lg leading-tight tracking-tight mb-2">${item.name}</h4>
<p class="text-sm text-slate-400 leading-snug">${item.desc}</p>
</div>
<div class="mt-auto pt-4 flex items-center justify-between text-xs">
<span class="px-2.5 py-1 bg-slate-800 text-slate-400 rounded-xl">${item.type.charAt(0).toUpperCase() + item.type.slice(1)}</span>
</div>
`;
container.appendChild(card);
});
}
function filterMenu(category) {
document.querySelectorAll('#menu-tabs button').forEach(btn => {
btn.classList.remove('active', 'bg-amber-400', 'text-slate-950');
btn.classList.add('hover:bg-slate-800');
if (category === 'all' && btn.dataset.filter === 'all') {
btn.classList.add('active', 'bg-amber-400', 'text-slate-950');
btn.classList.remove('hover:bg-slate-800');
} else if (btn.dataset.filter === category) {
btn.classList.add('active', 'bg-amber-400', 'text-slate-950');
btn.classList.remove('hover:bg-slate-800');
}
});
let filtered = menuItems;
if (category !== 'all') {
filtered = menuItems.filter(item => item.type === category);
}
renderMenu(filtered);
}
// ============================================
// RENDER EVENTS (from Google Sheet or sample)
// ============================================
function renderEvents(events) {
const container = document.getElementById('events-grid');
container.innerHTML = '';
if (!events || events.length === 0) {
container.innerHTML = `
<div class="col-span-full bg-slate-900 border border-slate-700 rounded-3xl p-8 text-center">
<p class="text-slate-400">No upcoming events scheduled yet. Check back soon!</p>
</div>
`;
return;
}
events.sort((a, b) => new Date(a.Date) - new Date(b.Date));
events.forEach(event => {
const dateObj = new Date(event.Date);
const dateStr = dateObj.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: dateObj.getFullYear() !== new Date().getFullYear() ? 'numeric' : undefined
});
const statusColor = event.Status && event.Status.toLowerCase().includes('open')
? 'bg-emerald-400 text-emerald-950'
: 'bg-amber-400 text-amber-950';
const card = document.createElement('div');
card.className = `event-card bg-slate-900 border border-slate-700 hover:border-amber-400/30 rounded-3xl p-6 flex flex-col`;
card.innerHTML = `
<div class="flex justify-between items-start mb-4">
<div>
<div class="text-xs font-mono tracking-widest text-amber-400">${dateStr}</div>
<h4 class="font-semibold text-xl leading-tight tracking-tight mt-1">${event.Title}</h4>
</div>
${event.Status ? `<span class="status-badge ${statusColor} whitespace-nowrap">${event.Status}</span>` : ''}
</div>
<p class="text-sm text-slate-300 flex-1 leading-relaxed">${event.Description || ''}</p>
<div class="mt-5 pt-4 border-t border-slate-700 flex items-center justify-between text-sm">
<div class="flex items-center text-slate-400">
<i class="fa-regular fa-clock mr-2"></i>
<span>${event.Time || 'TBD'}</span>
</div>
<a href="${GOOGLE_FORM_URL}" target="_blank"
class="inline-flex items-center text-amber-400 hover:text-amber-300 font-medium text-sm">
RSVP <i class="fa-solid fa-arrow-right ml-1.5 text-xs"></i>
</a>
</div>
`;
container.appendChild(card);
});
}
// ============================================
// INVENTORY FUNCTIONS
// ============================================
let currentInventoryData = [];
let currentCategories = [];
function renderInventory(data) {
currentInventoryData = data;
const container = document.getElementById('inventory-grid');
container.innerHTML = '';
updateInventoryStats(data);
populateCategoryFilter(data);
if (!data || data.length === 0) {
container.innerHTML = `<div class="col-span-full text-center py-8 text-slate-400">No inventory data found.</div>`;
return;
}
data.forEach(item => {
const qty = parseFloat(item.Quantity) || 0;
const threshold = parseFloat(item.Threshold) || 1;
const isLow = qty <= threshold;
const card = document.createElement('div');
card.className = `stock-card bg-slate-900 border ${isLow ? 'stock-low border-rose-600' : 'border-slate-700'} rounded-3xl p-4 flex flex-col`;
const statusHTML = isLow
? `<span class="status-badge bg-rose-500 text-white">LOW STOCK</span>`
: `<span class="status-badge bg-emerald-500 text-emerald-950">In Stock</span>`;
card.innerHTML = `
<div class="flex justify-between items-start">
<div class="text-xs px-2.5 py-px bg-slate-800 text-slate-400 rounded-xl self-start">${item.Category || 'Other'}</div>
${statusHTML}
</div>
<div class="mt-3 flex-1">
<div class="font-semibold tracking-tight leading-tight">${item.Item}</div>
${item.Notes ? `<div class="text-[10px] text-slate-500 mt-1 line-clamp-2">${item.Notes}</div>` : ''}
</div>
<div class="mt-4 flex items-baseline justify-between">
<div>
<span class="text-3xl font-bold tabular-nums">${qty}</span>
<span class="text-xs text-slate-400 ml-1">${item.Unit || ''}</span>
</div>
${isLow ?
`<div class="text-[10px] text-rose-400 font-medium">Needs restock</div>` :
`<div class="text-[10px] text-emerald-400/70">Good</div>`
}
</div>
`;
container.appendChild(card);
});
renderNeededItems(data);
}
function updateInventoryStats(data) {
const total = data.length;
let good = 0;
let low = 0;
data.forEach(item => {
const qty = parseFloat(item.Quantity) || 0;
const threshold = parseFloat(item.Threshold) || 1;
if (qty <= threshold) low++;
else good++;
});
document.getElementById('stat-total').textContent = total;
document.getElementById('stat-good').textContent = good;
document.getElementById('stat-low').textContent = low;
const timeEl = document.getElementById('last-updated');
timeEl.innerHTML = `<i class="fa-regular fa-clock mr-1"></i> ${new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'})}`;
timeEl.classList.remove('hidden');
document.getElementById('stat-time').textContent = new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'});
}
function populateCategoryFilter(data) {
const select = document.getElementById('category-filter');
const categories = [...new Set(data.map(item => item.Category).filter(Boolean))].sort();
currentCategories = categories;
select.innerHTML = '<option value="">All Categories</option>';
categories.forEach(cat => {
const opt = document.createElement('option');
opt.value = cat;
opt.textContent = cat;
select.appendChild(opt);
});
}
function filterInventory() {
const searchTerm = document.getElementById('inventory-search').value.toLowerCase().trim();
const categoryFilter = document.getElementById('category-filter').value;
let filtered = currentInventoryData;
if (searchTerm) {
filtered = filtered.filter(item =>
(item.Item && item.Item.toLowerCase().includes(searchTerm)) ||
(item.Notes && item.Notes.toLowerCase().includes(searchTerm)) ||
(item.Category && item.Category.toLowerCase().includes(searchTerm))
);
}
if (categoryFilter) {
filtered = filtered.filter(item => item.Category === categoryFilter);
}
const container = document.getElementById('inventory-grid');
container.innerHTML = '';
if (filtered.length === 0) {
container.innerHTML = `<div class="col-span-full text-center py-8 text-slate-400">No matching items found.</div>`;
return;
}
filtered.forEach(item => {
const qty = parseFloat(item.Quantity) || 0;
const threshold = parseFloat(item.Threshold) || 1;
const isLow = qty <= threshold;
const card = document.createElement('div');
card.className = `stock-card bg-slate-900 border ${isLow ? 'stock-low border-rose-600' : 'border-slate-700'} rounded-3xl p-4 flex flex-col`;
const statusHTML = isLow
? `<span class="status-badge bg-rose-500 text-white">LOW STOCK</span>`
: `<span class="status-badge bg-emerald-500 text-emerald-950">In Stock</span>`;
card.innerHTML = `
<div class="flex justify-between items-start">
<div class="text-xs px-2.5 py-px bg-slate-800 text-slate-400 rounded-xl self-start">${item.Category || 'Other'}</div>
${statusHTML}
</div>
<div class="mt-3 flex-1">
<div class="font-semibold tracking-tight leading-tight">${item.Item}</div>
${item.Notes ? `<div class="text-[10px] text-slate-500 mt-1 line-clamp-2">${item.Notes}</div>` : ''}
</div>
<div class="mt-4 flex items-baseline justify-between">
<div>
<span class="text-3xl font-bold tabular-nums">${qty}</span>
<span class="text-xs text-slate-400 ml-1">${item.Unit || ''}</span>
</div>
${isLow ?
`<div class="text-[10px] text-rose-400 font-medium">Needs restock</div>` :
`<div class="text-[10px] text-emerald-400/70">Good</div>`
}
</div>
`;
container.appendChild(card);
});
}
function renderNeededItems(data) {
const container = document.getElementById('needed-grid');
const emptyState = document.getElementById('needed-empty');
container.innerHTML = '';
const needed = data.filter(item => {
const qty = parseFloat(item.Quantity) || 0;
const threshold = parseFloat(item.Threshold) || 1;
return qty <= threshold;
});
if (needed.length === 0) {
emptyState.classList.remove('hidden');
container.classList.add('hidden');
return;
}
emptyState.classList.add('hidden');
container.classList.remove('hidden');
needed.forEach(item => {
const card = document.createElement('div');
card.className = `bg-rose-950/30 border border-rose-900 rounded-2xl p-4 text-sm`;
card.innerHTML = `
<div class="flex justify-between items-start">
<div>
<div class="font-semibold">${item.Item}</div>
<div class="text-xs text-rose-300/80 mt-0.5">${item.Category} • ${item.Quantity} ${item.Unit || ''} left</div>
</div>
<i class="fa-solid fa-exclamation-circle text-rose-400 mt-0.5"></i>
</div>
${item.Notes ? `<div class="text-xs text-rose-300/70 mt-2 italic">"${item.Notes}"</div>` : ''}
<div class="mt-3 text-[10px] text-rose-300/60">Bring a bottle next time? We’d appreciate it!</div>
`;
container.appendChild(card);
});
}
async function loadInventory() {
const container = document.getElementById('inventory-grid');
container.innerHTML = `
<div class="col-span-full flex justify-center items-center py-12 text-slate-400">
<i class="fa-solid fa-spinner fa-spin mr-3"></i>
<span>Syncing live inventory from Google Sheets...</span>
</div>
`;
if (!INVENTORY_CSV_URL || INVENTORY_CSV_URL.includes('PASTE_YOUR')) {
renderInventory(sampleInventory);
return;
}
try {
Papa.parse(INVENTORY_CSV_URL, {
download: true,
header: true,
skipEmptyLines: true,
complete: function(results) {
if (results.data && results.data.length > 0) {
renderInventory(results.data);
} else {
renderInventory(sampleInventory);
}
},
error: function(err) {
console.error('PapaParse error loading inventory:', err);
renderInventory(sampleInventory);
}
});
} catch (e) {
console.error(e);
renderInventory(sampleInventory);
}
}
function refreshInventory() {
loadInventory();
}
// ============================================
// LOAD EVENTS
// ============================================
async function loadEvents() {
const container = document.getElementById('events-grid');
const loading = document.getElementById('events-loading');
loading.classList.remove('hidden');
container.innerHTML = '';
if (!EVENTS_CSV_URL || EVENTS_CSV_URL.includes('PASTE_YOUR')) {
loading.classList.add('hidden');
renderEvents(sampleEvents);
return;
}
try {
Papa.parse(EVENTS_CSV_URL, {
download: true,
header: true,
skipEmptyLines: true,
complete: function(results) {
loading.classList.add('hidden');
if (results.data && results.data.length > 0) {
renderEvents(results.data);
} else {
renderEvents(sampleEvents);
}
},
error: function(err) {
console.error('Error loading events:', err);
loading.classList.add('hidden');
renderEvents(sampleEvents);
}
});
} catch (e) {
console.error(e);
loading.classList.add('hidden');
renderEvents(sampleEvents);
}
}
// ============================================
// DEMO BANNER (optional)
// ============================================
function showDemoBanner() {
// Optional - can be removed if not needed
}
function hideDemoBanner() {
// Optional
}
// ============================================
// MOBILE MENU
// ============================================
function initMobileMenu() {
const btn = document.getElementById('mobile-menu-btn');
const menu = document.getElementById('mobile-menu');
btn.addEventListener('click', () => {
if (menu.classList.contains('hidden')) {
menu.classList.remove('hidden');
btn.innerHTML = '<i class="fa-solid fa-times text-xl"></i>';
} else {
menu.classList.add('hidden');
btn.innerHTML = '<i class="fa-solid fa-bars text-xl"></i>';
}
});
document.querySelectorAll('.mobile-nav-link').forEach(link => {
link.addEventListener('click', () => {
menu.classList.add('hidden');
btn.innerHTML = '<i class="fa-solid fa-bars text-xl"></i>';
});
});
}
// ============================================
// SMOOTH SCROLL FOR ANCHOR LINKS
// ============================================
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const target = document.querySelector(this.getAttribute('href'));
if (target) {
e.preventDefault();
const navHeight = 80;
const elementPosition = target.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - navHeight;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
}
});
});
}
// ============================================
// INITIALIZE EVERYTHING
// ============================================
function initializePage() {
initTailwind();
initMobileMenu();
initSmoothScroll();
renderMenu();
loadEvents();
loadInventory();
}
window.onload = initializePage;
</script>
</body>
</html>