Initial build: Great Bear microbrewery site

- TanStack Start (React 19, Tailwind 4) frontend recreated from Stitch design
- PocketBase backend with schema migration + idempotent content seed
- Single Docker image running both services (non-root, healthchecked)
- deploy.sh to build & push to registry.tanshu.com
- Ansible playbook (roles: app, caddy) deploying to www.greatbear.in
  with Caddy TLS entries for the site and the PocketBase admin
This commit is contained in:
2026-09-03 08:51:47 +05:30
commit 7b070fde81
66 changed files with 8375 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
import { HeadContent, Outlet, Scripts, createRootRoute } from '@tanstack/react-router'
import * as React from 'react'
import appCss from '~/styles/app.css?url'
import { SiteHeader } from '~/components/site-header'
import { SiteFooter } from '~/components/site-footer'
import { getSettings } from '~/lib/data'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ name: 'theme-color', content: '#1a120b' },
],
links: [{ rel: 'stylesheet', href: appCss }],
scripts: [],
}),
loader: () => getSettings(),
shellComponent: RootDocument,
component: SiteLayout,
})
function SiteLayout() {
const settings = Route.useLoaderData()
return (
<>
<SiteHeader />
<main className="w-full bg-surface pt-20">
<Outlet />
</main>
<SiteFooter settings={settings} />
</>
)
}
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
)
}
+241
View File
@@ -0,0 +1,241 @@
import { createFileRoute } from '@tanstack/react-router'
import { getHomeData } from '~/lib/data'
import { QuickReserveForm } from '~/components/quick-reserve-form'
export const Route = createFileRoute('/')({
head: () => ({
meta: [
{
title: 'The Great Bear Microbrewery | Chandigarhs Finest Craft Brewery',
},
{
name: 'description',
content:
'Handcrafted small-batch brews, wood-fired gastronomy, and the citys most vibrant rooftop lounge — SCO 32, Sector 26, Chandigarh.',
},
],
}),
loader: () => getHomeData(),
component: HomePage,
})
function HomePage() {
const { stats, featuredBrews, experiences, testimonials } = Route.useLoaderData()
return (
<div className="flex w-full flex-col">
{/* Cinematic Hero Section */}
<section className="relative -mt-20 flex min-h-[870px] w-full items-center justify-center overflow-hidden pt-20">
<div
className="absolute inset-0 z-0 scale-105 bg-cover bg-center transition-transform duration-1000"
style={{ backgroundImage: "url('/images/hero-home.jpg')" }}
/>
<div className="absolute inset-0 z-10 bg-gradient-to-t from-surface via-surface/60 to-transparent" />
<div className="relative z-20 mx-auto flex max-w-7xl flex-col items-center gap-space-lg px-grid-margin py-space-2xl text-center">
<div className="inline-flex items-center gap-space-sm rounded-full border border-outline-variant/30 bg-surface-container/80 px-space-md py-space-xs text-label-lg uppercase tracking-widest text-primary backdrop-blur-md">
<span className="material-symbols-outlined text-[16px]">local_bar</span>
SCO 32, Sector 26, Chandigarh
</div>
<h1 className="max-w-4xl font-headline-xl text-headline-xl tracking-tight text-on-surface">
Chandigarh's Finest <span className="text-primary">Craft Brewery</span>
</h1>
<p className="max-w-2xl font-body-lg text-body-lg text-on-surface-variant">
Where industrial warmth meets artisanal mastery. Experience handcrafted small-batch
brews, wood-fired gastronomy, and the city's most vibrant rooftop lounge.
</p>
<div className="mt-space-sm flex flex-wrap items-center justify-center gap-space-md">
<a
className="flex items-center gap-space-sm rounded-lg bg-primary px-space-lg py-space-md font-label-lg text-on-primary transition-all hover:bg-primary-container hover:shadow-[0_0_20px_rgba(217,119,6,0.4)]"
href="#brews"
>
<span>Explore Brews</span>
<span className="material-symbols-outlined text-[18px]">arrow_forward</span>
</a>
<a
className="flex items-center gap-space-sm rounded-lg bg-surface-container-high/80 font-label-lg text-on-surface backdrop-blur-md transition-all hover:bg-surface-bright"
href="#reserve"
>
<span>Reserve a Table</span>
<span className="material-symbols-outlined text-[18px]">event_seat</span>
</a>
</div>
</div>
</section>
{/* Quick Stats / Highlights Bar */}
<section className="w-full bg-surface-container-low py-space-xl">
<div className="mx-auto grid max-w-7xl grid-cols-2 gap-grid-gutter px-grid-margin text-center md:grid-cols-4">
{stats.map((stat) => (
<div
key={stat.uid}
className="flex flex-col gap-space-xs rounded-xl bg-surface-container/50 p-space-md"
>
<span className="font-headline-xl text-primary">{stat.value}</span>
<span className="font-label-lg uppercase text-on-surface-variant">{stat.label}</span>
</div>
))}
</div>
</section>
{/* Featured Artisan Beers */}
<section className="w-full py-space-2xl" id="brews">
<div className="mx-auto flex max-w-7xl flex-col gap-space-xl px-grid-margin">
<div className="flex flex-col justify-between gap-space-md md:flex-row md:items-end">
<div className="flex flex-col gap-space-xs">
<span className="text-label-lg uppercase tracking-widest text-primary">
Fresh From The Cellar
</span>
<h2 className="font-headline-lg text-on-surface">Featured Artisan Beers</h2>
</div>
<p className="max-w-md text-body-md text-on-surface-variant">
Brewed on-site using imported German hops, crystal-clear Himalayan water, and
traditional time-honored techniques.
</p>
</div>
<div className="grid grid-cols-1 gap-grid-gutter md:grid-cols-2 lg:grid-cols-4">
{featuredBrews.map((brew) => (
<div
key={brew.uid}
className="group flex flex-col overflow-hidden rounded-xl bg-surface-container shadow-md transition-all duration-300 hover:-translate-y-1"
>
<div
className="relative h-64 w-full bg-cover bg-center"
style={{ backgroundImage: `url('${brew.image}')` }}
>
<div className="absolute right-space-sm top-space-sm rounded bg-surface/80 px-space-sm py-space-xs text-label-md uppercase text-primary backdrop-blur-sm">
ABV {brew.abv}%
</div>
</div>
<div className="flex flex-1 flex-col justify-between gap-space-md p-space-lg">
<div className="flex flex-col gap-space-xs">
<div className="text-label-md uppercase tracking-wider text-primary">
{brew.style}
</div>
<h3 className="font-headline-md text-on-surface">{brew.name}</h3>
<p className="text-body-sm text-on-surface-variant">{brew.description}</p>
</div>
<div className="flex items-center justify-between border-t border-outline-variant/10 pt-space-md">
<span className="text-label-md text-on-surface-variant">IBU: {brew.ibu}</span>
<a
href="/our-brews"
className="flex items-center gap-space-xs text-label-lg text-primary group-hover:underline"
>
Tasting Notes{' '}
<span className="material-symbols-outlined text-[16px]">chevron_right</span>
</a>
</div>
</div>
</div>
))}
</div>
</div>
</section>
{/* Ambiance Highlights (Bento Grid layout) */}
<section className="w-full bg-surface-container-low py-space-2xl">
<div className="mx-auto flex max-w-7xl flex-col gap-space-xl px-grid-margin">
<div className="mx-auto flex max-w-2xl flex-col gap-space-xs text-center">
<span className="text-label-lg uppercase tracking-widest text-primary">
The Experience
</span>
<h2 className="font-headline-lg text-on-surface">Designed for Unforgettable Nights</h2>
<p className="text-body-md text-on-surface-variant">
Sector 26's premier destination for craft connoisseurs and social gatherings.
</p>
</div>
<div className="grid grid-cols-1 gap-grid-gutter md:grid-cols-3">
{experiences.map((exp) => (
<div key={exp.uid} className="group flex flex-col overflow-hidden rounded-xl bg-surface-container">
<div
className="h-72 w-full bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
style={{ backgroundImage: `url('${exp.image}')` }}
/>
<div className="flex flex-col gap-space-sm p-space-lg">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="material-symbols-outlined">{exp.icon}</span>
</div>
<h3 className="font-headline-md text-on-surface">{exp.title}</h3>
<p className="text-body-sm text-on-surface-variant">{exp.description}</p>
</div>
</div>
))}
</div>
</div>
</section>
{/* Customer Testimonials */}
<section className="w-full py-space-2xl">
<div className="mx-auto flex max-w-7xl flex-col gap-space-xl px-grid-margin">
<div className="mx-auto flex max-w-2xl flex-col gap-space-xs text-center">
<span className="text-label-lg uppercase tracking-widest text-primary">
Testimonials
</span>
<h2 className="font-headline-lg text-on-surface">Loved by Chandigarh</h2>
</div>
<div className="grid grid-cols-1 gap-grid-gutter md:grid-cols-3">
{testimonials.map((t) => (
<div
key={t.uid}
className="flex flex-col justify-between gap-space-lg rounded-xl bg-surface-container p-space-lg"
>
<div className="flex flex-col gap-space-md">
<div className="flex items-center gap-space-xs text-primary">
{Array.from({ length: t.rating }).map((_, i) => (
<span
key={i}
className="material-symbols-outlined text-[18px]"
style={{ fontVariationSettings: "'FILL' 1" }}
>
star
</span>
))}
</div>
<p className="text-body-md italic text-on-surface">"{t.quote}"</p>
</div>
<div className="flex items-center gap-space-md border-t border-outline-variant/10 pt-space-md">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-surface-bright font-headline-md text-primary">
{t.name
.split(' ')
.map((part) => part[0])
.slice(0, 2)
.join('')
.toUpperCase()}
</div>
<div className="flex flex-col">
<span className="text-label-lg text-on-surface">{t.name}</span>
<span className="text-label-md text-on-surface-variant">{t.role}</span>
</div>
</div>
</div>
))}
</div>
</div>
</section>
{/* Reserve / CTA Section */}
<section
className="relative w-full overflow-hidden bg-surface-container-low py-space-2xl"
id="reserve"
>
<div
className="absolute inset-0 bg-cover bg-center opacity-10"
style={{ backgroundImage: "url('/images/reserve-bg.jpg')" }}
/>
<div className="relative z-10 mx-auto flex max-w-4xl flex-col items-center gap-space-lg px-grid-margin text-center">
<div className="inline-flex items-center gap-space-sm rounded-full bg-primary/20 px-space-md py-space-xs text-label-lg uppercase tracking-widest text-primary">
<span className="material-symbols-outlined text-[16px]">schedule</span>
Book Your Experience
</div>
<h2 className="font-headline-xl text-on-surface">Join Us For a Pint Tonight</h2>
<p className="max-w-xl text-body-lg text-on-surface-variant">
Whether it's an intimate dinner or a large celebration, secure your table at
Chandigarh's finest microbrewery in advance.
</p>
<div className="mt-space-md w-full max-w-xl">
<QuickReserveForm />
</div>
</div>
</section>
</div>
)
}
+76
View File
@@ -0,0 +1,76 @@
import { createFileRoute } from '@tanstack/react-router'
import { getMenuData } from '~/lib/data'
import { MenuBrowser } from '~/components/menu-browser'
export const Route = createFileRoute('/menu')({
head: () => ({
meta: [
{ title: 'Menu | The Great Bear Microbrewery' },
{
name: 'description',
content:
'Wood-fired pizzas, tandoori & tapas, burgers and artisanal desserts — every dish designed to complement our house beers.',
},
],
}),
loader: () => getMenuData(),
component: MenuPage,
})
function MenuPage() {
const { categories, items, pairings } = Route.useLoaderData()
return (
<div className="flex w-full flex-col">
{/* Hero / Category Header */}
<section className="relative w-full overflow-hidden bg-surface-container-lowest py-space-xl">
<div
className="absolute inset-0 bg-cover bg-center opacity-20"
style={{ backgroundImage: "url('/images/menu-hero.jpg')" }}
/>
<div className="absolute inset-0 bg-gradient-to-t from-surface via-surface/80 to-transparent" />
<div className="relative mx-auto flex max-w-7xl flex-col items-center px-grid-margin text-center">
<span className="mb-space-sm text-label-lg uppercase tracking-widest text-primary">
Artisanal Gastropub Menu
</span>
<h1 className="mb-space-md max-w-3xl font-headline-xl text-on-surface">
Flavors Crafted for the Glass &amp; Plate
</h1>
<p className="max-w-xl font-body-lg text-body-lg text-on-surface-variant">
Every dish on our menu is thoughtfully designed to complement the complex malt profiles
and hop notes of our freshly brewed house beers.
</p>
</div>
</section>
{/* Interactive Menu + Sticky Filter */}
<MenuBrowser categories={categories} items={items} />
{/* Pairing Recommendations Banner */}
<section className="mt-space-2xl w-full bg-surface-container-low py-space-xl">
<div className="mx-auto grid max-w-7xl grid-cols-1 items-center gap-grid-gutter px-grid-margin md:grid-cols-3">
<div className="flex flex-col gap-space-sm">
<span className="text-label-lg uppercase text-primary">Cicerone Approved</span>
<h2 className="font-headline-lg text-on-surface">
The Science of Pairing Craft &amp; Kitchen
</h2>
<p className="text-body-md text-on-surface-variant">
Our master brewer collaborates daily with our executive chef to harmonize hop
bitterness, malt sweetness, and umami richness for an unforgettable tasting journey.
</p>
</div>
<div className="grid grid-cols-1 gap-grid-gutter sm:grid-cols-2 md:col-span-2">
{pairings.map((pairing) => (
<div key={pairing.uid} className="rounded-xl bg-surface p-space-lg shadow">
<span className="mb-space-xs block font-headline-md text-primary">
{pairing.title}
</span>
<p className="text-body-sm text-on-surface-variant">{pairing.description}</p>
</div>
))}
</div>
</div>
</section>
</div>
)
}
+239
View File
@@ -0,0 +1,239 @@
import { createFileRoute } from '@tanstack/react-router'
import { getBrewsData } from '~/lib/data'
import { TastingFlight } from '~/components/tasting-flight'
export const Route = createFileRoute('/our-brews')({
head: () => ({
meta: [
{ title: 'Our Brews | The Great Bear Microbrewery' },
{
name: 'description',
content:
'Explore our core lineup and seasonal experiments — handcrafted in small batches within our state-of-the-art copper kettles.',
},
],
}),
loader: () => getBrewsData(),
component: OurBrewsPage,
})
function OurBrewsPage() {
const { flagship, coreBrews, seasonalBrews, flightBrews } = Route.useLoaderData()
const tapsFlowing = flightBrews.length
return (
<div className="flex w-full flex-col">
{/* Hero / Intro Header */}
<section className="relative w-full overflow-hidden bg-surface-container-low px-grid-margin py-space-xl">
<div className="pointer-events-none absolute -right-20 -top-20 h-96 w-96 rounded-full bg-primary/10 blur-3xl" />
<div className="relative z-10 mx-auto flex max-w-7xl flex-col justify-between gap-space-lg md:flex-row md:items-center">
<div className="flex max-w-2xl flex-col gap-space-md">
<div className="flex items-center gap-space-sm">
<span className="h-[1px] w-12 bg-primary" />
<span className="text-label-lg uppercase tracking-widest text-primary">
On Tap Today
</span>
</div>
<h1 className="font-headline-xl text-headline-xl text-on-surface">
Freshly Brewed Masterpieces
</h1>
<p className="text-body-lg text-on-surface-variant">
Handcrafted in small batches within our state-of-the-art copper kettles. Explore our
core lineup and seasonal experiments designed to challenge and delight your palate.
</p>
</div>
<div className="flex flex-col items-center gap-space-md rounded-xl bg-surface-container p-space-md shadow-lg sm:flex-row">
<div className="flex flex-col text-center sm:text-left">
<span className="text-label-md uppercase text-on-surface-variant">
Brewery Status
</span>
<span className="mt-1 flex items-center gap-2 text-body-md font-semibold text-on-surface">
<span className="h-2.5 w-2.5 animate-pulse rounded-full bg-green-500" />{' '}
{tapsFlowing} Taps Flowing Fresh
</span>
</div>
<a
className="rounded-lg bg-primary px-space-md py-space-sm text-center text-label-lg font-medium text-on-primary transition-all hover:bg-primary/90"
href="#tasting-flight"
>
Build a Flight
</a>
</div>
</div>
</section>
{/* Featured Brew Banner */}
{flagship ? (
<section className="w-full px-grid-margin py-space-xl">
<div className="mx-auto grid max-w-7xl grid-cols-1 items-center gap-grid-gutter overflow-hidden rounded-xl bg-surface-container shadow-xl lg:grid-cols-12">
<div className="relative h-96 lg:h-[500px] lg:col-span-6">
<div
className="h-full w-full bg-cover bg-center"
style={{ backgroundImage: `url('${flagship.image}')` }}
/>
<div className="absolute left-4 top-4 rounded-full bg-surface/80 px-space-md py-space-xs backdrop-blur-md">
<span className="text-label-md font-semibold uppercase text-primary">
Flagship Brew
</span>
</div>
</div>
<div className="flex flex-col justify-center gap-space-md p-space-xl lg:col-span-6">
<div className="flex items-center gap-space-sm">
<span className="rounded bg-surface-container-high px-space-sm py-space-xs text-label-md uppercase text-primary">
{flagship.style}
</span>
<span className="text-body-sm text-on-surface-variant">
ABV: {flagship.abv}% | IBU: {flagship.ibu}
</span>
</div>
<h2 className="font-headline-lg text-on-surface">{flagship.name}</h2>
<p className="text-body-md text-on-surface-variant">{flagship.description}</p>
<div className="my-space-sm grid grid-cols-2 gap-space-md">
<div className="rounded-lg bg-surface p-space-md">
<span className="block text-label-md uppercase text-on-surface-variant">
Tasting Notes
</span>
<span className="mt-1 block text-body-sm font-medium text-on-surface">
{flagship.tasting_notes}
</span>
</div>
<div className="rounded-lg bg-surface p-space-md">
<span className="block text-label-md uppercase text-on-surface-variant">
Suggested Pairing
</span>
<span className="mt-1 block text-body-sm font-medium text-on-surface">
{flagship.pairing}
</span>
</div>
</div>
<div className="flex items-center gap-space-md pt-space-sm">
<button
type="button"
className="flex items-center gap-space-sm rounded-lg bg-primary px-space-lg py-space-md text-label-lg font-medium text-on-primary shadow-md transition-all hover:bg-primary/90"
onClick={(event) => {
const button = event.currentTarget
button.disabled = true
const label = button.textContent
button.textContent = 'Added to your table order!'
setTimeout(() => {
button.disabled = false
button.textContent = label
}, 2500)
}}
>
<span className="material-symbols-outlined text-[18px]">sports_bar</span> Order
Pint (500ml)
</button>
</div>
</div>
</div>
</section>
) : null}
{/* Core Beers Grid */}
<section className="w-full bg-surface-container-low px-grid-margin py-space-xl">
<div className="mx-auto flex max-w-7xl flex-col gap-space-xl">
<div className="mx-auto flex max-w-xl flex-col items-center gap-space-sm text-center">
<span className="text-label-lg uppercase tracking-widest text-primary">
The Permanent Taproom Lineup
</span>
<h2 className="font-headline-lg text-on-surface">Crafted Without Compromise</h2>
<p className="text-body-md text-on-surface-variant">
Each brew is an ode to traditional European brewing craft infused with modern Indian
creativity.
</p>
</div>
<div className="grid grid-cols-1 gap-grid-gutter md:grid-cols-2 lg:grid-cols-3">
{coreBrews.map((brew) => (
<div
key={brew.uid}
className="flex flex-col justify-between overflow-hidden rounded-xl bg-surface shadow-md transition-transform hover:-translate-y-1"
>
<div className="relative h-64">
<div
className="h-full w-full bg-cover bg-center"
style={{ backgroundImage: `url('${brew.image}')` }}
/>
<div className="absolute right-4 top-4 rounded-full bg-surface/90 px-space-md py-space-xs backdrop-blur-sm">
<span className="text-label-md font-semibold text-primary">
ABV: {brew.abv}% IBU: {brew.ibu}
</span>
</div>
</div>
<div className="flex flex-grow flex-col gap-space-md p-space-lg">
<div className="flex items-center justify-between">
<h3 className="font-headline-md text-on-surface">{brew.name}</h3>
<span className="text-label-md uppercase tracking-wider text-on-surface-variant">
{brew.style}
</span>
</div>
<p className="text-body-sm text-on-surface-variant">{brew.description}</p>
<div className="mt-auto flex flex-col gap-space-xs border-t border-outline-variant/20 pt-space-md text-body-sm">
<div className="flex justify-between">
<span className="text-on-surface-variant">Notes:</span>
<span className="font-medium text-on-surface">{brew.tasting_notes}</span>
</div>
<div className="flex justify-between">
<span className="text-on-surface-variant">Pairing:</span>
<span className="font-medium text-on-surface">{brew.pairing}</span>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</section>
{/* Seasonal Fruit Beers Section */}
<section className="w-full px-grid-margin py-space-xl">
<div className="mx-auto flex max-w-7xl flex-col items-center gap-space-xl lg:flex-row">
<div className="flex flex-col gap-space-md lg:w-1/2">
<span className="text-label-lg uppercase tracking-widest text-primary">
Limited Release
</span>
<h2 className="font-headline-xl text-on-surface">Seasonal Fruit Infusions</h2>
<p className="text-body-lg text-on-surface-variant">
Our brewmaster experiments with seasonal harvest fruits to create vibrant, refreshing
ales that capture the essence of the changing seasons.
</p>
<div className="my-space-sm flex flex-col gap-space-md">
{seasonalBrews.map((brew) => (
<div
key={brew.uid}
className="flex items-start gap-space-md rounded-xl bg-surface-container p-space-md"
>
<span className="material-symbols-outlined text-[32px] text-primary">
{brew.seasonal_icon || 'local_florist'}
</span>
<div>
<h4 className="font-headline-md text-[18px] text-on-surface">
{brew.name} (ABV: {brew.abv}%)
</h4>
<p className="mt-1 text-body-sm text-on-surface-variant">{brew.description}</p>
</div>
</div>
))}
</div>
</div>
<div className="relative h-[450px] w-full overflow-hidden rounded-xl shadow-2xl lg:w-1/2">
<div
className="h-full w-full bg-cover bg-center"
style={{ backgroundImage: "url('/images/seasonal-flight.jpg')" }}
/>
</div>
</div>
</section>
{/* Interactive Tasting Flight Customizer */}
<section
className="w-full bg-surface-container-low px-grid-margin py-space-2xl"
id="tasting-flight"
>
<div className="mx-auto max-w-4xl">
<TastingFlight brews={flightBrews} />
</div>
</section>
</div>
)
}
+159
View File
@@ -0,0 +1,159 @@
import { createFileRoute } from '@tanstack/react-router'
import { getVisitData } from '~/lib/data'
import { ReservationForm } from '~/components/reservation-form'
export const Route = createFileRoute('/visit')({
head: () => ({
meta: [
{ title: 'Visit & Contact | The Great Bear Microbrewery' },
{
name: 'description',
content:
'Reserve your table at Chandigarhs premier microbrewery — SCO 32, Sector 26, Madhya Marg. Open daily 12:00 PM 1:00 AM.',
},
],
}),
loader: () => getVisitData(),
component: VisitPage,
})
function VisitPage() {
const settings = Route.useLoaderData()
const directionsUrl = `https://maps.google.com/?q=${encodeURIComponent(settings.maps_query)}`
const embedUrl = `https://maps.google.com/maps?q=${encodeURIComponent(settings.maps_query)}&output=embed`
return (
<div className="flex w-full flex-col">
{/* Hero Section with Immersive Atmosphere */}
<div className="relative flex min-h-[500px] w-full items-center justify-center overflow-hidden bg-surface">
<div
className="absolute inset-0 bg-cover bg-center opacity-40 mix-blend-luminosity"
style={{ backgroundImage: "url('/images/visit-hero.jpg')" }}
/>
<div className="absolute inset-0 bg-gradient-to-t from-surface via-surface/60 to-transparent" />
<div className="relative z-10 mx-auto flex max-w-7xl flex-col items-center gap-space-md px-grid-margin py-space-2xl text-center">
<span className="text-label-lg uppercase tracking-widest text-primary">
Get in Touch &amp; Experience The Craft
</span>
<h1 className="font-headline-xl text-headline-xl text-on-surface">
Visit The Great Bear
</h1>
<p className="max-w-2xl font-body-lg text-body-lg text-on-surface-variant">
Step into Chandigarh's premier microbrewery. Whether you're planning an evening with
close friends or reserving a table for a celebration, our doors are open daily.
</p>
</div>
</div>
{/* Main Content Grid: Reservation & Quick Info */}
<section className="mx-auto grid w-full max-w-7xl grid-cols-1 items-start gap-grid-gutter px-grid-margin py-space-xl lg:grid-cols-12">
{/* Left Column: Reservation Form */}
<div className="flex flex-col gap-space-lg rounded-xl bg-surface-container p-space-lg shadow-xl lg:col-span-7">
<div className="flex flex-col gap-space-xs">
<span className="text-label-lg uppercase text-primary">Table Booking</span>
<h2 className="font-headline-lg text-on-surface">Reserve Your Experience</h2>
<p className="text-body-sm text-on-surface-variant">
Fill out the details below and our host will confirm your table promptly.
</p>
</div>
<ReservationForm />
</div>
{/* Right Column: Location, Hours, Contact Card */}
<div className="flex flex-col gap-space-lg lg:col-span-5">
<div className="flex flex-col gap-space-md rounded-xl bg-surface-container p-space-lg shadow-xl">
<div className="flex items-center gap-space-md border-b border-outline-variant/20 pb-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="material-symbols-outlined">schedule</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface">Operating Hours</h3>
<p className="text-body-sm font-medium text-primary">{settings.hours_line}</p>
</div>
</div>
<div className="flex items-center gap-space-md border-b border-outline-variant/20 pb-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="material-symbols-outlined">location_on</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface">Location</h3>
<p className="text-body-sm text-on-surface-variant">
{settings.address_line}
<br />
{settings.city_line}
</p>
</div>
</div>
<div className="flex items-center gap-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="material-symbols-outlined">call</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface">Direct Lines</h3>
<p className="text-body-sm text-on-surface-variant">
{settings.phone_primary}
<br />
{settings.phone_secondary}
</p>
</div>
</div>
</div>
{/* Quick Social Callout */}
<a
className="group flex items-center justify-between rounded-xl bg-surface-container p-space-lg shadow-xl transition-all hover:bg-surface-container-high"
href={settings.instagram_url}
rel="noopener noreferrer"
target="_blank"
>
<div className="flex items-center gap-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-gradient-to-tr from-amber-600 via-rose-600 to-purple-600 text-white">
<span className="material-symbols-outlined">photo_camera</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface transition-colors group-hover:text-primary">
Instagram Feed
</h3>
<p className="text-body-sm text-on-surface-variant">{settings.instagram_handle}</p>
</div>
</div>
<span className="material-symbols-outlined text-on-surface-variant transition-transform group-hover:translate-x-1">
arrow_forward
</span>
</a>
</div>
</section>
{/* Interactive Map Section */}
<section className="w-full bg-surface-container-low py-space-xl">
<div className="mx-auto flex max-w-7xl flex-col gap-space-lg px-grid-margin">
<div className="flex flex-col justify-between gap-space-md md:flex-row md:items-end">
<div>
<span className="text-label-lg uppercase text-primary">Find Us Easily</span>
<h2 className="font-headline-lg text-on-surface">Sector 26, Madhya Marg Hub</h2>
</div>
<a
className="flex items-center gap-space-xs self-start rounded-lg border border-primary bg-transparent px-space-md py-space-sm text-label-lg text-primary transition-all hover:bg-primary hover:text-on-primary md:self-auto"
href={directionsUrl}
rel="noopener noreferrer"
target="_blank"
>
<span className="material-symbols-outlined text-[18px]">directions</span>
Get Directions
</a>
</div>
<div className="h-[450px] w-full overflow-hidden rounded-xl shadow-xl">
<iframe
title="The Great Bear Microbrewery location map"
src={embedUrl}
className="h-full w-full border-0"
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
allowFullScreen
/>
</div>
</div>
</section>
</div>
)
}