diff --git a/about.html b/about.html new file mode 100644 index 0000000..ba1cf50 --- /dev/null +++ b/about.html @@ -0,0 +1,253 @@ + + + + + + + About Venus Photo Studio And Lab | Karaikal Photography Studio + + + + + + + + + + + + + + + + + + + + +` + + + +
+
+
+
+ About Venus Photo Studio And Lab +

Cinematic craft with a calm, human touch.

+

From Karaikal weddings to intimate family portraits, the studio is built around direction that feels natural, lighting that feels premium, and storytelling that ages beautifully.

+
+
+ +
+ +
+
+ Studio Introduction +

A visual studio for people who want the day to feel as good as it looks.

+

Venus Photo Studio And Lab focuses on weddings, couple shoots, maternity, baby portraits, event coverage, album design, and reels. Every project is treated as a story with rhythm: quiet prep, emotional ceremony, composed portraits, celebration, and legacy.

+

The result is a gallery that feels rich without feeling loud, polished without losing warmth, and cinematic without turning real moments into performance.

+
+
+
+ Professional camera on a studio table +
+
+ Camera lens with premium lighting +
+
+
+ +
+
+
+ Photographer working with professional camera gear +
+
+ Photographer Details +

Experienced direction for real people, real families, and real celebrations.

+

The creative team brings together event awareness, portrait posing, lighting discipline, and film sequencing. The focus is simple: make people comfortable, read the emotion in the room, and keep the final work refined.

+
+
+ +

Photography

+

Candid, traditional, portrait, and family-led visual coverage.

+
+
+ +

Videography

+

Cinematic trailers, reels, and long-form celebration films.

+
+
+
+
+
+ +
+
+ Mission & Vision +

Preserve personal history with a luxury visual language.

+
+
+
+ +

Mission

+

Create emotionally honest images and films with premium composition, reliable coverage, and respectful client direction.

+
+
+ +

Vision

+

Become a trusted Karaikal studio known for cinematic wedding stories, polished portraits, and heirloom albums.

+
+
+ +

Creative Approach

+

Blend documentary timing with refined art direction so each gallery feels natural, graceful, and visually cohesive.

+
+
+
+ +
+
+
+
+ Experience +

Designed around calm execution.

+

From the first enquiry to delivery, the process is clear, considerate, and built for busy families.

+
+
+
+ 01 +
+

Creative Consultation

+

Discuss the event flow, family priorities, style references, deliverables, and must-have moments.

+
+
+
+ 02 +
+

Shoot Direction

+

Guide portraits and key frames while staying attentive to candid moments and family comfort.

+
+
+
+ 03 +
+

Edit & Delivery

+

Color grading, retouching, album sequencing, and final delivery prepared for sharing and archiving.

+
+
+
+
+
+
+ +
+
+
+ Ready When You Are +

Tell us the date. We will help shape the story.

+

Share your event type, venue, guest flow, and dream visual tone. The studio can recommend coverage that fits the moment.

+ + + Book Consultation + +
+
+ Premium wedding reception table decor +
+
+
+
+ + + + + + + + + diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 0000000..52ac8ba --- /dev/null +++ b/assets/css/style.css @@ -0,0 +1,628 @@ +:root { + --black: #0b0b0b; + --black-soft: #111013; + --gold: #d4af37; + --gold-soft: #f1d783; + --white: #ffffff; + --muted: #b8b1aa; + --line: rgba(212, 175, 55, 0.22); +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + background: var(--black); + color: var(--white); + font-family: "Montserrat", "Poppins", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + overflow-x: hidden; +} + +body.menu-open { + overflow: hidden; +} + +::selection { + background: rgba(212, 175, 55, 0.45); + color: var(--white); +} + +img { + max-width: 100%; + display: block; +} + +a, +button, +input, +textarea { + -webkit-tap-highlight-color: transparent; +} + +.font-display { + font-family: "Playfair Display", Georgia, serif; +} + +.site-shell { + position: relative; + isolation: isolate; + min-height: 100vh; + background: + linear-gradient(118deg, transparent 0%, transparent 36%, rgba(73, 44, 112, 0.14) 46%, rgba(212, 175, 55, 0.08) 52%, transparent 65%, transparent 100%), + radial-gradient(ellipse at 18% -8%, rgba(212, 175, 55, 0.12), transparent 30rem), + radial-gradient(ellipse at 86% 18%, rgba(78, 45, 120, 0.16), transparent 28rem), + linear-gradient(135deg, #0b0b0b 0%, #151017 54%, #0b0b0b 100%); +} + +.site-shell::before, +.site-shell::after { + content: ""; + position: fixed; + inset: 0; + pointer-events: none; +} + +.site-shell::before { + z-index: 0; + opacity: 0.72; + background-image: + url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='520' height='520' viewBox='0 0 520 520'%3E%3Cg fill='%23FFFFFF' opacity='.5'%3E%3Ccircle cx='44' cy='68' r='1.1'/%3E%3Ccircle cx='128' cy='42' r='.8'/%3E%3Ccircle cx='220' cy='96' r='1.2'/%3E%3Ccircle cx='344' cy='60' r='.9'/%3E%3Ccircle cx='472' cy='120' r='1.1'/%3E%3Ccircle cx='82' cy='220' r='.9'/%3E%3Ccircle cx='168' cy='300' r='1.3'/%3E%3Ccircle cx='286' cy='254' r='.8'/%3E%3Ccircle cx='424' cy='342' r='1.2'/%3E%3Ccircle cx='364' cy='456' r='.9'/%3E%3Ccircle cx='34' cy='438' r='1.1'/%3E%3C/g%3E%3Cg fill='%23D4AF37' opacity='.42'%3E%3Ccircle cx='392' cy='174' r='1.2'/%3E%3Ccircle cx='236' cy='392' r='1'/%3E%3Ccircle cx='486' cy='430' r='1'/%3E%3C/g%3E%3Cpath d='M44 68 128 42 220 96M286 254 392 174 472 120M168 300 236 392 364 456 486 430' fill='none' stroke='%23D4AF37' stroke-opacity='.13' stroke-width='1'/%3E%3C/svg%3E"), + radial-gradient(1px 1px at 12% 28%, rgba(255, 255, 255, 0.42), transparent 60%), + radial-gradient(1px 1px at 76% 46%, rgba(212, 175, 55, 0.36), transparent 60%), + radial-gradient(1px 1px at 42% 82%, rgba(255, 255, 255, 0.32), transparent 60%); + background-position: center top, 0 0, 0 0, 0 0; + background-size: 520px 520px, 240px 240px, 310px 310px, 380px 380px; +} + +.site-shell::after { + z-index: 0; + opacity: 0.42; + background: + linear-gradient(126deg, transparent 8%, rgba(46, 30, 76, 0.05) 30%, rgba(92, 58, 132, 0.18) 44%, rgba(212, 175, 55, 0.09) 52%, rgba(255, 255, 255, 0.035) 58%, transparent 76%), + repeating-linear-gradient(118deg, transparent 0 42px, rgba(212, 175, 55, 0.035) 43px, transparent 45px); + -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 13%, #000 88%, transparent 100%); + mask-image: linear-gradient(180deg, transparent 0%, #000 13%, #000 88%, transparent 100%); +} + +.site-shell > header, +.site-shell > main, +.site-shell > footer { + position: relative; + z-index: 1; +} + +.site-header { + position: fixed; + inset: 0 0 auto; + z-index: 50; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + background: linear-gradient(180deg, rgba(11, 11, 11, 0.92), rgba(11, 11, 11, 0.42)); + -webkit-backdrop-filter: blur(14px); + backdrop-filter: blur(14px); + transition: background 220ms ease, border-color 220ms ease, transform 220ms ease; +} + +.site-header.is-scrolled { + background: rgba(11, 11, 11, 0.92); + border-color: rgba(212, 175, 55, 0.18); +} + +.brand-mark { + width: 2.6rem; + height: 2.6rem; + display: grid; + place-items: center; + border: 1px solid rgba(212, 175, 55, 0.72); + color: var(--gold); + background: rgba(212, 175, 55, 0.08); + letter-spacing: 0; +} + +.nav-link { + position: relative; + color: rgba(255, 255, 255, 0.74); + transition: color 180ms ease; +} + +.nav-link::after { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: -0.45rem; + height: 1px; + transform: scaleX(0); + transform-origin: center; + background: var(--gold); + transition: transform 220ms ease; +} + +.nav-link:hover, +.nav-link.is-active { + color: var(--white); +} + +.nav-link:hover::after, +.nav-link.is-active::after { + transform: scaleX(1); +} + +.mobile-panel { + max-height: 0; + overflow: hidden; + opacity: 0; + transition: max-height 260ms ease, opacity 220ms ease; +} + +.mobile-panel.is-open { + max-height: 26rem; + opacity: 1; +} + +.hero-home { + background-image: + linear-gradient(90deg, rgba(11, 11, 11, 0.9), rgba(11, 11, 11, 0.48) 48%, rgba(11, 11, 11, 0.22)), + linear-gradient(180deg, rgba(11, 11, 11, 0.28), rgba(11, 11, 11, 0.95)), + url("https://images.unsplash.com/photo-1519741497674-611481863552?auto=format&fit=crop&w=2200&q=82"); +} + +.hero-about { + background-image: + linear-gradient(90deg, rgba(11, 11, 11, 0.86), rgba(11, 11, 11, 0.34)), + linear-gradient(180deg, rgba(11, 11, 11, 0.22), rgba(11, 11, 11, 0.96)), + url("https://images.unsplash.com/photo-1492691527719-9d1e07e534b4?auto=format&fit=crop&w=2200&q=82"); +} + +.hero-gallery { + background-image: + linear-gradient(90deg, rgba(11, 11, 11, 0.86), rgba(11, 11, 11, 0.36)), + linear-gradient(180deg, rgba(11, 11, 11, 0.2), rgba(11, 11, 11, 0.94)), + url("https://images.unsplash.com/photo-1519225421980-715cb0215aed?auto=format&fit=crop&w=2200&q=82"); +} + +.hero-services { + background-image: + linear-gradient(90deg, rgba(11, 11, 11, 0.88), rgba(11, 11, 11, 0.38)), + linear-gradient(180deg, rgba(11, 11, 11, 0.22), rgba(11, 11, 11, 0.96)), + url("https://images.unsplash.com/photo-1520854221256-17451cc331bf?auto=format&fit=crop&w=2200&q=82"); +} + +.hero-contact { + background-image: + linear-gradient(90deg, rgba(11, 11, 11, 0.88), rgba(11, 11, 11, 0.42)), + linear-gradient(180deg, rgba(11, 11, 11, 0.2), rgba(11, 11, 11, 0.96)), + url("https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?auto=format&fit=crop&w=2200&q=82"); +} + +.cinematic-hero { + min-height: 94svh; + background-position: center; + background-size: cover; + background-attachment: scroll; +} + +@media (max-width: 768px) { + .cinematic-hero { + min-height: 88svh; + background-attachment: scroll; + } +} + +.section-kicker { + display: inline-flex; + align-items: center; + gap: 0.65rem; + color: var(--gold-soft); + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.18em; + text-transform: uppercase; +} + +.section-kicker::before { + content: ""; + width: 2rem; + height: 1px; + background: var(--gold); +} + +.gold-text { + color: var(--gold); +} + +.text-gradient { + background: linear-gradient(100deg, #ffffff 0%, #f7e7ab 54%, #d4af37 100%); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +.reveal-text { + opacity: 0; + transform: translateY(22px); + animation: revealUp 620ms ease forwards; +} + +@keyframes revealUp { + to { + opacity: 1; + transform: translateY(0); + } +} + +.lux-button { + display: inline-flex; + min-height: 3rem; + align-items: center; + justify-content: center; + gap: 0.6rem; + border: 1px solid rgba(212, 175, 55, 0.78); + background: linear-gradient(135deg, rgba(212, 175, 55, 0.94), rgba(241, 215, 131, 0.9)); + color: #12100b; + font-size: 0.78rem; + font-weight: 800; + letter-spacing: 0.08em; + text-transform: uppercase; + padding: 0.9rem 1.3rem; + border-radius: 999px; + transition: transform 180ms ease, box-shadow 180ms ease, background 180ms ease; + box-shadow: 0 18px 48px rgba(212, 175, 55, 0.18); +} + +.lux-button:hover { + transform: translateY(-2px); + box-shadow: 0 24px 60px rgba(212, 175, 55, 0.28); +} + +.ghost-button { + display: inline-flex; + min-height: 3rem; + align-items: center; + justify-content: center; + gap: 0.6rem; + border: 1px solid rgba(255, 255, 255, 0.24); + color: var(--white); + font-size: 0.78rem; + font-weight: 800; + letter-spacing: 0.08em; + text-transform: uppercase; + padding: 0.9rem 1.3rem; + border-radius: 999px; + transition: border-color 180ms ease, background 180ms ease, transform 180ms ease; +} + +.ghost-button:hover { + transform: translateY(-2px); + border-color: rgba(212, 175, 55, 0.74); + background: rgba(212, 175, 55, 0.08); +} + +.glass-panel { + border: 1px solid rgba(255, 255, 255, 0.1); + background: rgba(255, 255, 255, 0.055); + -webkit-backdrop-filter: blur(14px); + backdrop-filter: blur(14px); + box-shadow: 0 30px 90px rgba(0, 0, 0, 0.32); +} + +main > section:not(:first-child) { + content-visibility: auto; + contain-intrinsic-size: 1px 820px; +} + +.lux-card { + border: 1px solid rgba(255, 255, 255, 0.1); + background: linear-gradient(180deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.035)); + transition: transform 180ms ease, border-color 180ms ease, background 180ms ease; +} + +.lux-card:hover { + transform: translateY(-3px); + border-color: rgba(212, 175, 55, 0.42); + background: linear-gradient(180deg, rgba(212, 175, 55, 0.12), rgba(255, 255, 255, 0.035)); +} + +.image-frame { + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.11); + background: + linear-gradient(135deg, rgba(212, 175, 55, 0.08), rgba(36, 20, 36, 0.42)), + #16120f; +} + +.image-frame img { + width: 100%; + height: 100%; + object-fit: cover; + transform: scale(1.005); + transition: transform 360ms ease; +} + +.image-frame:hover img, +.gallery-card:hover img, +.service-card:hover img { + transform: scale(1.045); +} + +.masonry-grid { + columns: 1; + column-gap: 1rem; +} + +@media (min-width: 640px) { + .masonry-grid { + columns: 2; + } +} + +@media (min-width: 1024px) { + .masonry-grid { + columns: 3; + } +} + +.gallery-card { + position: relative; + display: inline-block; + width: 100%; + margin: 0 0 1rem; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.1); + background: + linear-gradient(135deg, rgba(212, 175, 55, 0.08), rgba(36, 20, 36, 0.42)), + #13100e; + cursor: zoom-in; +} + +.gallery-card img { + width: 100%; + object-fit: cover; + transition: transform 360ms ease; +} + +.gallery-card::after { + content: ""; + position: absolute; + inset: auto 0 0; + height: 55%; + background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.8)); + opacity: 0.9; +} + +.gallery-caption { + position: absolute; + z-index: 1; + left: 1rem; + right: 1rem; + bottom: 1rem; +} + +.filter-btn { + min-height: 2.6rem; + border: 1px solid rgba(255, 255, 255, 0.14); + color: rgba(255, 255, 255, 0.72); + background: rgba(255, 255, 255, 0.035); + border-radius: 999px; + padding: 0.65rem 1rem; + font-size: 0.75rem; + font-weight: 800; + letter-spacing: 0.06em; + text-transform: uppercase; + transition: color 180ms ease, border-color 180ms ease, background 180ms ease; +} + +.filter-btn:hover, +.filter-btn.is-active { + color: var(--black); + border-color: var(--gold); + background: var(--gold); +} + +.service-card { + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.1); + background: linear-gradient(180deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.035)); + transition: transform 180ms ease, border-color 180ms ease; +} + +.service-card:hover { + transform: translateY(-3px); + border-color: rgba(212, 175, 55, 0.44); +} + +.service-card img { + width: 100%; + height: 15rem; + object-fit: cover; + transition: transform 360ms ease; +} + +.input-field { + min-height: 3.25rem; + width: 100%; + border: 1px solid rgba(255, 255, 255, 0.13); + border-radius: 0; + background: rgba(255, 255, 255, 0.055); + color: var(--white); + padding: 0.9rem 1rem; + outline: none; + transition: border-color 180ms ease, background 180ms ease; +} + +.input-field:focus { + border-color: rgba(212, 175, 55, 0.72); + background: rgba(255, 255, 255, 0.08); +} + +.input-field::placeholder { + color: rgba(255, 255, 255, 0.42); +} + +.map-frame { + min-height: 24rem; + width: 100%; + border: 0; + filter: grayscale(1) invert(0.92) contrast(0.92); +} + +.lightbox { + position: fixed; + inset: 0; + z-index: 80; + display: none; + align-items: center; + justify-content: center; + padding: 1rem; + background: rgba(0, 0, 0, 0.9); +} + +.lightbox.is-open { + display: flex; +} + +.lightbox img { + max-height: 82vh; + width: auto; + max-width: min(92vw, 74rem); + object-fit: contain; + border: 1px solid rgba(212, 175, 55, 0.32); + box-shadow: 0 28px 90px rgba(0, 0, 0, 0.65); +} + +.lightbox-close { + position: fixed; + top: 1rem; + right: 1rem; + width: 3rem; + height: 3rem; + display: grid; + place-items: center; + border: 1px solid rgba(255, 255, 255, 0.24); + color: var(--white); + background: rgba(255, 255, 255, 0.08); +} + +.marquee-track { + display: flex; + width: max-content; + animation: marquee 30s linear infinite; +} + +@keyframes marquee { + from { + transform: translateX(0); + } + + to { + transform: translateX(-50%); + } +} + +.hero-scroll { + position: absolute; + left: 50%; + bottom: 2rem; + display: none; + width: 1px; + height: 5rem; + overflow: hidden; + background: rgba(255, 255, 255, 0.15); +} + +.hero-scroll::after { + content: ""; + position: absolute; + inset: 0; + height: 45%; + background: var(--gold); + animation: scrollLine 1.8s ease-in-out infinite; +} + +@media (min-width: 768px) { + .hero-scroll { + display: block; + } +} + +@keyframes scrollLine { + 0% { + transform: translateY(-120%); + } + + 100% { + transform: translateY(230%); + } +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + } + + .cinematic-hero { + background-attachment: scroll; + } + + .reveal-text { + opacity: 1; + transform: none; + } + + [data-aos] { + opacity: 1 !important; + transform: none !important; + transition: none !important; + } + + .site-shell::before { + opacity: 0.58; + background-size: 420px 420px, 260px 260px, 320px 320px, 380px 380px; + } + + .site-shell::after { + opacity: 0.25; + } +} + +@media (max-width: 768px) { + html { + scroll-behavior: auto; + } + + .image-frame:hover img, + .gallery-card:hover img, + .service-card:hover img, + .lux-card:hover, + .service-card:hover, + .lux-button:hover, + .ghost-button:hover { + transform: none; + } + + .marquee-track { + animation-duration: 48s; + } + + .site-header, + .glass-panel { + -webkit-backdrop-filter: none; + backdrop-filter: none; + } + + [data-aos] { + opacity: 1 !important; + transform: none !important; + transition: none !important; + } +} diff --git a/assets/fonts/.gitkeep b/assets/fonts/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/assets/fonts/.gitkeep @@ -0,0 +1 @@ + diff --git a/assets/images/gallery/.gitkeep b/assets/images/gallery/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/assets/images/gallery/.gitkeep @@ -0,0 +1 @@ + diff --git a/assets/images/gallery/studio-fallback.svg b/assets/images/gallery/studio-fallback.svg new file mode 100644 index 0000000..f5e146b --- /dev/null +++ b/assets/images/gallery/studio-fallback.svg @@ -0,0 +1,30 @@ + + Venus Photo Studio And Lab fallback image + Luxury black and gold photography placeholder for unloaded gallery images. + + + + + + + + + + + + + + + + + + + + + + + + + VENUS PHOTO STUDIO AND LAB + Photography | Videography | Photo Lab + diff --git a/assets/images/hero/.gitkeep b/assets/images/hero/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/assets/images/hero/.gitkeep @@ -0,0 +1 @@ + diff --git a/assets/images/logo/venus-monogram.jpg b/assets/images/logo/venus-monogram.jpg new file mode 100644 index 0000000..8dd0a18 Binary files /dev/null and b/assets/images/logo/venus-monogram.jpg differ diff --git a/assets/images/services/.gitkeep b/assets/images/services/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/assets/images/services/.gitkeep @@ -0,0 +1 @@ + diff --git a/assets/js/app.js b/assets/js/app.js new file mode 100644 index 0000000..31edfa5 --- /dev/null +++ b/assets/js/app.js @@ -0,0 +1,215 @@ +const qs = (selector, scope = document) => scope.querySelector(selector); +const qsa = (selector, scope = document) => [...scope.querySelectorAll(selector)]; + +const initHeader = () => { + const header = qs(".site-header"); + const toggle = qs("[data-menu-toggle]"); + const panel = qs("[data-mobile-panel]"); + const page = document.body.dataset.page; + let scrollTicking = false; + + if (page) { + qsa(`[data-nav="${page}"]`).forEach((link) => link.classList.add("is-active")); + } + + const updateHeader = () => { + if (!header) return; + header.classList.toggle("is-scrolled", window.scrollY > 24); + scrollTicking = false; + }; + + const onScroll = () => { + if (scrollTicking) return; + scrollTicking = true; + window.requestAnimationFrame(updateHeader); + }; + + updateHeader(); + window.addEventListener("scroll", onScroll, { passive: true }); + + if (toggle && panel) { + toggle.addEventListener("click", () => { + const isOpen = panel.classList.toggle("is-open"); + document.body.classList.toggle("menu-open", isOpen); + toggle.setAttribute("aria-expanded", String(isOpen)); + const icon = qs("[data-menu-icon]", toggle); + if (icon) icon.setAttribute("data-lucide", isOpen ? "x" : "menu"); + if (window.lucide) window.lucide.createIcons(); + }); + + qsa("a", panel).forEach((link) => { + link.addEventListener("click", () => { + panel.classList.remove("is-open"); + document.body.classList.remove("menu-open"); + toggle.setAttribute("aria-expanded", "false"); + const icon = qs("[data-menu-icon]", toggle); + if (icon) icon.setAttribute("data-lucide", "menu"); + if (window.lucide) window.lucide.createIcons(); + }); + }); + } +}; + +const initSmoothAnchors = () => { + const smoothMotion = window.matchMedia("(prefers-reduced-motion: no-preference)").matches && window.matchMedia("(min-width: 768px)").matches; + + qsa('a[href^="#"]').forEach((anchor) => { + anchor.addEventListener("click", (event) => { + const target = qs(anchor.getAttribute("href")); + if (!target) return; + event.preventDefault(); + target.scrollIntoView({ behavior: smoothMotion ? "smooth" : "auto", block: "start" }); + }); + }); +}; + +const initAnimations = () => { + const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + + if (window.AOS) { + AOS.init({ + once: true, + duration: 560, + easing: "ease-out-cubic", + offset: 70, + disable: () => window.innerWidth < 640 || reducedMotion + }); + } +}; + +const initHeroReveal = () => { + qsa(".reveal-text").forEach((item, index) => { + item.style.animationDelay = `${Math.min(index * 70, 420)}ms`; + }); +}; + +const initGallery = () => { + const buttons = qsa("[data-filter]"); + const cards = qsa("[data-category]"); + if (!buttons.length || !cards.length) return; + + buttons.forEach((button) => { + button.addEventListener("click", () => { + const filter = button.dataset.filter; + buttons.forEach((item) => item.classList.remove("is-active")); + button.classList.add("is-active"); + + cards.forEach((card) => { + const show = filter === "all" || card.dataset.category === filter; + card.style.display = show ? "inline-block" : "none"; + }); + + if (window.AOS) AOS.refreshHard(); + }); + }); +}; + +const initImageHints = () => { + const fallback = "assets/images/gallery/studio-fallback.svg"; + + const applyFallback = (img) => { + if (img.dataset.fallbackApplied === "true") return; + img.dataset.fallbackApplied = "true"; + img.src = fallback; + img.alt = img.alt || "Venus Photo Studio And Lab image preview"; + + const lightboxTrigger = img.closest("[data-lightbox]"); + if (lightboxTrigger) { + lightboxTrigger.dataset.lightbox = fallback; + } + }; + + qsa("img").forEach((img) => { + img.decoding = "async"; + + if (!img.hasAttribute("loading") && !img.closest(".site-header")) { + img.loading = "lazy"; + } + + img.addEventListener("error", () => applyFallback(img), { once: true }); + + if (img.complete && img.naturalWidth === 0) { + applyFallback(img); + } + }); +}; + +const initLightbox = () => { + const triggers = qsa("[data-lightbox]"); + if (!triggers.length) return; + + const lightbox = document.createElement("div"); + lightbox.className = "lightbox"; + lightbox.setAttribute("role", "dialog"); + lightbox.setAttribute("aria-modal", "true"); + lightbox.innerHTML = ` + + + `; + document.body.appendChild(lightbox); + + const image = qs("img", lightbox); + const close = qs(".lightbox-close", lightbox); + + const closeLightbox = () => { + lightbox.classList.remove("is-open"); + document.body.classList.remove("menu-open"); + image.removeAttribute("src"); + image.alt = ""; + }; + + triggers.forEach((trigger) => { + trigger.addEventListener("click", () => { + const source = trigger.dataset.lightbox || qs("img", trigger)?.src; + const caption = trigger.dataset.caption || qs(".gallery-caption", trigger)?.textContent?.trim() || "Venus Photo Studio And Lab gallery preview"; + if (!source) return; + image.src = source; + image.alt = caption; + lightbox.classList.add("is-open"); + document.body.classList.add("menu-open"); + if (window.lucide) window.lucide.createIcons(); + }); + }); + + close.addEventListener("click", closeLightbox); + lightbox.addEventListener("click", (event) => { + if (event.target === lightbox) closeLightbox(); + }); + window.addEventListener("keydown", (event) => { + if (event.key === "Escape") closeLightbox(); + }); +}; + +const initContactForm = () => { + const form = qs("[data-contact-form]"); + const note = qs("[data-form-note]"); + if (!form || !note) return; + + form.addEventListener("submit", (event) => { + event.preventDefault(); + note.textContent = "Thank you. Your enquiry is ready to send through the connected contact channel."; + note.classList.remove("hidden"); + form.reset(); + }); +}; + +const initFooterYear = () => { + qsa("[data-year]").forEach((item) => { + item.textContent = String(new Date().getFullYear()); + }); +}; + +document.addEventListener("DOMContentLoaded", () => { + initHeader(); + initSmoothAnchors(); + initHeroReveal(); + initAnimations(); + initGallery(); + initLightbox(); + initContactForm(); + initImageHints(); + initFooterYear(); + if (window.lucide) window.lucide.createIcons(); +}); diff --git a/components/footer.html b/components/footer.html new file mode 100644 index 0000000..98bb7fd --- /dev/null +++ b/components/footer.html @@ -0,0 +1,32 @@ + diff --git a/components/navbar.html b/components/navbar.html new file mode 100644 index 0000000..041ce14 --- /dev/null +++ b/components/navbar.html @@ -0,0 +1,34 @@ + diff --git a/contact.html b/contact.html new file mode 100644 index 0000000..24241fd --- /dev/null +++ b/contact.html @@ -0,0 +1,288 @@ + + + + + + + Contact Venus Photo Studio And Lab | Karaikal + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ Contact Venus Photo Studio And Lab +

Start your visual story with one simple enquiry.

+

Send your date, event type, and preferred coverage. The studio will help you choose a photo, film, or complete visual package.

+
+
+ +
+ +
+
+ Contact Form +

Tell us what you are planning.

+
+
+ + +
+
+ + +
+ + + +
+
+ + +
+ +
+
+
+ Visit Studio +

Door no. 24, Kannadiyar Street studio access.

+

Use the embedded map to plan your route, then call or WhatsApp before visiting for a consultation slot.

+ +
+
+ +
+
+
+ +
+
+
+ Fast Links +

Prefer a direct message?

+

WhatsApp is the fastest way to share dates, references, and event details. Instagram is ideal for checking the current visual style.

+ +
+
+ Camera lens closeup for contact section +
+
+
+
+ + + + + + + + diff --git a/gallery.html b/gallery.html new file mode 100644 index 0000000..d0ad623 --- /dev/null +++ b/gallery.html @@ -0,0 +1,216 @@ + + + + + + + Gallery | Venus Photo Studio And Lab Karaikal + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ Portfolio Categories +

Choose a mood, then open any frame.

+
+
+ + + + + + + +
+
+ +
+ + + + + + + + + + + + +
+
+ +
+
+ Like This Mood? +
+

Let us build a gallery around your story, family, and location.

+ + + Enquire Now + +
+
+
+
+ + + + + + + + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7d55500 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module venusstudio + +go 1.25 diff --git a/index.html b/index.html new file mode 100644 index 0000000..dc7aa0f --- /dev/null +++ b/index.html @@ -0,0 +1,407 @@ + + + + + + + Venus Photo Studio And Lab | Photography Studio in Karaikal + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ Karaikal Luxury Visual Stories +

Venus Photo Studio And Lab

+

Cinematic wedding photography, soulful portraits, and graceful family films crafted with rich color, patient direction, and a timeless editorial eye.

+ +
+
+
+

01

+

Direction

+
+
+

4K

+

Films

+
+
+

24h

+

Highlights

+
+
+
+ +
+ + + +
+
+
+ Photographer holding a professional camera +
+
+ About Studio +

A premium studio for moments that deserve more than documentation.

+

Venus Photo Studio And Lab blends candid observation with refined direction, creating wedding albums, family portraits, event stories, and cinematic reels with a polished brand sensibility.

+
+
+ +

Photography

+
+
+ +

Cinematography

+
+
+ +

Albums

+
+
+ + + Our Story + +
+
+
+ +
+
+ Services +

Complete visual coverage for family milestones and grand celebrations.

+
+
+
+ +

Wedding Photography

+

Candid, traditional, and editorial coverage with polished retouching and album-ready sequencing.

+
+
+ +

Cinematic Videography

+

Trailer edits, long-form films, reels, drone-style framing, and music-led storytelling.

+
+
+ +

Couple Sessions

+

Pre-wedding, engagement, and anniversary shoots shaped around your location and mood.

+
+
+
+ +
+
+ Wedding Films/Baby Shoots/Maternity/Events/Albums/Reels + Wedding Films/Baby Shoots/Maternity/Events/Albums/Reels +
+
+ +
+
+
+ Portfolio Preview +

A glimpse into wedding days, portraits, and celebration energy.

+
+ + + Full Gallery + +
+
+ + + + +
+
+ +
+
+
+ Testimonials +

Clients come for coverage. They remember the calm.

+
+
+
+ +

The team guided every pose gently and still captured so many natural moments. Our album feels elegant and very personal.

+

Wedding Client

+
+
+ +

The highlight video looked cinematic without feeling artificial. It brought the whole event back in minutes.

+

Event Client

+
+
+ +

Our baby shoot was relaxed, patient, and beautifully lit. The final pictures are now framed at home.

+

Family Client

+
+
+
+
+ +
+
+
+ Google Reviews +

4.9

+

956 Google reviews

+
+
+

Trusted by families across Karaikal.

+

Clients highlight friendly service, quality photos, wedding albums, timely delivery, and strong photography output from Venus Photo Studio And Lab.

+ +
+
+
+ +
+
+
+ Instagram Gallery +

Fresh visual stories from the studio feed.

+
+ + + @venus_karaikal + +
+
+ Instagram wedding preview + Instagram couple preview + Instagram portrait preview + Instagram event preview + Instagram portrait preview + Instagram ceremony preview +
+
+ +
+
+
+ Contact CTA +

Planning a wedding, portrait session, or family milestone?

+

Share your date, location, and dream mood. Venus Photo Studio And Lab will help shape the coverage into a calm, elegant visual plan.

+ +
+
+ Bridal portrait used as contact call to action +
+
+
+
+ + + + + + + + diff --git a/main.go b/main.go new file mode 100644 index 0000000..ff2bb91 --- /dev/null +++ b/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "os" + "path/filepath" + "time" +) + +type pageRoute struct { + Path string + File string +} + +func main() { + + port := os.Getenv("PORT") + + if port == "" { + port = "8080" + } + + root, err := filepath.Abs(".") + if err != nil { + log.Fatalf("resolve website directory: %v", err) + } + + mux := http.NewServeMux() + registerPages(mux, root) + registerAssets(mux, root) + + server := &http.Server{ + Addr: ":" + port, + Handler: mux, + ReadHeaderTimeout: 5 * time.Second, + } + + fmt.Printf("Venus Photo Studio And Lab running on port %s\n", port) + + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatalf("start server: %v", err) + } +} + +func registerPages(mux *http.ServeMux, root string) { + pages := []pageRoute{ + {Path: "/", File: "index.html"}, + {Path: "/about", File: "about.html"}, + {Path: "/gallery", File: "gallery.html"}, + {Path: "/services", File: "services.html"}, + {Path: "/contact", File: "contact.html"}, + } + + for _, page := range pages { + route := page + + mux.HandleFunc(route.Path, func(w http.ResponseWriter, r *http.Request) { + + if r.URL.Path != route.Path { + http.NotFound(w, r) + return + } + + servePage(w, r, filepath.Join(root, route.File)) + }) + } + + redirects := map[string]string{ + "/index.html": "/", + "/about.html": "/about", + "/gallery.html": "/gallery", + "/services.html": "/services", + "/contact.html": "/contact", + } + + for from, to := range redirects { + + target := to + + mux.HandleFunc(from, func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, target, http.StatusMovedPermanently) + }) + } +} + +func registerAssets(mux *http.ServeMux, root string) { + + fileServer := http.FileServer(http.Dir(root)) + + mux.Handle("/assets/", fileServer) + + mux.HandleFunc("/tailwind.config.js", func(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, filepath.Join(root, "tailwind.config.js")) + }) +} + +func servePage(w http.ResponseWriter, r *http.Request, file string) { + + if r.Method != http.MethodGet && r.Method != http.MethodHead { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + w.Header().Set("Cache-Control", "no-cache") + + http.ServeFile(w, r, file) +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..4747ed9 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "venus-photo-studio-and-lab", + "version": "1.0.0", + "description": "Go-served premium website for Venus Photo Studio And Lab photography and videography.", + "private": true, + "scripts": { + "dev": "go run main.go", + "start": "go run main.go" + }, + "keywords": [ + "photography", + "golang", + "static-site", + "tailwind", + "aos" + ], + "author": "Venus Photo Studio And Lab", + "license": "UNLICENSED" +} diff --git a/services.html b/services.html new file mode 100644 index 0000000..952bb2b --- /dev/null +++ b/services.html @@ -0,0 +1,280 @@ + + + + + + + Services | Venus Photo Studio And Lab Karaikal + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ Services +

Premium coverage for the moments that become legacy.

+

Choose focused coverage or build a custom collection across photography, cinematography, albums, reels, and event storytelling.

+
+
+ +
+ +
+
+ Service Cards +

Every offering is shaped for clarity, elegance, and delivery quality.

+
+
+
+
+ Wedding photography service + +
+
+

Wedding Photography

+

Full-day candid, traditional, portrait, ritual, family, and decor coverage with refined color grading.

+ + + WhatsApp + +
+
+
+
+ Cinematic videography service + +
+
+

Cinematic Videography

+

Trailer films, highlight reels, long-form edits, interviews, and mood-led storytelling for every event rhythm.

+ + + WhatsApp + +
+
+
+
+ Couple shoot service + +
+
+

Couple Shoots

+

Pre-wedding, engagement, anniversary, and editorial couple portraits directed with a relaxed mood.

+ + + WhatsApp + +
+
+
+
+ Kids photography service + +
+
+

Kids Photography

+

Baby portraits, birthdays, family lifestyle sessions, and patient studio direction for little personalities.

+ + + WhatsApp + +
+
+
+
+ Album design service + +
+
+

Album Design

+

Heirloom album layouts, photo selection, sequencing, cover design, and print-ready storytelling.

+ + + WhatsApp + +
+
+
+
+ Event coverage service + +
+
+

Event Coverage

+

Birthdays, engagements, corporate events, stage programs, rituals, and social celebrations.

+ + + WhatsApp + +
+
+
+
+ +
+
+
+ Booking Flow +

A clear process keeps the creative work effortless.

+
+
+
+ 01 +

Enquire

+

Share date, event type, venue, and expected coverage.

+
+
+ 02 +

Plan

+

Choose services, timeline, deliverables, and visual mood.

+
+
+ 03 +

Capture

+

Work with a prepared team and thoughtful on-day direction.

+
+
+ 04 +

Deliver

+

Receive edited photos, films, reels, and album-ready files.

+
+
+
+
+ +
+
+
+ Custom Packages +

Need a combined photo, film, album, and reel plan?

+

Venus Photo Studio And Lab can design a custom collection for multi-day weddings, family events, and venue-heavy celebrations where coverage needs to feel complete.

+ + + Build My Package + +
+
+
+ Wedding couple service preview +
+
+ Event decor service preview +
+
+
+
+
+ + + + + + + + diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..4418d2f --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,26 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./*.html", + "./components/**/*.html", + "./assets/js/**/*.js" + ], + theme: { + extend: { + colors: { + night: "#0B0B0B", + gold: "#D4AF37", + ivory: "#F7F2E8", + aubergine: "#241424" + }, + maxWidth: { + content: "1180px" + }, + fontFamily: { + display: ["Playfair Display", "Georgia", "serif"], + sans: ["Montserrat", "Poppins", "system-ui", "sans-serif"] + } + } + }, + plugins: [] +};