first commit
BIN
public/images/crispy-masala.png
Normal file
|
After Width: | Height: | Size: 780 KiB |
BIN
public/images/hero-dosa.png
Normal file
|
After Width: | Height: | Size: 842 KiB |
BIN
public/images/medu-vada.png
Normal file
|
After Width: | Height: | Size: 774 KiB |
BIN
public/images/new.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/images/sambar.png
Normal file
|
After Width: | Height: | Size: 768 KiB |
BIN
public/images/south-indian-thali.png
Normal file
|
After Width: | Height: | Size: 982 KiB |
BIN
public/images/story-heritage.png
Normal file
|
After Width: | Height: | Size: 894 KiB |
@ -1,34 +1,31 @@
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
}
|
||||
--color-primary: #014d33;
|
||||
--color-primary-light: #0d6e4d;
|
||||
--color-secondary: #d99c43;
|
||||
--color-secondary-hover: #b88231;
|
||||
--color-bg-light: #f5f7f2;
|
||||
--color-bg-white: #ffffff;
|
||||
--color-text-dark: #333333;
|
||||
--color-text-medium: #666666;
|
||||
--color-text-light: #f9f9f9;
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
--font-serif: var(--font-playfair), Georgia, serif;
|
||||
--font-sans: var(--font-inter), system-ui, sans-serif;
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
--spacing-xs: 0.5rem;
|
||||
--spacing-sm: 1rem;
|
||||
--spacing-md: 2rem;
|
||||
--spacing-lg: 4rem;
|
||||
--spacing-xl: 6rem;
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--foreground);
|
||||
background: var(--background);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
--border-radius-sm: 4px;
|
||||
--border-radius-md: 8px;
|
||||
--border-radius-lg: 16px;
|
||||
--border-radius-full: 9999px;
|
||||
|
||||
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
--shadow-lg: 0 12px 24px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
* {
|
||||
@ -37,13 +34,53 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
font-family: var(--font-sans);
|
||||
color: var(--color-text-dark);
|
||||
background-color: var(--color-bg-white);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-serif);
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
color-scheme: dark;
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
font-family: var(--font-sans);
|
||||
border: none;
|
||||
background: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--spacing-sm);
|
||||
}
|
||||
|
||||
.section-padding {
|
||||
padding: var(--spacing-xl) 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.section-padding {
|
||||
padding: var(--spacing-lg) 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,24 +1,30 @@
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import { Inter, Playfair_Display, Great_Vibes } from "next/font/google";
|
||||
import "./globals.css";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
const inter = Inter({
|
||||
variable: "--font-inter",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
const playfair = Playfair_Display({
|
||||
variable: "--font-playfair",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const greatVibes = Great_Vibes({
|
||||
variable: "--font-cursive",
|
||||
weight: "400",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
title: "My Dosa Place Restaurant | Authentic & Vibrant",
|
||||
description: "Experience the authentic taste of South India with our premium dosas.",
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
|
||||
<html lang="en" className={`${inter.variable} ${playfair.variable} ${greatVibes.variable}`}>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@ -1,66 +1,37 @@
|
||||
import Image from "next/image";
|
||||
import styles from "./page.module.css";
|
||||
import Navbar from '@/components/Navbar';
|
||||
import HeroSection from '@/components/HeroSection';
|
||||
import FavoritesSection from '@/components/FavoritesSection';
|
||||
import ExperienceSection from '@/components/ExperienceSection';
|
||||
import ProcessSection from '@/components/ProcessSection';
|
||||
import MenuSection from '@/components/MenuSection';
|
||||
import PromoSection from '@/components/PromoSection';
|
||||
import GallerySection from '@/components/GallerySection';
|
||||
import FeaturesSection from '@/components/FeaturesSection';
|
||||
import ReviewsSection from '@/components/ReviewsSection';
|
||||
import BlogSection from '@/components/BlogSection';
|
||||
import LocationSection from '@/components/LocationSection';
|
||||
import Footer from '@/components/Footer';
|
||||
import ScrollToTop from '@/components/ScrollToTop';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className={styles.page}>
|
||||
<main className={styles.main}>
|
||||
<Image
|
||||
className={styles.logo}
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={100}
|
||||
height={20}
|
||||
priority
|
||||
/>
|
||||
<div className={styles.intro}>
|
||||
<h1>To get started, edit the page.js file.</h1>
|
||||
<p>
|
||||
Looking for a starting point or more instructions? Head over to{" "}
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Templates
|
||||
</a>{" "}
|
||||
or the{" "}
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learning
|
||||
</a>{" "}
|
||||
center.
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.ctas}>
|
||||
<a
|
||||
className={styles.primary}
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className={styles.logo}
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Deploy Now
|
||||
</a>
|
||||
<a
|
||||
className={styles.secondary}
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
<>
|
||||
<Navbar />
|
||||
<main>
|
||||
<HeroSection />
|
||||
<FavoritesSection />
|
||||
<ExperienceSection />
|
||||
<ProcessSection />
|
||||
<MenuSection />
|
||||
<PromoSection />
|
||||
<GallerySection />
|
||||
{/* <FeaturesSection /> */}
|
||||
<ReviewsSection />
|
||||
<BlogSection />
|
||||
<LocationSection />
|
||||
</main>
|
||||
</div>
|
||||
<Footer />
|
||||
<ScrollToTop />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,142 +1 @@
|
||||
.page {
|
||||
--background: #fafafa;
|
||||
--foreground: #fff;
|
||||
|
||||
--text-primary: #000;
|
||||
--text-secondary: #666;
|
||||
|
||||
--button-primary-hover: #383838;
|
||||
--button-secondary-hover: #f2f2f2;
|
||||
--button-secondary-border: #ebebeb;
|
||||
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--font-geist-sans);
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
background-color: var(--foreground);
|
||||
padding: 120px 60px;
|
||||
}
|
||||
|
||||
.intro {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
text-align: left;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.intro h1 {
|
||||
max-width: 320px;
|
||||
font-size: 40px;
|
||||
font-weight: 600;
|
||||
line-height: 48px;
|
||||
letter-spacing: -2.4px;
|
||||
text-wrap: balance;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.intro p {
|
||||
max-width: 440px;
|
||||
font-size: 18px;
|
||||
line-height: 32px;
|
||||
text-wrap: balance;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.intro a {
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.ctas {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
max-width: 440px;
|
||||
gap: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ctas a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
padding: 0 16px;
|
||||
border-radius: 128px;
|
||||
border: 1px solid transparent;
|
||||
transition: 0.2s;
|
||||
cursor: pointer;
|
||||
width: fit-content;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
a.primary {
|
||||
background: var(--text-primary);
|
||||
color: var(--background);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
a.secondary {
|
||||
border-color: var(--button-secondary-border);
|
||||
}
|
||||
|
||||
/* Enable hover only on non-touch devices */
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
a.primary:hover {
|
||||
background: var(--button-primary-hover);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
a.secondary:hover {
|
||||
background: var(--button-secondary-hover);
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.main {
|
||||
padding: 48px 24px;
|
||||
}
|
||||
|
||||
.intro {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.intro h1 {
|
||||
font-size: 32px;
|
||||
line-height: 40px;
|
||||
letter-spacing: -1.92px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.logo {
|
||||
filter: invert();
|
||||
}
|
||||
|
||||
.page {
|
||||
--background: #000;
|
||||
--foreground: #000;
|
||||
|
||||
--text-primary: #ededed;
|
||||
--text-secondary: #999;
|
||||
|
||||
--button-primary-hover: #ccc;
|
||||
--button-secondary-hover: #1a1a1a;
|
||||
--button-secondary-border: #1a1a1a;
|
||||
}
|
||||
}
|
||||
/* page.module.css - minimal, page-level styles only */
|
||||
|
||||
55
src/components/BlogSection.js
Normal file
@ -0,0 +1,55 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './BlogSection.module.css';
|
||||
|
||||
const posts = [
|
||||
{
|
||||
title: 'The Secret Behind Our Perfectly Crisp Dosas',
|
||||
date: 'March 15, 2026',
|
||||
excerpt: 'Discover the traditional fermentation process and the precise rice-to-lentil ratio that makes our dosas perfectly crisp every single time.',
|
||||
image: '/images/hero-dosa.png',
|
||||
},
|
||||
{
|
||||
title: '5 Health Benefits of South Indian Cuisine',
|
||||
date: 'February 28, 2026',
|
||||
excerpt: 'From gut-friendly fermented foods to antioxidant-rich spices, learn why South Indian food is as healthy as it is delicious.',
|
||||
image: '/images/south-indian-thali.png',
|
||||
},
|
||||
{
|
||||
title: 'A Guide to South Indian Spices',
|
||||
date: 'February 10, 2026',
|
||||
excerpt: 'Mustard seeds, curry leaves, and tamarind. We break down the essential flavor profiles that define authentic South Indian cooking.',
|
||||
image: '/images/sambar.png',
|
||||
}
|
||||
];
|
||||
|
||||
export default function BlogSection() {
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<p className={styles.sectionTag}>📰 Culinary Journal</p>
|
||||
<h2 className={styles.sectionTitle}>Latest from Our Blog</h2>
|
||||
|
||||
<div className={styles.blogGrid}>
|
||||
{posts.map((post, index) => (
|
||||
<article key={index} className={styles.blogCard}>
|
||||
<div className={styles.imageWrap}>
|
||||
<Image
|
||||
src={post.image}
|
||||
alt={post.title}
|
||||
fill
|
||||
className={styles.image}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
<span className={styles.date}>{post.date}</span>
|
||||
<h3 className={styles.title}>{post.title}</h3>
|
||||
<p className={styles.excerpt}>{post.excerpt}</p>
|
||||
<a href="#" className={styles.readMore}>Read Article →</a>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
120
src/components/BlogSection.module.css
Normal file
@ -0,0 +1,120 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.sectionTag {
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-secondary);
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
text-align: center;
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.4rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.blogGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.blogCard {
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.blogCard:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.imageWrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.image {
|
||||
object-fit: cover;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.blogCard:hover .image {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 0.8rem;
|
||||
color: var(--color-secondary);
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.25rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-text-medium);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.readMore {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.readMore:hover {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.blogGrid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.blogGrid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
10
src/components/Button.js
Normal file
@ -0,0 +1,10 @@
|
||||
import styles from './Button.module.css';
|
||||
|
||||
export default function Button({ children, variant = 'primary', ...props }) {
|
||||
const className = `${styles.button} ${styles[variant]}`;
|
||||
return (
|
||||
<button className={className} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
34
src/components/Button.module.css
Normal file
@ -0,0 +1,34 @@
|
||||
.button {
|
||||
padding: 0.8rem 2rem;
|
||||
border-radius: 999px;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.primary {
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.primary:hover {
|
||||
background: var(--color-primary-dark);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(249, 115, 22, 0.4);
|
||||
}
|
||||
|
||||
.secondary {
|
||||
background: transparent;
|
||||
color: var(--color-text);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-color: var(--color-primary);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
108
src/components/ExperienceSection.js
Normal file
@ -0,0 +1,108 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './ExperienceSection.module.css';
|
||||
|
||||
export default function ExperienceSection() {
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.grid}>
|
||||
{/* Left - Image Collage */}
|
||||
<div className={styles.imageCol}>
|
||||
<div className={styles.collageWrap}>
|
||||
|
||||
{/* Decorative element - top left: leaf/spice SVG */}
|
||||
<div className={styles.decorativeTop}>
|
||||
<svg viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg" width="80" height="80">
|
||||
<path d="M40 5 C10 5 5 40 5 40 C5 40 20 75 40 75 C60 75 75 40 75 40 C75 40 70 5 40 5Z" fill="var(--color-primary)" fillOpacity="0.15" stroke="var(--color-primary)" strokeWidth="1.5" strokeOpacity="0.4"/>
|
||||
<path d="M40 15 C40 15 40 65 40 65" stroke="var(--color-primary)" strokeWidth="1.5" strokeOpacity="0.5" strokeDasharray="3 3"/>
|
||||
<path d="M40 30 C30 25 18 28 15 35" stroke="var(--color-primary)" strokeWidth="1" strokeOpacity="0.4"/>
|
||||
<path d="M40 42 C50 37 62 40 65 47" stroke="var(--color-primary)" strokeWidth="1" strokeOpacity="0.4"/>
|
||||
<path d="M40 20 C32 18 24 22 22 28" stroke="var(--color-primary)" strokeWidth="1" strokeOpacity="0.35"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className={styles.imgLarge}>
|
||||
<Image
|
||||
src="/images/story-heritage.png"
|
||||
alt="Chefs cooking"
|
||||
fill
|
||||
className={styles.image}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.imgSmallBottom}>
|
||||
<Image
|
||||
src="/images/sambar.png"
|
||||
alt="Authentic dishes"
|
||||
fill
|
||||
className={styles.image}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.imgSmallLeft}>
|
||||
<Image
|
||||
src="/images/crispy-masala.png"
|
||||
alt="Making dosa"
|
||||
fill
|
||||
className={styles.image}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.experienceBadge}>
|
||||
<span className={styles.badgeNumber}>25</span>
|
||||
<span className={styles.badgeText}>Years Experience</span>
|
||||
</div>
|
||||
|
||||
{/* Decorative element - bottom right: dosa/plate SVG */}
|
||||
<div className={styles.decorativeBottom}>
|
||||
<svg viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg" width="70" height="70">
|
||||
<circle cx="35" cy="35" r="30" stroke="var(--color-primary)" strokeWidth="1.5" strokeOpacity="0.3" strokeDasharray="4 3"/>
|
||||
<circle cx="35" cy="35" r="22" stroke="var(--color-primary)" strokeWidth="1" strokeOpacity="0.2"/>
|
||||
<circle cx="35" cy="35" r="8" fill="var(--color-primary)" fillOpacity="0.12"/>
|
||||
<path d="M20 35 Q35 20 50 35" stroke="var(--color-primary)" strokeWidth="1.2" strokeOpacity="0.35"/>
|
||||
<path d="M22 40 Q35 52 48 40" stroke="var(--color-primary)" strokeWidth="1.2" strokeOpacity="0.35"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Content */}
|
||||
<div className={styles.contentCol}>
|
||||
<span className={styles.tag}>About Our Heritage</span>
|
||||
<h2 className={styles.title}>Experience & Expertise in Authentic Cuisine</h2>
|
||||
<p className={styles.description}>
|
||||
Born from a deep passion for preserving South Indian culinary traditions, our restaurant brings you the true essence of heritage cooking. Every dish we serve is a testament to our decades of experience in crafting perfect, authentic flavors.
|
||||
</p>
|
||||
|
||||
<div className={styles.featureCards}>
|
||||
<div className={`${styles.featureCard} ${styles.cardSolid}`}>
|
||||
<div className={styles.iconWrap}>
|
||||
<span className={styles.icon}>👨🍳</span>
|
||||
</div>
|
||||
<div className={styles.cardContent}>
|
||||
<h4 className={styles.cardTitle}>Passionate Chefs</h4>
|
||||
<p className={styles.cardDesc}>
|
||||
Our master chefs have spent years perfecting the art of traditional South Indian cooking, bringing authentic recipes to life.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`${styles.featureCard} ${styles.cardOutline}`}>
|
||||
<div className={styles.iconWrap}>
|
||||
<span className={styles.icon}>🌿</span>
|
||||
</div>
|
||||
<div className={styles.cardContent}>
|
||||
<h4 className={styles.cardTitle}>Authentic Ingredients</h4>
|
||||
<p className={styles.cardDesc}>
|
||||
We source the finest spices directly from India and prepare our signature batters fresh every single day.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
264
src/components/ExperienceSection.module.css
Normal file
@ -0,0 +1,264 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: var(--color-bg-light);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.1fr;
|
||||
gap: 5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Left - Image Collage */
|
||||
.imageCol {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.collageWrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.image {
|
||||
object-fit: cover;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.imgLarge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 60%;
|
||||
height: 60%;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
|
||||
z-index: 2;
|
||||
border: 4px solid #fff;
|
||||
}
|
||||
|
||||
.imgSmallBottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 15%;
|
||||
width: 45%;
|
||||
height: 45%;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
|
||||
z-index: 3;
|
||||
border: 4px solid #fff;
|
||||
}
|
||||
|
||||
.imgSmallLeft {
|
||||
position: absolute;
|
||||
top: 35%;
|
||||
left: 0;
|
||||
width: 50%;
|
||||
height: 40%;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
|
||||
z-index: 4;
|
||||
border: 4px solid #fff;
|
||||
}
|
||||
|
||||
.experienceBadge {
|
||||
position: absolute;
|
||||
bottom: 15%;
|
||||
left: 5%;
|
||||
background: var(--color-primary);
|
||||
padding: 1rem 1.5rem;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 25px rgba(1, 77, 51, 0.25);
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.badgeNumber {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 2.2rem;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.badgeNumber::after {
|
||||
content: '+';
|
||||
font-size: 1.5rem;
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.badgeText {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
/* Decorative restaurant elements (leaf top, plate bottom) */
|
||||
.decorativeTop {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: -15px;
|
||||
z-index: 1;
|
||||
opacity: 0.9;
|
||||
animation: floatSlow 5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.decorativeBottom {
|
||||
position: absolute;
|
||||
bottom: 20%;
|
||||
right: -15px;
|
||||
z-index: 1;
|
||||
opacity: 0.9;
|
||||
animation: floatSlow 5s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
@keyframes floatSlow {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-8px); }
|
||||
}
|
||||
|
||||
|
||||
/* Right - Content */
|
||||
.contentCol {
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
background: rgba(1, 77, 51, 0.1);
|
||||
color: var(--color-primary);
|
||||
padding: 0.4rem 1.2rem;
|
||||
border-radius: 20px;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
border: 1px solid rgba(1, 77, 51, 0.2);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
line-height: 1.2;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.7;
|
||||
color: var(--color-text-medium);
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.featureCards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 1.2rem;
|
||||
padding: 1.8rem;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.cardSolid {
|
||||
background: rgba(1, 77, 51, 0.07);
|
||||
border: 1px solid rgba(1, 77, 51, 0.15);
|
||||
}
|
||||
|
||||
.cardOutline {
|
||||
background: #fff;
|
||||
border: 1px solid #e0e0e0;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
.iconWrap {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cardSolid .iconWrap {
|
||||
background: var(--color-primary);
|
||||
box-shadow: 0 4px 10px rgba(1, 77, 51, 0.2);
|
||||
}
|
||||
|
||||
.cardOutline .iconWrap {
|
||||
background: var(--color-bg-light);
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.cardTitle {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-text-dark);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.cardDesc {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
color: var(--color-text-medium);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 4rem;
|
||||
}
|
||||
|
||||
.collageWrap {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
padding: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
65
src/components/FavoritesSection.js
Normal file
@ -0,0 +1,65 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './FavoritesSection.module.css';
|
||||
|
||||
const favorites = [
|
||||
{
|
||||
name: 'Crispy Masala',
|
||||
subtitle: 'Classic',
|
||||
image: '/images/new.png',
|
||||
price: '12.99',
|
||||
description: 'Aromatic, soft, and tender potato masala layered inside a crispy golden crepe infused with the flavors of South Indian spices...',
|
||||
theme: 'green',
|
||||
},
|
||||
{
|
||||
name: 'South Indian Thali',
|
||||
subtitle: 'Royal',
|
||||
image: '/images/new.png',
|
||||
price: '24.99',
|
||||
description: 'A complete feast featuring an array of curries, dal, rice, breads, and desserts served traditionally on a banana leaf...',
|
||||
theme: 'yellow',
|
||||
},
|
||||
{
|
||||
name: 'Authentic Sambar',
|
||||
subtitle: 'Spicy',
|
||||
image: '/images/new.png',
|
||||
price: '8.99',
|
||||
description: 'A flavorful lentil stew made with fresh vegetables, tamarind broth, and our signature roasted spice blend...',
|
||||
theme: 'green',
|
||||
},
|
||||
];
|
||||
|
||||
export default function FavoritesSection() {
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<p className={styles.sectionTag}>Chef's Selection</p>
|
||||
<h2 className={styles.sectionTitle}>Customer Favourites</h2>
|
||||
</div>
|
||||
<div className={styles.grid}>
|
||||
{favorites.map((item, i) => (
|
||||
<div key={i} className={`${styles.card} ${styles[item.theme]}`}>
|
||||
<div className={styles.imageWrap}>
|
||||
<Image
|
||||
src={item.image}
|
||||
alt={item.name}
|
||||
width={280}
|
||||
height={200}
|
||||
className={styles.image}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.cardBody}>
|
||||
<div className={styles.labelRow}>
|
||||
<span className={styles.subtitleTag}>{item.subtitle}</span>
|
||||
{/* <span className={styles.price}>${item.price}</span> */}
|
||||
</div>
|
||||
<h3 className={styles.cardTitle}>{item.name}</h3>
|
||||
<p className={styles.description}>{item.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
147
src/components/FavoritesSection.module.css
Normal file
@ -0,0 +1,147 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.sectionHeader {
|
||||
text-align: center;
|
||||
margin-bottom: 3.5rem;
|
||||
}
|
||||
|
||||
.sectionTag {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-secondary);
|
||||
letter-spacing: 1.5px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.5rem;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* Grid */
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 2rem;
|
||||
/* padding-top: 3.5rem; */
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.card {
|
||||
position: relative;
|
||||
border-radius: 20px;
|
||||
overflow: visible;
|
||||
margin-top: 50px;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Theme Colors */
|
||||
.green {
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.yellow {
|
||||
background-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
/* Image */
|
||||
.imageWrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
margin-top: -50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(0 15px 20px rgba(0, 0, 0, 0.35));
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.card:hover .image {
|
||||
transform: scale(1.06) rotate(2deg);
|
||||
}
|
||||
|
||||
/* Card Body */
|
||||
.cardBody {
|
||||
padding: 0.5rem 1.8rem 2rem;
|
||||
}
|
||||
|
||||
/* Label row: subtitle tag + price side by side */
|
||||
.labelRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.subtitleTag {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1rem;
|
||||
font-style: italic;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1.2rem;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.cardTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
line-height: 1.15;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.6;
|
||||
color: rgba(255, 255, 255, 0.82);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
44
src/components/FeaturesSection.js
Normal file
@ -0,0 +1,44 @@
|
||||
import styles from './FeaturesSection.module.css';
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: '🌿',
|
||||
title: 'Fresh Ingredients',
|
||||
description: 'We source only the freshest, locally available ingredients for authentic taste.',
|
||||
},
|
||||
{
|
||||
icon: '📜',
|
||||
title: 'Famous Recipes',
|
||||
description: 'Time-honored recipes passed down through generations of South Indian kitchens.',
|
||||
},
|
||||
{
|
||||
icon: '🌶️',
|
||||
title: 'Pure Spices',
|
||||
description: 'Hand-ground spices imported directly from the spice gardens of Kerala.',
|
||||
},
|
||||
{
|
||||
icon: '🌙',
|
||||
title: 'Evening Specials',
|
||||
description: 'Exclusive tiffin specials every evening with rotating seasonal menus.',
|
||||
},
|
||||
];
|
||||
|
||||
export default function FeaturesSection() {
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.grid}>
|
||||
{features.map((feature, i) => (
|
||||
<div key={i} className={styles.card}>
|
||||
<div className={styles.iconWrap}>
|
||||
<span className={styles.icon}>{feature.icon}</span>
|
||||
</div>
|
||||
<h3 className={styles.cardTitle}>{feature.title}</h3>
|
||||
<p className={styles.cardDesc}>{feature.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
78
src/components/FeaturesSection.module.css
Normal file
@ -0,0 +1,78 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: var(--color-bg-light);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
text-align: center;
|
||||
padding: 2rem 1.5rem;
|
||||
border-radius: var(--border-radius-lg);
|
||||
border: 1px solid #eee;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: var(--shadow-md);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
.iconWrap {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 0 auto 1.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--color-bg-light);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.cardTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.05rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.cardDesc {
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-medium);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
max-width: 360px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
100
src/components/Footer.js
Normal file
@ -0,0 +1,100 @@
|
||||
import Link from 'next/link';
|
||||
import styles from './Footer.module.css';
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.grid}>
|
||||
{/* Column 1: Brand & Socials */}
|
||||
<div className={styles.brand}>
|
||||
<Link href="/" className={styles.logo}>
|
||||
<span className={styles.logoLeaf}>🌿</span>
|
||||
<span className={styles.logoText}>My Dosa Place</span>
|
||||
</Link>
|
||||
<p className={styles.brandDesc}>
|
||||
Bringing the authentic taste of South India to Waterloo since 1980.
|
||||
Every dosa tells a story of tradition and flavor.
|
||||
</p>
|
||||
<div className={styles.socials}>
|
||||
{/* Real icons */}
|
||||
<a href="#" className={styles.socialLink} aria-label="Facebook">
|
||||
<svg width="18" height="18" fill="currentColor" viewBox="0 0 24 24"><path d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z"/></svg>
|
||||
</a>
|
||||
<a href="#" className={styles.socialLink} aria-label="Instagram">
|
||||
<svg width="18" height="18" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm3.98-10.181a1.44 1.44 0 11-2.88 0 1.44 1.44 0 012.88 0z"/></svg>
|
||||
</a>
|
||||
<a href="#" className={styles.socialLink} aria-label="Twitter">
|
||||
<svg width="18" height="18" fill="currentColor" viewBox="0 0 24 24"><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723 10.054 10.054 0 01-3.127 1.184 4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Column 2: Quick Links */}
|
||||
<div className={styles.column}>
|
||||
<h4 className={styles.columnTitle}>Quick Links</h4>
|
||||
<ul className={styles.linkList}>
|
||||
<li><Link href="/">Home</Link></li>
|
||||
<li><Link href="#about">About Us</Link></li>
|
||||
<li><Link href="#menu">Our Menu</Link></li>
|
||||
<li><Link href="#gallery">Gallery</Link></li>
|
||||
<li><Link href="#contact">Contact Us</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Column 3: Menu Categories */}
|
||||
<div className={styles.column}>
|
||||
<h4 className={styles.columnTitle}>Our Menu</h4>
|
||||
<ul className={styles.linkList}>
|
||||
<li><Link href="#menu">Breakfast</Link></li>
|
||||
<li><Link href="#menu">Appetizer’s</Link></li>
|
||||
<li><Link href="#menu">Breads</Link></li>
|
||||
<li><Link href="#menu">Speciality Dosa</Link></li>
|
||||
<li><Link href="#menu">Lunch</Link></li>
|
||||
<li><Link href="#menu">Utthappam’s</Link></li>
|
||||
<li><Link href="#menu">BEVERAGES</Link></li>
|
||||
<li><Link href="#menu">Combos</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Column 4: Contact */}
|
||||
<div className={styles.column}>
|
||||
<h4 className={styles.columnTitle}>Contact Info</h4>
|
||||
|
||||
<div className={styles.contactItem}>
|
||||
<h5 className={styles.contactLabel}>Address</h5>
|
||||
<p className={styles.contactText}>
|
||||
#922 ERB STREET WEST<br />
|
||||
ON N2T OC3<br />
|
||||
WATERLOO
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.contactItem}>
|
||||
<h5 className={styles.contactLabel}>Reservations</h5>
|
||||
<p className={styles.contactText}>
|
||||
Phone: +1 (519) 888-7459<br />
|
||||
Email: mydosaplacewaterloo@gmail.com
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.contactItem}>
|
||||
<h5 className={styles.contactLabel}>Opening hours</h5>
|
||||
<p className={styles.contactText}>
|
||||
Mon - Thu: 4pm-10pm<br />
|
||||
Fri - Sun: 11am-10pm
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Bar */}
|
||||
<div className={styles.bottomBar}>
|
||||
<p className={styles.copyright}>
|
||||
Copyright 2026 © mydosarestruant. Powered by <a href="https://metatroncubesolutions.com/" target="_blank" rel="noopener noreferrer" className={styles.poweredLink}>MetatronCube</a>. All Right Reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
171
src/components/Footer.module.css
Normal file
@ -0,0 +1,171 @@
|
||||
.footer {
|
||||
background: var(--color-primary);
|
||||
border-top: 1px solid rgba(255,255,255,0.1);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1.5fr 1fr 1fr 1.5fr;
|
||||
gap: 3rem;
|
||||
padding: 5rem 0 4rem;
|
||||
}
|
||||
|
||||
/* Brand */
|
||||
.brand {
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
text-decoration: none;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.logoLeaf {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.logoText {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.brandDesc {
|
||||
font-size: 0.95rem;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.socials {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.socialLink {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.socialLink:hover {
|
||||
background: var(--color-secondary);
|
||||
border-color: var(--color-secondary);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
/* Columns */
|
||||
.column {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.columnTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.3rem;
|
||||
color: var(--color-secondary);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.linkList {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.linkList li {
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.linkList a {
|
||||
font-size: 0.95rem;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.linkList a::before {
|
||||
content: "›";
|
||||
font-size: 1.2rem;
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.linkList a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Contact Info Column */
|
||||
.contactItem {
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
.contactLabel {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.contactText {
|
||||
font-size: 0.9rem;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Bottom Bar */
|
||||
.bottomBar {
|
||||
text-align: center;
|
||||
padding: 2rem 0;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 0.9rem;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.poweredLink {
|
||||
color: var(--color-secondary);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.poweredLink:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4rem 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 3rem;
|
||||
}
|
||||
}
|
||||
42
src/components/GallerySection.js
Normal file
@ -0,0 +1,42 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './GallerySection.module.css';
|
||||
|
||||
const images = [
|
||||
'/images/hero-dosa.png',
|
||||
'/images/south-indian-thali.png',
|
||||
'/images/sambar.png',
|
||||
'/images/crispy-masala.png',
|
||||
'/images/hero-dosa.png',
|
||||
'/images/story-heritage.png'
|
||||
];
|
||||
|
||||
export default function GallerySection() {
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<p className={styles.sectionTag}>📸 Follow Our Journey</p>
|
||||
<h2 className={styles.sectionTitle}>Our Culinary Gallery</h2>
|
||||
|
||||
<div className={styles.galleryGrid}>
|
||||
{images.map((src, index) => (
|
||||
<div key={index} className={styles.galleryItem}>
|
||||
<Image
|
||||
src={src}
|
||||
alt={`Gallery image ${index + 1}`}
|
||||
fill
|
||||
className={styles.image}
|
||||
/>
|
||||
<div className={styles.overlay}>
|
||||
<span className={styles.icon}></span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className={styles.centerBtn}>
|
||||
<a href="#" className={styles.btnInsta}>View on Instagram</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
123
src/components/GallerySection.module.css
Normal file
@ -0,0 +1,123 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.sectionTag {
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-secondary);
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
text-align: center;
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.4rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.galleryGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.galleryItem {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.image {
|
||||
object-fit: cover;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.galleryItem:hover .image {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(1, 77, 51, 0.6);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.galleryItem:hover .overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 2rem;
|
||||
color: #fff;
|
||||
transform: scale(0.5);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.galleryItem:hover .icon {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.centerBtn {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btnInsta {
|
||||
display: inline-block;
|
||||
padding: 0.8rem 2rem;
|
||||
background-color: var(--color-secondary);
|
||||
color: #fff;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
border-radius: 30px;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btnInsta:hover {
|
||||
background-color: var(--color-secondary-hover);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 15px rgba(217, 156, 67, 0.4);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.galleryGrid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.galleryGrid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
107
src/components/HeroSection.js
Normal file
@ -0,0 +1,107 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import styles from './HeroSection.module.css';
|
||||
|
||||
const slides = [
|
||||
{
|
||||
image: '/images/hero-dosa.png',
|
||||
title: 'Authentic South Indian',
|
||||
highlight: 'Vegetarian Flavours',
|
||||
subtitle: 'Welcome to My Dosa Place, where we bring you traditional South Indian cuisine crafted with passion. Every dish tells a story of heritage, flavor, and love.',
|
||||
primaryBtn: 'Explore Menu 🍽️',
|
||||
secondaryBtn: 'Book a Table',
|
||||
},
|
||||
{
|
||||
image: '/images/south-indian-thali.png',
|
||||
title: 'Experience the Royal',
|
||||
highlight: 'South Indian Thali',
|
||||
subtitle: 'A magnificent feast of 21 authentic items served exclusively on weekends. A true celebration of Southern culinary diversity.',
|
||||
primaryBtn: 'View Weekend Specials',
|
||||
secondaryBtn: 'Reserve Now',
|
||||
},
|
||||
{
|
||||
image: '/images/crispy-masala.png',
|
||||
title: 'Crispy, Golden &',
|
||||
highlight: 'Perfectly Spiced',
|
||||
subtitle: 'Taste our signature dosas, made fresh every day with our heritage batter and secret spice blends passed down through generations.',
|
||||
primaryBtn: 'Order Online',
|
||||
secondaryBtn: 'Our Story',
|
||||
}
|
||||
];
|
||||
|
||||
export default function HeroSection() {
|
||||
const [currentSlide, setCurrentSlide] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setCurrentSlide((prev) => (prev + 1) % slides.length);
|
||||
}, 5000); // Change slide every 5 seconds
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section className={styles.hero}>
|
||||
{slides.map((slide, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`${styles.slideBg} ${index === currentSlide ? styles.activeBg : ''}`}
|
||||
style={{ backgroundImage: `url(${slide.image})` }}
|
||||
/>
|
||||
))}
|
||||
<div className={styles.heroOverlay}></div>
|
||||
<div className={styles.heroContent}>
|
||||
{slides.map((slide, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`${styles.textContent} ${index === currentSlide ? styles.activeText : ''}`}
|
||||
>
|
||||
<h1 className={styles.heroTitle}>
|
||||
{slide.title}<br />
|
||||
<span className={styles.highlight}>{slide.highlight}</span> in Waterloo
|
||||
</h1>
|
||||
<p className={styles.heroSubtitle}>
|
||||
{slide.subtitle}
|
||||
</p>
|
||||
<div className={styles.heroActions}>
|
||||
<a href="#menu" className={styles.btnPrimary}>
|
||||
{slide.primaryBtn}
|
||||
</a>
|
||||
<a href="#contact" className={styles.btnSecondary}>
|
||||
{slide.secondaryBtn}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className={styles.heroMeta}>
|
||||
<div className={styles.metaItem}>
|
||||
<span className={styles.metaIcon}>⭐</span>
|
||||
<span>4.9 Rating</span>
|
||||
</div>
|
||||
<div className={styles.metaDivider}></div>
|
||||
<div className={styles.metaItem}>
|
||||
<span className={styles.metaIcon}>🍃</span>
|
||||
<span>100% Vegetarian</span>
|
||||
</div>
|
||||
<div className={styles.metaDivider}></div>
|
||||
<div className={styles.metaItem}>
|
||||
<span className={styles.metaIcon}>🕐</span>
|
||||
<span>Open 7 Days</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Slide Indicators */}
|
||||
<div className={styles.indicators}>
|
||||
{slides.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className={`${styles.indicator} ${index === currentSlide ? styles.activeIndicator : ''}`}
|
||||
onClick={() => setCurrentSlide(index)}
|
||||
aria-label={`Go to slide ${index + 1}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
230
src/components/HeroSection.module.css
Normal file
@ -0,0 +1,230 @@
|
||||
.hero {
|
||||
position: relative;
|
||||
min-height: 92vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 120px 5% 60px;
|
||||
overflow: hidden;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.slideBg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0;
|
||||
transition: opacity 1.5s ease-in-out, transform 8s ease-in-out;
|
||||
transform: scale(1.05);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.activeBg {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.heroOverlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
105deg,
|
||||
rgba(1, 77, 51, 0.92) 0%,
|
||||
rgba(1, 77, 51, 0.75) 45%,
|
||||
rgba(1, 77, 51, 0.3) 70%,
|
||||
transparent 100%
|
||||
);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
max-width: 620px;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.textContent {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
transition: opacity 0.8s ease, transform 0.8s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.activeText {
|
||||
position: relative;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: clamp(2.2rem, 4.5vw, 3.4rem);
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
line-height: 1.15;
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.heroSubtitle {
|
||||
font-size: 1rem;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
line-height: 1.7;
|
||||
margin-bottom: 2rem;
|
||||
max-width: 520px;
|
||||
}
|
||||
|
||||
.heroActions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 2.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btnPrimary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.85rem 2rem;
|
||||
background: var(--color-secondary);
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btnPrimary:hover {
|
||||
background: var(--color-secondary-hover);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(217, 156, 67, 0.4);
|
||||
}
|
||||
|
||||
.btnSecondary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.85rem 2rem;
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
border: 2px solid rgba(255, 255, 255, 0.5);
|
||||
border-radius: var(--border-radius-full);
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btnSecondary:hover {
|
||||
border-color: #fff;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.heroMeta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
margin-top: auto;
|
||||
padding-top: 2rem;
|
||||
}
|
||||
|
||||
.metaItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.metaIcon {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.metaDivider {
|
||||
width: 1px;
|
||||
height: 20px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* Indicators */
|
||||
.indicators {
|
||||
position: absolute;
|
||||
bottom: -40px;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.activeIndicator {
|
||||
background: var(--color-secondary);
|
||||
width: 25px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero {
|
||||
min-height: 80vh;
|
||||
padding: 100px 1.5rem 60px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.heroOverlay {
|
||||
background: linear-gradient(
|
||||
to top,
|
||||
rgba(1, 77, 51, 0.95) 0%,
|
||||
rgba(1, 77, 51, 0.6) 60%,
|
||||
transparent 100%
|
||||
);
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.metaDivider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.heroMeta {
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
min-height: 350px;
|
||||
}
|
||||
}
|
||||
103
src/components/LocationSection.js
Normal file
@ -0,0 +1,103 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './LocationSection.module.css';
|
||||
|
||||
export default function LocationSection() {
|
||||
return (
|
||||
<section id="contact" className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
<p className={styles.sectionTag}>📍 Contact & Location</p>
|
||||
<h2 className={styles.sectionTitle}>Get in Touch</h2>
|
||||
<p className={styles.sectionDesc}>We'd love to hear from you. Book a table or ask us a question.</p>
|
||||
</div>
|
||||
|
||||
<div className={styles.premiumCard}>
|
||||
{/* Left - Image & Glass Info */}
|
||||
<div className={styles.imagePane}>
|
||||
<Image
|
||||
src="/images/hero-dosa.png"
|
||||
alt="Restaurant ambiance"
|
||||
fill
|
||||
className={styles.bgImage}
|
||||
/>
|
||||
<div className={styles.imageOverlay}></div>
|
||||
|
||||
<div className={styles.glassInfo}>
|
||||
<div className={styles.infoItem}>
|
||||
<div className={styles.infoIcon}>
|
||||
<svg width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" viewBox="0 0 24 24"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className={styles.infoLabel}>Our Location</h4>
|
||||
<p className={styles.infoText}>
|
||||
123 King St S, Waterloo,<br />
|
||||
ON N2J 1N9, Canada
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.infoItem}>
|
||||
<div className={styles.infoIcon}>
|
||||
<svg width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className={styles.infoLabel}>Opening Hours</h4>
|
||||
<p className={styles.infoText}>
|
||||
Mon – Thu: 4 PM – 10 PM<br />
|
||||
Fri – Sun: 11 AM – 10 PM
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.infoItem}>
|
||||
<div className={styles.infoIcon}>
|
||||
<svg width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" viewBox="0 0 24 24"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className={styles.infoLabel}>Contact Us</h4>
|
||||
<p className={styles.infoText}>
|
||||
+1 (519) 888-7459<br />
|
||||
mydosaplacewaterloo@gmail.com
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Contact Form */}
|
||||
<div className={styles.formPane}>
|
||||
<h3 className={styles.formTitle}>Send a Message</h3>
|
||||
<p className={styles.formSubtitle}>Fill out the form below and our team will get back to you shortly.</p>
|
||||
|
||||
<form className={styles.form}>
|
||||
<div className={styles.formRow}>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="name" className={styles.label}>First Name</label>
|
||||
<input type="text" id="name" className={styles.input} placeholder="John" />
|
||||
</div>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="lastName" className={styles.label}>Last Name</label>
|
||||
<input type="text" id="lastName" className={styles.input} placeholder="Doe" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="email" className={styles.label}>Email Address</label>
|
||||
<input type="email" id="email" className={styles.input} placeholder="john@example.com" />
|
||||
</div>
|
||||
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="message" className={styles.label}>Your Message</label>
|
||||
<textarea id="message" rows="4" className={styles.textarea} placeholder="How can we help you?"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" className={styles.btnSubmit}>
|
||||
Send Message
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
234
src/components/LocationSection.module.css
Normal file
@ -0,0 +1,234 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.sectionTag {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-secondary);
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.5rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sectionDesc {
|
||||
font-size: 1rem;
|
||||
color: var(--color-text-medium);
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.premiumCard {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
background: #fff;
|
||||
border-radius: 24px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20px 50px rgba(0,0,0,0.08);
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
/* Left - Image & Glass Info */
|
||||
.imagePane {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding: 3rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bgImage {
|
||||
object-fit: cover;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.imageOverlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to top, rgba(1, 77, 51, 0.9) 0%, rgba(1, 77, 51, 0.4) 100%);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.glassInfo {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.infoItem {
|
||||
display: flex;
|
||||
gap: 1.2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.infoItem:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.infoIcon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
background: var(--color-secondary);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2rem;
|
||||
flex-shrink: 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.infoLabel {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 0.3rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.infoText {
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.5;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
/* Right - Form */
|
||||
.formPane {
|
||||
padding: 4rem 3rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.formTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.formSubtitle {
|
||||
font-size: 0.95rem;
|
||||
color: var(--color-text-medium);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.formRow {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-text-dark);
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.input, .textarea {
|
||||
width: 100%;
|
||||
padding: 0.9rem 1rem;
|
||||
border: 1px solid #e0e0e0;
|
||||
background: #fdfdfd;
|
||||
border-radius: 8px;
|
||||
font-family: inherit;
|
||||
font-size: 0.95rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.input:focus, .textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-secondary);
|
||||
background: #fff;
|
||||
box-shadow: 0 0 0 4px rgba(1, 77, 51, 0.1);
|
||||
}
|
||||
|
||||
.textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.btnSubmit {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.btnSubmit:hover {
|
||||
background: var(--color-primary-light);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(1, 77, 51, 0.2);
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.premiumCard {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.imagePane {
|
||||
min-height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.formRow {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.imagePane {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
.formPane {
|
||||
padding: 2.5rem 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
53
src/components/MenuSection.js
Normal file
@ -0,0 +1,53 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './MenuSection.module.css';
|
||||
|
||||
const menuItems = [
|
||||
{ name: 'Classic Plain Dosa', desc: 'Thin crispy crepe made from fermented rice & lentil batter', price: '$8.99', image: '/images/hero-dosa.png' },
|
||||
{ name: 'South Indian Thali', desc: 'A royal feast featuring an array of curries, dal, rice & dessert', price: '$24.99', image: '/images/south-indian-thali.png' },
|
||||
{ name: 'Authentic Sambar', desc: 'Flavorful lentil stew with fresh vegetables & tamarind', price: '$8.99', image: '/images/sambar.png' },
|
||||
{ name: 'Crispy Masala Dosa', desc: 'Classic dosa filled with spiced potato curry', price: '$12.99', image: '/images/crispy-masala.png' },
|
||||
{ name: 'Medu Vada', desc: 'Crispy fried lentil donuts served with coconut chutney', price: '$9.99', image: '/images/new.png' },
|
||||
{ name: 'Mysore Masala Dosa', desc: 'Spicy red chutney spread with potato filling inside a crispy dosa', price: '$13.99', image: '/images/hero-dosa.png' },
|
||||
];
|
||||
|
||||
export default function MenuSection() {
|
||||
return (
|
||||
<section id="menu" className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<p className={styles.sectionTag}>🍽️ Our Menu</p>
|
||||
<h2 className={styles.sectionTitle}>The Tiffin Menu</h2>
|
||||
|
||||
{/* Menu Grid */}
|
||||
<div className={styles.menuGrid}>
|
||||
{menuItems.map((item, i) => (
|
||||
<div key={i} className={styles.menuItem}>
|
||||
<div className={styles.menuItemImageWrap}>
|
||||
<Image
|
||||
src={item.image}
|
||||
alt={item.name}
|
||||
width={80}
|
||||
height={80}
|
||||
className={styles.menuItemImage}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.menuItemContent}>
|
||||
<div className={styles.menuItemTop}>
|
||||
<h3 className={styles.itemName}>{item.name}</h3>
|
||||
<span className={styles.dots}></span>
|
||||
<span className={styles.itemPrice}>{item.price}</span>
|
||||
</div>
|
||||
<p className={styles.itemDesc}>{item.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className={styles.center}>
|
||||
<a href="#order" className={styles.btnViewFull}>
|
||||
📋 Explore Full Menu
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
138
src/components/MenuSection.module.css
Normal file
@ -0,0 +1,138 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: var(--color-bg-light);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.sectionTag {
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-secondary);
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
text-align: center;
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.2rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 3.5rem;
|
||||
}
|
||||
|
||||
/* Menu Grid */
|
||||
.menuGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 2rem 3rem;
|
||||
margin-bottom: 3.5rem;
|
||||
}
|
||||
|
||||
.menuItem {
|
||||
display: flex;
|
||||
gap: 1.2rem;
|
||||
padding: 1rem 0;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.menuItemImageWrap {
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
.menuItemImage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.menuItemContent {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.menuItemTop {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.itemName {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-text-dark);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dots {
|
||||
flex: 1;
|
||||
border-bottom: 2px dotted #ccc;
|
||||
min-width: 20px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.itemPrice {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.itemDesc {
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-medium);
|
||||
margin-top: 0.4rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* CTA */
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btnViewFull {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.8rem 2rem;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
border-radius: var(--border-radius-full);
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btnViewFull:hover {
|
||||
background: var(--color-primary-light);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(1, 77, 51, 0.3);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.menuGrid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
37
src/components/Navbar.js
Normal file
@ -0,0 +1,37 @@
|
||||
import Link from 'next/link';
|
||||
import styles from './Navbar.module.css';
|
||||
|
||||
export default function Navbar() {
|
||||
return (
|
||||
<nav className={styles.navbar}>
|
||||
<div className={styles.navInner}>
|
||||
{/* Logo */}
|
||||
<Link href="/" className={styles.logo}>
|
||||
<span className={styles.logoLeaf}>🌿</span>
|
||||
<span className={styles.logoText}>My Dosa Place</span>
|
||||
</Link>
|
||||
|
||||
{/* Navigation Links */}
|
||||
<ul className={styles.navLinks}>
|
||||
<li><Link href="/" className={styles.navLink}>Home</Link></li>
|
||||
<li><Link href="#about" className={styles.navLink}>About</Link></li>
|
||||
<li><Link href="#menu" className={styles.navLink}>Menu</Link></li>
|
||||
<li><Link href="#specials" className={styles.navLink}>Specials</Link></li>
|
||||
<li><Link href="#catering" className={styles.navLink}>Catering</Link></li>
|
||||
<li><Link href="#gallery" className={styles.navLink}>Gallery</Link></li>
|
||||
<li><Link href="#contact" className={styles.navLink}>Contact</Link></li>
|
||||
</ul>
|
||||
|
||||
{/* Right Actions */}
|
||||
<div className={styles.navActions}>
|
||||
<Link href="tel:+15191234567" className={styles.btnCall}>
|
||||
📞 Call Now
|
||||
</Link>
|
||||
<Link href="#order" className={styles.btnOrder}>
|
||||
Order Online
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
127
src/components/Navbar.module.css
Normal file
@ -0,0 +1,127 @@
|
||||
.navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.navInner {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
text-decoration: none;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.logoLeaf {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.logoText {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.35rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.navLinks {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.8rem;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navLink {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-medium);
|
||||
text-decoration: none;
|
||||
transition: color 0.25s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.navLink:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.navLink::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: var(--color-secondary);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.navLink:hover::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.navActions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.btnCall {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-primary);
|
||||
border: 1px solid var(--color-primary);
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
text-decoration: none;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.btnCall:hover {
|
||||
border-color: var(--color-primary);
|
||||
background: rgba(1, 77, 51, 0.06);
|
||||
}
|
||||
|
||||
.btnOrder {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-primary);
|
||||
background: var(--color-secondary);
|
||||
padding: 0.55rem 1.2rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
text-decoration: none;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.btnOrder:hover {
|
||||
background: var(--color-secondary-hover);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(217, 156, 67, 0.4);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.navLinks {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.btnCall {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
43
src/components/ProcessSection.js
Normal file
@ -0,0 +1,43 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './ProcessSection.module.css';
|
||||
|
||||
export default function ProcessSection() {
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.grid}>
|
||||
{/* Left - Dark Green Card with Overlapping Image */}
|
||||
<div className={styles.leftCard}>
|
||||
<div className={styles.cardContent}>
|
||||
<h2 className={styles.cardTitle}>My Dosa Place<br/>Restaurant</h2>
|
||||
<p className={styles.cardDescription}>
|
||||
Born from a passion for preserving the culinary heritage of South India, My Dosa Place brings authentic flavors from the kitchens of Tamil Nadu and Karnataka right to Waterloo.
|
||||
</p>
|
||||
<a href="#menu" className={styles.btnExplore}>
|
||||
Explore Menu
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.cardImageWrap}>
|
||||
<Image
|
||||
src="/images/south-indian-thali.png"
|
||||
alt="South Indian Spread"
|
||||
width={400}
|
||||
height={400}
|
||||
className={styles.cardImage}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Text Content */}
|
||||
<div className={styles.rightContent}>
|
||||
{/* <div className={styles.stepCircle}>1</div> */}
|
||||
<h3 className={styles.rightTitle}>Authentic Flavors Prepared Specially for You</h3>
|
||||
<p className={styles.rightDescription}>
|
||||
Every dosa is crafted with love using traditional recipes passed down through generations. We source the finest ingredients and grind our own batter fresh every day to ensure that perfect crispy, golden crepe. Experience the true taste of tradition in every bite.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
166
src/components/ProcessSection.module.css
Normal file
@ -0,0 +1,166 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1.1fr 0.9fr;
|
||||
gap: 6rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Left - Dark Green Card */
|
||||
.leftCard {
|
||||
background-color: var(--color-primary); /* #014d33 */
|
||||
border-radius: 20px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
min-height: 380px;
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
padding: 3.5rem 3rem;
|
||||
width: 55%;
|
||||
max-width: 400px;
|
||||
color: #fff;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.cardTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.4rem;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 1.5rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.cardDescription {
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.6;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.btnExplore {
|
||||
display: inline-block;
|
||||
background-color: var(--color-secondary);
|
||||
color: #fff;
|
||||
padding: 0.8rem 2rem;
|
||||
border-radius: 30px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btnExplore:hover {
|
||||
background-color: var(--color-secondary-hover);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 15px rgba(217, 156, 67, 0.4);
|
||||
}
|
||||
|
||||
.cardImageWrap {
|
||||
position: absolute;
|
||||
right: -70px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 280px;
|
||||
height: 85%;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 15px 30px rgba(0,0,0,0.3);
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.cardImage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Right - Text Content */
|
||||
.rightContent {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.stepCircle {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: var(--color-secondary);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.rightTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.4rem;
|
||||
color: var(--color-primary);
|
||||
line-height: 1.2;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.rightDescription {
|
||||
font-size: 1.05rem;
|
||||
color: var(--color-text-medium);
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 4rem;
|
||||
}
|
||||
|
||||
.leftCard {
|
||||
margin-right: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.leftCard {
|
||||
flex-direction: column;
|
||||
margin-right: 0;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
width: 100%;
|
||||
padding: 2.5rem 2rem 150px;
|
||||
}
|
||||
|
||||
.cardImageWrap {
|
||||
position: absolute;
|
||||
right: 50%;
|
||||
transform: translateX(50%);
|
||||
bottom: -60px;
|
||||
top: auto;
|
||||
width: 85%;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.rightContent {
|
||||
padding-right: 0;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
28
src/components/PromoSection.js
Normal file
@ -0,0 +1,28 @@
|
||||
import styles from './PromoSection.module.css';
|
||||
|
||||
export default function PromoSection() {
|
||||
return (
|
||||
<section id="specials" className={styles.section}>
|
||||
<div className={styles.overlay}></div>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.pill}>WEEKEND SPECIAL</div>
|
||||
<h2 className={styles.title}>Royal South Indian Thali</h2>
|
||||
<p className={styles.description}>
|
||||
A limited edition 21-item feast served exclusively on Saturdays and
|
||||
Sundays. Experience the true diversity of Southern flavours in one
|
||||
sitting.
|
||||
</p>
|
||||
<div className={styles.details}>
|
||||
<span className={styles.detailItem}>🕒 12:00 PM - 4:00 PM</span>
|
||||
<span className={styles.detailDivider}>•</span>
|
||||
<span className={styles.detailItem}>💵 $24.99 Per Person</span>
|
||||
</div>
|
||||
<a href="#contact" className={styles.btnReserve}>
|
||||
Reserve for This Weekend
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
133
src/components/PromoSection.module.css
Normal file
@ -0,0 +1,133 @@
|
||||
.section {
|
||||
position: relative;
|
||||
padding: 80px 0;
|
||||
background-image: url('/images/hero-dosa.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(1, 77, 51, 0.88);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.content {
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pill {
|
||||
background-color: #f7dfaf; /* Lighter gold for better contrast on green */
|
||||
color: #8c5b1b;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 800;
|
||||
padding: 0.4rem 1rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 1.5rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
margin-bottom: 1.2rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1.1rem;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 2rem;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.2rem;
|
||||
margin-bottom: 3rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.detailItem {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.detailDivider {
|
||||
color: #f7dfaf;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.btnReserve {
|
||||
display: inline-block;
|
||||
padding: 1rem 2.5rem;
|
||||
background: #fff;
|
||||
color: var(--color-primary);
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
border-radius: var(--border-radius-full);
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btnReserve:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.title {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.details {
|
||||
flex-direction: column;
|
||||
gap: 0.8rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.detailDivider {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
129
src/components/ReviewsSection.js
Normal file
@ -0,0 +1,129 @@
|
||||
'use client';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import Image from 'next/image';
|
||||
import styles from './ReviewsSection.module.css';
|
||||
|
||||
const reviews = [
|
||||
{
|
||||
text: "Best dosa I've ever had outside of India! The Masala Dosa was perfectly crispy and the sambar was incredibly flavorful. The weekend Thali is outstanding — so many flavors in one plate. We will definitely be back!",
|
||||
name: 'Sarah M. & Family',
|
||||
role: 'Local Food Critic',
|
||||
initials: 'SM',
|
||||
rating: '4.9',
|
||||
},
|
||||
{
|
||||
text: "My Dosa Place is an absolute gem in Waterloo. The chutneys are made fresh daily and the Rava Dosa has the most amazing crunch. It genuinely transports you to Tamil Nadu. Highly recommend the Uttappam too!",
|
||||
name: 'Raj Patel',
|
||||
role: 'Food Blogger',
|
||||
initials: 'RP',
|
||||
rating: '5.0',
|
||||
},
|
||||
{
|
||||
text: "We visited for lunch and were blown away by the authentic South Indian experience. The Sambar was rich and perfectly spiced, and the dosas were golden crisp. The staff was warm and welcoming — felt like home!",
|
||||
name: 'Priya & Anand K.',
|
||||
role: 'Regular Customer',
|
||||
initials: 'PK',
|
||||
rating: '4.8',
|
||||
},
|
||||
{
|
||||
text: "I've tried many Indian restaurants across Canada and My Dosa Place stands out for its genuine authenticity. The Benne Masala Dosa is a must-try. Amazing value for the quality and portion sizes. Can't wait to return!",
|
||||
name: 'Michael Torres',
|
||||
role: 'Food Enthusiast',
|
||||
initials: 'MT',
|
||||
rating: '4.9',
|
||||
},
|
||||
];
|
||||
|
||||
export default function ReviewsSection() {
|
||||
const [current, setCurrent] = useState(0);
|
||||
const [animating, setAnimating] = useState(false);
|
||||
|
||||
const goTo = useCallback((index) => {
|
||||
if (animating) return;
|
||||
setAnimating(true);
|
||||
setTimeout(() => {
|
||||
setCurrent(index);
|
||||
setAnimating(false);
|
||||
}, 300);
|
||||
}, [animating]);
|
||||
|
||||
const prev = () => goTo((current - 1 + reviews.length) % reviews.length);
|
||||
const next = useCallback(() => goTo((current + 1) % reviews.length), [current, goTo]);
|
||||
|
||||
// Auto-slide every 5 seconds
|
||||
useEffect(() => {
|
||||
const timer = setInterval(next, 5000);
|
||||
return () => clearInterval(timer);
|
||||
}, [next]);
|
||||
|
||||
const review = reviews[current];
|
||||
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.contentWrap}>
|
||||
|
||||
{/* Left – Stacked image collage */}
|
||||
<div className={styles.imageCol}>
|
||||
<div className={styles.collage}>
|
||||
<div className={styles.imgLeft}>
|
||||
<Image src="/images/story-heritage.png" alt="Dosa" fill className={styles.img} />
|
||||
</div>
|
||||
<div className={styles.imgRight}>
|
||||
<Image src="/images/sambar.png" alt="Sambar" fill className={styles.img} />
|
||||
</div>
|
||||
<div className={styles.ratingBadge}>
|
||||
<span className={styles.ratingText}>4.9</span>
|
||||
<div className={styles.stars}>⭐⭐⭐⭐⭐</div>
|
||||
<span className={styles.ratingLabel}>500+ Reviews</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right – Testimonial slider */}
|
||||
<div className={styles.textCol}>
|
||||
<p className={styles.sectionTag}>Testimonials</p>
|
||||
<h2 className={styles.sectionTitle}>What Our Customers Say</h2>
|
||||
|
||||
<div className={`${styles.reviewCard} ${animating ? styles.fadeOut : styles.fadeIn}`}>
|
||||
<div className={styles.quoteMark}>“</div>
|
||||
<p className={styles.reviewText}>{review.text}</p>
|
||||
|
||||
<div className={styles.reviewer}>
|
||||
<div className={styles.avatar}>{review.initials}</div>
|
||||
<div>
|
||||
<p className={styles.reviewerName}>{review.name}</p>
|
||||
<p className={styles.reviewDate}>{review.role}</p>
|
||||
</div>
|
||||
<div className={styles.reviewRating}>{review.rating} ⭐</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dots + Arrows */}
|
||||
<div className={styles.controls}>
|
||||
<div className={styles.dots}>
|
||||
{reviews.map((_, i) => (
|
||||
<button
|
||||
key={i}
|
||||
className={`${styles.dot} ${i === current ? styles.dotActive : ''}`}
|
||||
onClick={() => goTo(i)}
|
||||
aria-label={`Go to review ${i + 1}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className={styles.navButtons}>
|
||||
<button className={styles.navBtn} onClick={prev} aria-label="Previous">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>
|
||||
</button>
|
||||
<button className={styles.navBtn} onClick={next} aria-label="Next">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
287
src/components/ReviewsSection.module.css
Normal file
@ -0,0 +1,287 @@
|
||||
.section {
|
||||
padding: 80px 0;
|
||||
background: var(--color-bg-light);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.contentWrap {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.2fr;
|
||||
gap: 5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* ─── Left: Image Collage ─── */
|
||||
.imageCol {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.collage {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 420px;
|
||||
}
|
||||
|
||||
.imgLeft,
|
||||
.imgRight {
|
||||
position: absolute;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
border: 4px solid #fff;
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.imgLeft {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 55%;
|
||||
height: 90%;
|
||||
}
|
||||
|
||||
.imgRight {
|
||||
top: 8%;
|
||||
right: 0;
|
||||
width: 42%;
|
||||
height: 75%;
|
||||
}
|
||||
|
||||
.img {
|
||||
object-fit: cover;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.imgLeft:hover .img,
|
||||
.imgRight:hover .img {
|
||||
transform: scale(1.06);
|
||||
}
|
||||
|
||||
/* Rating badge overlaid on collage */
|
||||
.ratingBadge {
|
||||
position: absolute;
|
||||
bottom: 5%;
|
||||
right: -12px;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
padding: 1rem 1.2rem;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(1, 77, 51, 0.3);
|
||||
text-align: center;
|
||||
z-index: 5;
|
||||
min-width: 110px;
|
||||
}
|
||||
|
||||
.ratingText {
|
||||
display: block;
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.2rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.stars {
|
||||
font-size: 0.7rem;
|
||||
margin: 0.4rem 0;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.ratingLabel {
|
||||
font-size: 0.72rem;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ─── Right: Text + Slider ─── */
|
||||
.textCol {
|
||||
padding-right: 1rem;
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.sectionTag {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-secondary);
|
||||
letter-spacing: 1.5px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.2rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Review card with fade animation */
|
||||
.reviewCard {
|
||||
background: #fff;
|
||||
border-radius: 20px;
|
||||
padding: 2rem;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.06);
|
||||
margin-bottom: 1.8rem;
|
||||
border-left: 4px solid var(--color-primary);
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
.fadeIn {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.fadeOut {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
.quoteMark {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 4rem;
|
||||
color: var(--color-secondary);
|
||||
line-height: 0.5;
|
||||
margin-bottom: 1rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.reviewText {
|
||||
font-size: 1rem;
|
||||
line-height: 1.8;
|
||||
color: var(--color-text-medium);
|
||||
margin-bottom: 1.5rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.reviewer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
min-width: 46px;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.reviewerName {
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.reviewDate {
|
||||
font-size: 0.82rem;
|
||||
color: var(--color-text-medium);
|
||||
}
|
||||
|
||||
.reviewRating {
|
||||
margin-left: auto;
|
||||
font-weight: 700;
|
||||
font-size: 0.95rem;
|
||||
color: var(--color-primary);
|
||||
background: rgba(1, 77, 51, 0.07);
|
||||
padding: 0.3rem 0.8rem;
|
||||
border-radius: 20px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ─── Controls: Dots + Arrows ─── */
|
||||
.controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dots {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: #d0d0d0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dotActive {
|
||||
background: var(--color-primary);
|
||||
width: 28px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.navButtons {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.navBtn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-primary);
|
||||
background: transparent;
|
||||
color: var(--color-primary);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.navBtn:hover {
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(1, 77, 51, 0.25);
|
||||
}
|
||||
|
||||
/* ─── Responsive ─── */
|
||||
@media (max-width: 992px) {
|
||||
.contentWrap {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 4rem;
|
||||
}
|
||||
|
||||
.collage {
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
height: 380px;
|
||||
}
|
||||
|
||||
.textCol {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.section {
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.collage {
|
||||
height: 320px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
}
|
||||
43
src/components/ScrollToTop.js
Normal file
@ -0,0 +1,43 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import styles from './ScrollToTop.module.css';
|
||||
|
||||
export default function ScrollToTop() {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
// Show button when page is scrolled down
|
||||
const toggleVisibility = () => {
|
||||
if (window.scrollY > 300) {
|
||||
setIsVisible(true);
|
||||
} else {
|
||||
setIsVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
const scrollToTop = () => {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', toggleVisibility);
|
||||
return () => window.removeEventListener('scroll', toggleVisibility);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isVisible && (
|
||||
<button
|
||||
onClick={scrollToTop}
|
||||
className={styles.scrollToTopBtn}
|
||||
aria-label="Scroll to top"
|
||||
>
|
||||
↑
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
48
src/components/ScrollToTop.module.css
Normal file
@ -0,0 +1,48 @@
|
||||
.scrollToTopBtn {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
right: 30px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: var(--color-secondary);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1000;
|
||||
transition: all 0.3s ease;
|
||||
animation: fadeIn 0.3s;
|
||||
}
|
||||
|
||||
.scrollToTopBtn:hover {
|
||||
background-color: var(--color-primary);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.scrollToTopBtn {
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
113
src/components/StorySection.js
Normal file
@ -0,0 +1,113 @@
|
||||
import Image from 'next/image';
|
||||
import styles from './StorySection.module.css';
|
||||
|
||||
export default function StorySection() {
|
||||
return (
|
||||
<section id="about" className={styles.section}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.grid}>
|
||||
{/* Left - Images */}
|
||||
<div className={styles.collageWrap}>
|
||||
<div className={styles.collageBg}>
|
||||
{/* Photo 1 - Top left, tilted left */}
|
||||
<div className={`${styles.polaroid} ${styles.polaroid1}`}>
|
||||
<div className={styles.polaroidInner}>
|
||||
<Image
|
||||
src="/images/hero-dosa.png"
|
||||
alt="Golden crispy dosa"
|
||||
width={280}
|
||||
height={220}
|
||||
className={styles.polaroidImg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Photo 2 - Top center, slight right tilt */}
|
||||
<div className={`${styles.polaroid} ${styles.polaroid2}`}>
|
||||
<div className={styles.polaroidInner}>
|
||||
<Image
|
||||
src="/images/story-heritage.png"
|
||||
alt="Chef preparing dosa"
|
||||
width={260}
|
||||
height={200}
|
||||
className={styles.polaroidImg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Photo 3 - Bottom right */}
|
||||
<div className={`${styles.polaroid} ${styles.polaroid3}`}>
|
||||
<div className={styles.polaroidInner}>
|
||||
<Image
|
||||
src="/images/sambar.png"
|
||||
alt="Authentic sambar"
|
||||
width={240}
|
||||
height={190}
|
||||
className={styles.polaroidImg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Photo 4 - Bottom center, wide */}
|
||||
<div className={`${styles.polaroid} ${styles.polaroid4}`}>
|
||||
<div className={styles.polaroidInner}>
|
||||
<Image
|
||||
src="/images/crispy-masala.png"
|
||||
alt="Crispy masala dosa"
|
||||
width={300}
|
||||
height={200}
|
||||
className={styles.polaroidImg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Heritage badge */}
|
||||
<div className={styles.badge}>
|
||||
<span className={styles.badgeNumber}>45+</span>
|
||||
<span className={styles.badgeText}>Years of South Indian<br/>Culinary Heritage</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Content */}
|
||||
<div className={styles.content}>
|
||||
<p className={styles.sectionTag}>— Our Story</p>
|
||||
<h2 className={styles.title}>Welcome to My Dosa Place</h2>
|
||||
<p className={styles.description}>
|
||||
Born from a passion for preserving the culinary heritage of
|
||||
South India, My Dosa Place brings authentic flavors from the
|
||||
kitchens of Tamil Nadu and Karnataka right to Waterloo.
|
||||
</p>
|
||||
<p className={styles.description}>
|
||||
Every dosa is crafted with love using traditional recipes passed
|
||||
down through generations. We source the finest ingredients and
|
||||
grind our own batter fresh every day to ensure that perfect
|
||||
crispy, golden crepe.
|
||||
</p>
|
||||
|
||||
<div className={styles.stats}>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>45+</span>
|
||||
<span className={styles.statLabel}>Recipes</span>
|
||||
</div>
|
||||
<div className={styles.statDivider}></div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>15K+</span>
|
||||
<span className={styles.statLabel}>Happy Customers</span>
|
||||
</div>
|
||||
<div className={styles.statDivider}></div>
|
||||
<div className={styles.statItem}>
|
||||
<span className={styles.statNumber}>4.9</span>
|
||||
<span className={styles.statLabel}>Google Rating</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#menu" className={styles.btnExplore}>
|
||||
Explore Our Heritage →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
297
src/components/StorySection.module.css
Normal file
@ -0,0 +1,297 @@
|
||||
.section {
|
||||
padding: 5rem 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Polaroid Collage */
|
||||
.collageWrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.collageBg {
|
||||
position: relative;
|
||||
background: #1a1a1a;
|
||||
border-radius: 20px;
|
||||
min-height: 480px;
|
||||
padding: 2rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* Base polaroid style */
|
||||
.polaroid {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
padding: 10px 10px 30px;
|
||||
box-shadow:
|
||||
0 4px 15px rgba(0, 0, 0, 0.25),
|
||||
0 1px 3px rgba(0, 0, 0, 0.15);
|
||||
transition: transform 0.4s ease, box-shadow 0.4s ease, z-index 0s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.polaroid:hover {
|
||||
z-index: 10 !important;
|
||||
box-shadow:
|
||||
0 12px 35px rgba(0, 0, 0, 0.4),
|
||||
0 2px 6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.polaroidInner {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.polaroidImg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.polaroid:hover .polaroidImg {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* Photo 1 — Top left, tilted left */
|
||||
.polaroid1 {
|
||||
top: 10px;
|
||||
left: -10px;
|
||||
transform: rotate(-6deg);
|
||||
z-index: 2;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.polaroid1:hover {
|
||||
transform: rotate(-2deg) scale(1.05);
|
||||
}
|
||||
|
||||
.polaroid1 .polaroidInner {
|
||||
height: 170px;
|
||||
}
|
||||
|
||||
/* Photo 2 — Top right, tilted right */
|
||||
.polaroid2 {
|
||||
top: -15px;
|
||||
right: 10px;
|
||||
transform: rotate(4deg);
|
||||
z-index: 3;
|
||||
width: 210px;
|
||||
}
|
||||
|
||||
.polaroid2:hover {
|
||||
transform: rotate(1deg) scale(1.05);
|
||||
}
|
||||
|
||||
.polaroid2 .polaroidInner {
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
/* Photo 3 — Bottom right, tilted */
|
||||
.polaroid3 {
|
||||
bottom: 30px;
|
||||
right: -5px;
|
||||
transform: rotate(-3deg);
|
||||
z-index: 4;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.polaroid3:hover {
|
||||
transform: rotate(0deg) scale(1.05);
|
||||
}
|
||||
|
||||
.polaroid3 .polaroidInner {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
/* Photo 4 — Bottom center/left, overlapping */
|
||||
.polaroid4 {
|
||||
bottom: 10px;
|
||||
left: 40px;
|
||||
transform: rotate(5deg);
|
||||
z-index: 5;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.polaroid4:hover {
|
||||
transform: rotate(2deg) scale(1.05);
|
||||
}
|
||||
|
||||
.polaroid4 .polaroidInner {
|
||||
height: 165px;
|
||||
}
|
||||
|
||||
/* Heritage badge */
|
||||
.badge {
|
||||
position: absolute;
|
||||
bottom: -12px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
padding: 0.9rem 1.4rem;
|
||||
border-radius: var(--border-radius-md);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
||||
z-index: 20;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.badgeNumber {
|
||||
display: block;
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-secondary);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.badgeText {
|
||||
font-size: 0.72rem;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.content {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.sectionTag {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-secondary);
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 2.2rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 0.95rem;
|
||||
color: var(--color-text-medium);
|
||||
line-height: 1.75;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
padding: 1.5rem;
|
||||
background: var(--color-bg-light);
|
||||
border-radius: var(--border-radius-md);
|
||||
}
|
||||
|
||||
.statItem {
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.statNumber {
|
||||
display: block;
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
line-height: 1;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.statLabel {
|
||||
font-size: 0.8rem;
|
||||
color: var(--color-text-medium);
|
||||
}
|
||||
|
||||
.statDivider {
|
||||
width: 1px;
|
||||
height: 40px;
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.btnExplore {
|
||||
display: inline-block;
|
||||
padding: 0.8rem 2rem;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
border-radius: var(--border-radius-full);
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btnExplore:hover {
|
||||
background: var(--color-primary-light);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(1, 77, 51, 0.3);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.collageBg {
|
||||
min-height: 380px;
|
||||
}
|
||||
|
||||
.polaroid1 {
|
||||
width: 170px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.polaroid1 .polaroidInner {
|
||||
height: 130px;
|
||||
}
|
||||
|
||||
.polaroid2 {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.polaroid2 .polaroidInner {
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.polaroid3 {
|
||||
width: 155px;
|
||||
}
|
||||
|
||||
.polaroid3 .polaroidInner {
|
||||
height: 115px;
|
||||
}
|
||||
|
||||
.polaroid4 {
|
||||
width: 185px;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.polaroid4 .polaroidInner {
|
||||
height: 130px;
|
||||
}
|
||||
}
|
||||