You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1779 lines
47 KiB

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base th:href="${baseURL}" />
<title>Victoria Public Hall</title>
<link rel="icon" th:href="@{files/assets/images/favicon.png}" type="image/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Georgia', serif;
overflow-x: hidden;
}
.navbar {
position: absolute;
top: 0;
width: 100%;
padding: 20px 40px;
display: flex;
align-items: center;
justify-content: space-between;
z-index: 999;
}
.nav-left {
display: flex;
align-items: center;
gap: 20px;
}
.logo {
height: 120px;
padding-left: 50%;
}
.nav-menu {
display: flex;
align-items: center;
gap: 25px;
}
.nav-menu a {
color: white;
font-size: 18px;
text-decoration: none;
}
.hamburger {
display: none;
flex-direction: column;
gap: 5px;
cursor: pointer;
}
.hamburger span {
width: 28px;
height: 3px;
background: white;
transition: 0.3s;
}
.mobile-book {
display: none;
}
@media (min-width: 768px) {
#registerbutton {
display: none;
}
#vichallbutton {
display: none;
}
#loginbutton {
display: none;
}
}
@media (max-width: 768px) {
.logo {
height: 45px;
}
.desktop-book {
display: none;
}
#registerbutton {
display: block;
margin-top: 25px;
margin-left: 30%;
font-size: 16px;
padding: 9px 18px;
border: 1px solid #fff;
background: inherit;
color: #fff;
cursor: pointer;
transition: 0.3s;
font-style: italic;
}
#vichallbutton {
display: block;
margin-top: 25px;
margin-left: 28%;
font-size: 16px;
padding: 9px 18px;
border: 1px solid #fff;
background: inherit;
color: #fff;
cursor: pointer;
transition: 0.3s;
font-style: italic;
}
#loginbutton {
display: block;
margin-top: 25px;
margin-left: 30%;
font-size: 16px;
padding: 9px 18px;
border: 1px solid #fff;
background: inherit;
color: #fff;
cursor: pointer;
transition: 0.3s;
font-style: italic;
}
#registerbutton:active {
background: #fff;
color: #222;
}
#vichallbutton:active {
background: #fff;
color: #222;
}
#loginbutton:active {
background: #fff;
color: #222;
}
.hamburger {
display: flex;
}
.nav-menu {
position: absolute;
top: 75px;
left: 0;
width: 100%;
background: transparent;
backdrop-filter: blur(10px);
padding: 20px 0;
flex-direction: column;
gap: 15px;
display: none;
}
.nav-menu a {
font-size: 20px;
color: white;
}
.nav-menu.active {
display: flex;
}
.mobile-book {
display: block;
margin-top: 10px;
font-size: 18px;
}
}
/* HERO SECTION */
.hero {
height: 125vh;
/* big enough to show top + bottom */
width: 100%;
background: url('/victoriapublichall/images/vph-background_v1.jpg') no-repeat;
background-size: cover;
background-position: center 55%;
/* fine tuning */
/* PERFECT for this image */
display: flex;
align-items: center;
padding-left: 80px;
color: #f6e7b0;
}
.hero h1 {
font-size: 70px;
font-weight: 400;
line-height: 1.1;
font-family: 'Inter', sans-serif;
}
.hero p {
font-size: 36px;
font-weight: 400;
margin-top: 15px;
font-family: "Playfair Display", sans-serif;
;
color: #FFF5ED;
}
.about-section {
background: #1a1a1a;
padding: 60px 60px;
color: #fdf2c2;
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 40px;
}
.about-section h2 {
font-size: 58px;
margin-bottom: 10px;
}
.about-section p {
max-width: 600px;
font-size: 18px;
line-height: 1.6;
color: #ccc;
text-align: left;
margin: 0;
/* remove unwanted left auto margin */
}
@media (max-width: 768px) {
/* HERO SECTION */
.hero {
height: auto;
padding: 80px 20px 60px 20px;
text-align: center;
justify-content: center;
background-position: center center;
}
.hero-logo {
width: 90%;
max-width: 300px;
height: auto;
margin: 0px auto 15px auto;
display: block;
padding-top: 3px;
}
.hero p {
font-size: 24px;
font-weight: 400;
font-family: "Playfair Display", sans-serif;
;
}
/* ABOUT SECTION */
.about-section {
flex-direction: column;
text-align: center;
padding: 40px 20px;
gap: 20px;
}
.about-section h2 {
font-size: 32px;
margin-bottom: 10px;
padding-left: 20%;
}
.about-section p {
max-width: 85%;
font-size: 16px;
line-height: 1.5;
text-align: justify;
margin: auto;
}
}
/* Button */
.visit-btn {
margin-top: 25px;
font-size: 24px;
font-weight: 700;
font-family: "Playfair Display", sans-serif;
;
padding: 12px 32px;
border: 1px solid #F0E4AF;
background: inherit;
color: #F0E4AF;
cursor: pointer;
transition: 0.3s;
font-style: italic;
}
.visit-btn:hover {
background: #fff;
color: #222;
}
@media (max-width: 768px) {
.visit-btn {
margin-top: 12px;
/* less spacing */
font-size: 16px;
/* smaller text */
padding: 8px 18px;
/* smaller button */
font-weight: 600;
/* slightly lighter */
}
.mobile-actions .visit-btn {
width: 85%;
/* full-width feel */
text-align: center;
}
}
/* CONTENT SECTIONS */
section {
padding: 80px 100px;
}
.section-title {
font-size: 64px;
margin-bottom: 20px;
font-family: "Playfair Display", sans-serif;
;
font-weight: 400;
}
.section-text {
font-size: 20px;
line-height: 1.6;
max-width: 1000px;
}
.info-cards-section {
width: 100%;
padding: 60px 0;
}
.row {
display: flex;
justify-content: center;
gap: 25px;
margin-bottom: 30px;
}
/* First row has 3 equal cards */
.row-1 .card {
width: 340px;
}
/* Second row has 2 cards aligned center */
.row-2 .card {
width: 340px;
}
.card {
padding: 35px 30px;
color: white;
border-radius: 6px;
min-height: 200px;
}
.card .icon {
font-size: 32px;
margin-bottom: 15px;
}
.card h3 {
font-size: 32px;
margin-bottom: 10px;
font-family: "Playfair Display", sans-serif;
font-weight: 400;
}
.card p {
font-size: 16px;
opacity: 0.85;
line-height: 1.4;
font-family: "Inter", sans-serif;
font-weight: 400;
}
/* Colors */
.red {
background: #67181B;
}
.olive {
background: #5A6135;
}
.teal {
background: #2E4B49;
}
.dark-blue {
background: #023F5A;
}
.purple {
background: #4D2F3E;
}
/* Responsive */
@media (max-width: 900px) {
.row {
flex-wrap: wrap;
}
.card {
width: 100%;
}
}
/* 2. THE MAIN SPLIT CONTAINER */
.split-container {
display: flex;
position: relative;
width: 100%;
margin: 0 0;
}
.split-container::-webkit-scrollbar {
display: none;
}
/* 3. LEFT COLUMN (SCROLLING TEXT) */
.right-content {
width: 40%;
/*padding-left: 5%;*/
color: #F0E4AF;
}
.right-content h5 {
font-size: 18px;
margin-bottom: 10px;
letter-spacing: 2px;
padding-left: 5%;
}
.right-content h2 {
font-family: "Playfair Display ", sans-serif;
padding-top: 0px;
margin-bottom: 15px;
font-size: 36px;
padding-left: 8%;
padding-right: 10%;
font-weight: 400;
}
.right-content p {
font-family: 'Inter', sans-serif;
font-size: 16px;
margin-bottom: 15px;
line-height: 1.5;
padding-left: 8%;
/* keep same */
padding-right: 15%;
font-weight: 400;
/* padding: 0 9%; */
}
/* The individual text blocks */
.text-block {
height: 100vh;
/* Each block takes up a full screen height */
display: flex;
flex-direction: column;
justify-content: center;
opacity: 0.2;
/* Dimmed by default */
transition: opacity 0.5s ease;
}
/* Highlight the active text */
.text-block.active {
opacity: 1;
}
/* 4. RIGHT COLUMN (STICKY IMAGE) */
.left-sticky {
width: 60%;
height: 100vh;
/* Fill screen */
position: sticky;
/* THE MAGIC */
top: 0;
display: flex;
/*align-items: center;*/
/*justify-content: center;*/
overflow: hidden;
/* Masks the zoom effect */
}
/* Image Wrapper */
.image-stack {
position: relative;
width: 100%;
height: 100%;
/* Not full height, so it looks like a nice window */
/*border-radius: 12px;*/
overflow: hidden;
}
/* The Images */
.sticky-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: fill;
opacity: 0;
transform: scale(1.2);
/* Start slightly zoomed in */
transition: opacity 0.8s ease, transform 1.2s ease-out;
}
/* Active Image State */
.sticky-img.active {
opacity: 1;
transform: scale(1);
/* Zooms out to normal size (Parallax feel) */
z-index: 2;
}
@media (max-width: 1024px) {
.split-container {
flex-direction: column;
}
/* Hide sticky image on mobile & tablet */
.left-sticky {
display: none;
}
.right-content {
width: 100%;
padding: 0;
}
.mobile-img img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Text block normal flow */
.text-block {
height: auto;
opacity: 1;
padding: 30px 20px;
margin-bottom: 40px;
}
/* Disable fade animation on mobile */
.text-block.active {
opacity: 1;
}
}
/* scroll top icon */
/* Button box */
.scroll-top {
position: fixed;
bottom: 25px;
right: 25px;
width: 50px;
height: 50px;
background: #0A3A52;
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
cursor: pointer;
opacity: 0;
visibility: hidden;
z-index: 9999;
transition: 0.4s ease;
box-shadow: 0 0 0 rgba(0, 0, 0, 0.4);
animation: none;
}
/* Show animation */
.scroll-top.show {
opacity: 1;
visibility: visible;
animation: bounceIn 0.8s ease forwards;
}
/* Hover animation */
.scroll-top:hover {
transform: translateY(-5px) scale(1.1);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}
/* Simple glowing pulse animation */
@keyframes bounceIn {
0% {
transform: scale(0.5) translateY(30px);
opacity: 0;
}
60% {
transform: scale(1.1) translateY(-10px);
opacity: 1;
}
100% {
transform: scale(1) translateY(0);
}
}
/* Optional smooth glowing effect */
.scroll-top.show {
animation: bounceIn 0.6s ease forwards, pulseGlow 2s infinite ease-in-out;
}
@keyframes pulseGlow {
0% {
box-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
}
50% {
box-shadow: 0 0 25px rgba(255, 255, 255, 0.6);
}
100% {
box-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
}
}
.img-comp-container {
position: relative;
width: 100%;
max-width: 1200px;
/* increase to desired width */
height: 650px;
/* increase to desired height */
margin: auto;
}
.img-comp-img {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
.img-comp-img img {
width: 100%;
height: 100%;
object-fit: cover;
/* keeps image proportional */
display: block;
vertical-align: middle;
}
.img-comp-slider {
position: absolute;
z-index: 9;
cursor: ew-resize;
width: 40px;
height: 40px;
background-color: #2196F3;
opacity: 0.7;
border-radius: 50%;
}
.baimages {
text-align: center;
padding: 60px 0;
background: #f9f7f2;
}
.visit-subtitle {
font-size: 18px;
color: #6f6f6f;
margin-bottom: 40px;
text-align: center;
}
.visit-title {
font-size: 42px;
color: #4a2a22;
margin-bottom: 8px;
text-align: center;
}
.amenities-list {
margin-top: 10px;
padding-left: 20px;
list-style-type: disc;
font-family: "Inter", sans-serif;
font-size: 16px;
line-height: 140%;
color: #fff;
/* adjust based on your card background */
}
.amenities-list li {
margin-bottom: 6px;
}
.book-btn {
margin-top: 20px;
display: inline-block;
padding: 10px 25px;
border: 2px solid #d3c5bf;
color: #efefe4;
text-decoration: none;
font-family: "Playfair Display", serif;
font-size: 18px;
border-radius: 6px;
}
@media (max-width: 768px) {
.baimages {
padding: 20px 10px;
}
.visit-title {
font-size: 24px;
}
.visit-subtitle {
font-size: 14px;
}
/* responsive height */
.img-comp-container {
height: 300px;
/* reduce for mobile */
}
.img-comp-img img {
object-fit: cover;
}
}
@media (max-width: 480px) {
.img-comp-container {
height: 220px;
/* very small screen */
}
.visit-title {
font-size: 20px;
}
.visit-subtitle {
font-size: 12px;
}
}
.button-wrapper {
display: flex;
justify-content: center;
margin-top: 40px;
}
.visit-outline-btn {
font-family: "Playfair Display", serif;
font-size: 18px;
font-style: italic;
padding: 10px 28px;
background: transparent;
border: 2px solid #5a3e36;
/* soft brown border */
color: #5a3e36;
/* brown text */
border-radius: 8px;
cursor: pointer;
transition: 0.3s ease;
}
.visit-outline-btn:hover {
background: #5a3e36;
color: #fff;
}
/* visit gallery section */
/* Section */
.visit-gallery-section {
text-align: center;
padding: 40px 0;
}
/* Layout wrapper */
.gallery-wrapper {
width: 85%;
margin: auto;
}
/* --- GALLERY GRID LAYOUT --- */
.gallery-container {
display: grid;
grid-template-columns: 1.5fr 1fr 1.2fr;
gap: 15px;
margin-top: 30px;
}
.gallery-left img,
.gallery-right img {
width: 100%;
height: 420px;
object-fit: cover;
border-radius: 10px;
}
.gallery-middle {
display: grid;
grid-template-rows: 1fr 1fr;
gap: 15px;
}
.gallery-middle img {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 10px;
}
/* --- ARROWS --- */
.arrows {
display: flex;
justify-content: center;
gap: 25px;
margin-top: 30px;
}
/* Left arrow (grey) */
.arrow-left {
background: #e6e6e6;
color: #333;
border: none;
width: 45px;
height: 45px;
border-radius: 50%;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
/* Right arrow (yellow) */
.arrow-right {
background: #f5b800;
color: black;
border: none;
width: 48px;
height: 47px;
border-radius: 50%;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
/* Hover */
.arrow-left:hover,
.arrow-right:hover {
transform: scale(1.1);
transition: 0.2s;
}
/* -------- IMAGE POPUP MODAL -------- */
.img-modal {
display: none;
position: fixed;
z-index: 9999;
padding-top: 80px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background: rgba(0, 0, 0, 0.8);
}
/* Modal Image */
.modal-content {
margin: auto;
display: block;
max-width: 90%;
max-height: 85vh;
border-radius: 10px;
}
/* Close button */
.close-modal {
position: absolute;
top: 35px;
right: 45px;
color: white;
font-size: 45px;
font-weight: bold;
cursor: pointer;
}
/* Wrapper for positioning loader over gallery */
.gallery-container-wrapper {
position: relative;
width: 85%;
margin: auto;
}
/* Center loader inside the gallery box */
.gallery-loader {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.7);
display: none;
/* hidden initially */
justify-content: center;
align-items: center;
z-index: 10;
}
/* Spinner */
.spinner {
width: 60px;
height: 60px;
border: 6px solid #ddd;
border-top-color: #15445c;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.mobile-book {
display: inline-block;
}
/* Mobile view */
@media (max-width: 768px) {
.mobile-book {
display: block;
margin-top: 12px;
font-size: 16px;
padding: 10px 20px;
border: 1px solid #fff;
background: transparent;
color: #fff;
font-style: italic;
}
}
.marquee-container {
width: 100%;
color: grey;
overflow: hidden;
white-space: nowrap;
font-family: "Inter", sans-serif;
font-size: 16px;
font-weight: 500;
position: relative;
z-index: 9999;
/*padding-bottom: 35px;*/
}
.marquee-text {
display: inline-block;
padding-left: 100%;
animation: marquee 18s linear infinite;
}
.marquee-text:hover {
animation-play-state: paused;
}
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); }
}
/* ===== MOBILE VIEW ===== */
@media (max-width: 768px) {
.marquee-container {
padding: 6px 0 12px 0;
font-size: 15px;
}
.marquee-text {
animation-duration: 25s; /* ✅ ONLY mobile */
padding-left: 80%; /* prevents early cut-off */
}
}
</style>
</head>
<body>
<!-- NAVBAR -->
<nav class="navbar">
<div class="nav-left">
<img th:src="@{images/VPH-logo_main-EN 1.png}" alt="VPH logo" class="logo">
</div>
<div class="nav-menu" id="navMenu">
<a href="#about">About VPH</a>
<!-- <a href="#visit" id="plantovisit">Planning to Visit</a> -->
<a href="/victoriapublichall/visit" id="plantovisit">Planning to Visit?</a>
<!--<a href="#contact">Contact Us</a>-->
</div>
<div class="nav-actions">
<button class="visit-btn desktop-book" id="registerbtn"> Book a Visit </button>
<button type="button" class="visit-btn desktop-book"
onclick="window.location.href='https://gccservices.in/victoriahallbooking'"> Book the Hall
</button>
<button class="visit-btn desktop-book" id="loginbtn"> Book a Event </button>
</div>
<div class="hamburger" id="hamburger">
<span></span>
<span></span>
<span></span>
</div>
</nav>
<!-- HERO SECTION -->
<div class="hero">
<div>
<img th:src="@{images/text.svg}" alt="VPH Logo" class="hero-logo" style="color: #F0E4AF">
<p>The Town Hall of Chennai</p>
<button id="registerbutton">Book a Visit</button>
<button id="vichallbutton">Book the Hall</button>
<button id="loginbutton"> Book a Event </button>
</div>
</div>
<!-- ABOUT SECTION -->
<section class="about-section" id="about">
<h2 class="section-title">About the Hall</h2>
<p class="section-text">
Built in the 1880s as the first town hall of Madras, Victoria Public Hall stands as a living symbol of the
city’s public spirit and cultural evolution.
Once a gathering place for reformers, artists, and citizens, it now opens its restored doors to celebrate
Chennai’s heritage.
Step inside and discover where history, architecture, and community meet in harmony.
</p>
</section>
<div class="split-container">
<div class="left-sticky">
<div class="image-stack">
<img th:src="@{images/image_townhall.jpg}" class="sticky-img active" alt="townhall">
<img th:src="@{images/image_gandhi.jpg}" class="sticky-img" alt="gandhi">
<img th:src="@{images/image_fighters.jpg}" class="sticky-img" alt="fighters">
<img th:src="@{images/image_women.jpg}" class="sticky-img" alt="women">
<img th:src="@{images/image_groups.jpg}" class="sticky-img" alt="groups">
<img th:src="@{images/image_carrom.jpg}" class="sticky-img" alt="carrom">
<img th:src="@{images/image_village.jpg}" class="sticky-img" alt="village">
</div>
</div>
<div class="right-content">
<div class="text-block active" data-index="0" style="background: #06585C">
<!-- <h1>01</h1>-->
<h2>The Birth of The Town Hall</h2>
<br>
<p>
It began as a dream to give Madras a hall of its own, a place where citizens could gather, speak,
and celebrate progress.
Born from public will and civic pride, this red-brick monument became the heartbeat of a growing
city.
Come discover where Chennai’s civic story first took shape.
</p>
</div>
<div class="text-block" data-index="1" style="background: #04356E">
<!-- <h1>02</h1>-->
<h2>Prominent Speakers</h2> <br>
<p>
Gandhi, Vivekananda, and Bharathiyar spoke here, Not just to an Audience, But to history itself.
Step inside the hall that echoed with the sound of change.
</p>
</div>
<div class="text-block" data-index="2" style="background:#836C12 ">
<!-- <h1>03</h1>-->
<h2>The Rise of Justice Party</h2> <br>
<p>
Here, a movement was born.
The Justice Party took its first stand in this very hall, calling for equality, self-respect, and
representation.
Witness where Tamilnadu’s political awakening began.
</p>
</div>
<div class="text-block" data-index="3" style="background: #612E49">
<!-- <h1>04</h1>-->
<h2>Advent of Theatre</h2> <br>
<p>
The lights dimmed, the curtains rose and a city found its stage.
From powerful dramas to the earliest film screenings, Victoria Public Hall became the cradle of
storytelling in Madras.
Come see where theatre breathed life into cinema itself.
</p>
</div>
<div class="text-block" data-index="4" style="background:#612E2E ">
<!-- <h1>05</h1>-->
<h2>Echoes of Melody</h2> <br>
<p>
Before concert halls and auditoriums, there was this place.
Here, Madras first found its music and its voice. Between songs and speeches,
this stage witnessed revolutions, reforms, and rare performances that shaped the city’s spirit.
Step in to hear what history still hums.
</p>
</div>
<div class="text-block" data-index="5" style="background: #615A2E">
<!-- <h1>06</h1>-->
<h2>From Halls to Arenas:<br>
The Birth of Chennai’s
Sporting Spirit</h2> <br>
<p>
Few know that Madras’s love for sport began here. Within and around Victoria Public Hall, Cue
Sports, Tennis, and Tournaments took root, shaping the city’s Athletic spirit.
Discover how a Civic hall Became Chennai’s Earliest Arena of Energy, Competition, and Pride.
</p>
</div>
<div class="text-block" data-index="6" style="background: #57612E">
<!-- <h1>07</h1>-->
<h2>Wheels of Time:<br>
How Chennai Learned
to Move</h2> <br>
<p>
Wheels turned, sails lifted, and tracks were laid and the city began to move.
From catamarans on quiet waters to trams gliding past <b>Victoria Public Hall</b> ,
Every journey tells a story of change. Step into this gallery to trace how Chennai travelled through
time,
From hoofbeats to high-speed rails.
</p>
</div>
</div>
</div>
<!--new visit card section -->
<section class="info-cards-section">
<h2 class="visit-title">Visit</h2>
<p class="visit-subtitle">Plan your trip with ease.</p>
<div class="row row-1">
<div class="card red">
<div class="icon"><i class="fa-solid fa-ticket"></i></div>
<h3>Hours & Tickets</h3>
<p>Sunday - Saturday: 8 AM to 6 PM <br>
Tuesday: Victoria Public Hall is closed</p>
</div>
<div class="card olive">
<div class="icon"><i class="fa-solid fa-route"></i></div>
<h3>Getting Here</h3>
<p>Located beside Ripon Building, EVR Periyar Salai Chennai - 600 003</p>
<a class="book-btn" target="_blank" href="https://maps.app.goo.gl/vgoEuimqRLXMgHzB7?g_st=ipc">
Open in Google Maps
</a>
</div>
<div class="card teal">
<div class="icon"><i class="fa-solid fa-users"></i></div>
<h3>Group Visits</h3>
<p>Open to Schools, Colleges, Organizations, Corporate Teams and Other Groups.</p>
</div>
<div class="card dark-blue">
<div class="icon"><i class="fa-solid fa-location-dot"></i></div>
<h3>Amenities</h3>
<ul class="amenities-list">
<li>Activity Centres</li>
<li>Restrooms</li>
<li>Elevators</li>
<li>Water Stations</li>
<li>Cafe for refreshments</li>
</ul>
</div>
</div>
<div class="button-wrapper">
<button class="visit-outline-btn" id="visitbutton">Book a Visit</button>
</div>
</section>
<section class="visit-gallery-section">
<h2 class="visit-title">Gallery</h2>
<div class="gallery-container-wrapper">
<!-- Loader OVER gallery -->
<div id="galleryLoader" class="gallery-loader">
<div class="spinner"></div>
</div>
<!-- Gallery Images -->
<div class="gallery-container" id="galleryContainer"></div>
</div>
<div class="gallery-wrapper">
<div class="arrows">
<button class="arrow-left" id="prevBtn">
<i class="fa-solid fa-arrow-left"></i>
</button>
<button class="arrow-right" id="nextBtn">
<i class="fa-solid fa-arrow-right"></i>
</button>
</div>
</div>
</section>
<!-- IMAGE POPUP MODAL -->
<div id="imgModal" class="img-modal">
<span class="close-modal">&times;</span>
<img class="modal-content" id="modalImg">
</div>
<section class="baimages" style="padding: 20px 20px;">
<h2 class="visit-title">Restoration</h2>
<p class="visit-subtitle">Plan your trip with ease.</p>
<div class="img-comp-container">
<div class="img-comp-img">
<img th:src="@{images/after.jpg}">
</div>
<div class="img-comp-img img-comp-overlay">
<img th:src="@{images/before.jpg}">
</div>
</div>
</section>
<div class="scroll-top" onclick="scrollToTop()">
<i class="fa-solid fa-arrow-up"></i>
</div>
<!--Footer-->
<footer class="text-center text-white" style="background-color:rgb(21,69,93); font-size: medium">
<!-- Grid container -->
<div class="container p-2">
<section style="text-align: center;color: white">
<p>
Victoria Public Hall Registration &copy; <span style="color: white;"
data-toggle="year-copy"></span>Greater Chennai Corporation
</p>
<button class="visit-btn desktop-book mt-2" style="text-align: center" id="officialbtn"> Official login </button>
</section>
<!-- Section: Text -->
</div>
<!-- Grid container -->
</footer>
<script>
function toggleMenu() {
document.getElementById("mobileMenu").classList.toggle("active");
}
document.querySelectorAll('#mobileMenu a').forEach(link => {
link.addEventListener('click', () => {
document.getElementById("mobileMenu").classList.remove("active");
});
});
document.getElementById("hamburger").addEventListener("click", function () {
document.getElementById("navMenu").classList.toggle("active");
});
let scrollHandler = null;
function initScrollSync() {
const textBlocks = document.querySelectorAll('.text-block');
const images = document.querySelectorAll('.sticky-img');
scrollHandler = () => {
let activeIndex = 0;
const windowHeight = window.innerHeight;
textBlocks.forEach((block, index) => {
const rect = block.getBoundingClientRect();
if (rect.top <= windowHeight * 0.5 && rect.bottom >= windowHeight * 0.5) {
activeIndex = index;
}
});
images.forEach((img, idx) => {
img.classList.toggle('active', idx === activeIndex);
});
textBlocks.forEach((block, idx) => {
block.classList.toggle('active', idx === activeIndex);
});
};
window.addEventListener("scroll", scrollHandler);
scrollHandler();
}
function destroyScrollSync() {
if (scrollHandler) {
window.removeEventListener("scroll", scrollHandler);
}
}
function setupMobileBlocks() {
const textBlocks = document.querySelectorAll(".text-block");
const images = document.querySelectorAll(".sticky-img");
if (window.innerWidth <= 1024) {
destroyScrollSync(); // disable desktop scroll sync
textBlocks.forEach((block, index) => {
// already added → skip
if (block.querySelector(".mobile-img")) return;
const wrapper = document.createElement("div");
wrapper.classList.add("mobile-img");
const img = document.createElement("img");
img.src = images[index].src;
wrapper.appendChild(img);
block.prepend(wrapper);
});
} else {
// Remove mobile images when returning to desktop
document.querySelectorAll(".mobile-img").forEach(el => el.remove());
// Enable scroll sync again
initScrollSync();
}
}
let resizeTimer;
window.addEventListener("resize", () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
setupMobileBlocks();
}, 150);
});
function scrollToTop() {
window.scrollTo({ top: 0, behavior: "smooth" });
}
window.addEventListener("scroll", () => {
const scrollBtn = document.querySelector(".scroll-top");
if (window.scrollY > 300) {
scrollBtn.classList.add("show");
} else {
scrollBtn.classList.remove("show");
}
});
document.getElementById("registerbtn")?.addEventListener("click", function () {
window.location.href = "/victoriapublichall/register";
});
document.getElementById("visitbutton")?.addEventListener("click", function () {
window.location.href = "/victoriapublichall/register";
});
document.getElementById("vichallbutton")?.addEventListener("click", function () {
window.location.href = "https://gccservices.in/victoriahallbooking";
});
document.getElementById("loginbtn")?.addEventListener("click", function () {
// window.open("/victoriapublichall/adminlogin", "_blank");
window.location.href = "https://gccservices.in/victoriapublichallevent/";
});
document.getElementById("officialbtn")?.addEventListener("click", function () {
window.location.href = "/victoriapublichall/adminlogin";
});
document.getElementById("registerbutton")?.addEventListener("click", function () {
window.location.href = "/victoriapublichall/register";
});
document.getElementById("loginbutton")?.addEventListener("click", function () {
// window.open("/victoriapublichall/adminlogin", "_blank");
window.location.href = "https://gccservices.in/victoriapublichallevent/";
});
function initComparisons() {
var x = document.getElementsByClassName("img-comp-overlay");
for (let i = 0; i < x.length; i++) {
compareImages(x[i]);
}
function compareImages(img) {
let slider, clicked = 0, w, h;
w = img.offsetWidth;
h = img.offsetHeight;
img.style.width = (w / 2) + "px";
slider = document.createElement("DIV");
slider.setAttribute("class", "img-comp-slider");
img.parentElement.insertBefore(slider, img);
slider.style.top = (h / 2) - (slider.offsetHeight / 2) + "px";
slider.style.left = (w / 2) - (slider.offsetWidth / 2) + "px";
slider.addEventListener("mousedown", slideReady);
window.addEventListener("mouseup", slideFinish);
slider.addEventListener("touchstart", slideReady);
window.addEventListener("touchend", slideFinish);
function slideReady(e) {
e.preventDefault();
clicked = 1;
window.addEventListener("mousemove", slideMove);
window.addEventListener("touchmove", slideMove);
}
function slideFinish() { clicked = 0; }
function slideMove(e) {
if (!clicked) return false;
let pos = getCursorPos(e);
if (pos < 0) pos = 0;
if (pos > w) pos = w;
slide(pos);
}
function getCursorPos(e) {
e = (e.changedTouches) ? e.changedTouches[0] : e;
let rect = img.getBoundingClientRect();
let x = e.pageX - rect.left - window.pageXOffset;
return x;
}
function slide(x) {
img.style.width = x + "px";
slider.style.left = img.offsetWidth - (slider.offsetWidth / 2) + "px";
}
}
}
function resetComparisonSlider() {
document.querySelectorAll(".img-comp-slider").forEach(el => el.remove());
document.querySelectorAll(".img-comp-overlay").forEach(img => {
img.style.width = "100%";
});
}
window.addEventListener("resize", function () {
resetComparisonSlider();
initComparisons();
});
initComparisons();
setupMobileBlocks();
const images = [
"/victoriapublichall/images/gallery1.JPG",
"/victoriapublichall/images/gallery2.JPG",
"/victoriapublichall/images/gallery3.JPG",
"/victoriapublichall/images/gallery4.JPG",
"/victoriapublichall/images/gallery2.JPG",
"/victoriapublichall/images/gallery3.JPG",
"/victoriapublichall/images/gallery4.JPG",
"/victoriapublichall/images/gallery1.JPG"
];
let index = 0;
const container = document.getElementById("galleryContainer");
const loader = document.getElementById("galleryLoader");
const prevBtn = document.getElementById("prevBtn");
const nextBtn = document.getElementById("nextBtn");
// ---- FUNCTION: Update arrow buttons ----
function updateArrows() {
prevBtn.disabled = index === 0;
nextBtn.disabled = index + 4 >= images.length;
// Add visual effect
prevBtn.style.opacity = prevBtn.disabled ? "0.5" : "1";
nextBtn.style.opacity = nextBtn.disabled ? "0.5" : "1";
}
// ---- FUNCTION: Load Images with Loader ----
function loadImages() {
container.innerHTML = "";
loader.style.display = "flex"; // Show Loader (flex keeps it centered)
let leftImg = images[index];
let midTop = images[index + 1];
let midBottom = images[index + 2];
let rightImg = images[index + 3];
const imageList = [leftImg, midTop, midBottom, rightImg].filter(src => src);
let loadedCount = 0;
function checkAllLoaded() {
loadedCount++;
if (loadedCount === imageList.length) {
loader.style.display = "none"; // Hide loader
enableImageClick();
}
}
// Build HTML
container.innerHTML = `
<div class="gallery-left">
<img src="${leftImg || ''}" class="g-img"/>
</div>
<div class="gallery-middle">
<img src="${midTop || ''}" class="g-img"/>
<img src="${midBottom || ''}" class="g-img"/>
</div>
<div class="gallery-right">
<img src="${rightImg || ''}" class="g-img"/>
</div>
`;
// Track image loading
document.querySelectorAll(".g-img").forEach(img => {
img.onload = checkAllLoaded;
img.onerror = checkAllLoaded;
});
updateArrows();
}
// ---- NEXT BUTTON ----
nextBtn.addEventListener("click", () => {
if (index + 4 < images.length) {
index += 4;
loadImages();
}
});
// ---- PREVIOUS BUTTON ----
prevBtn.addEventListener("click", () => {
if (index - 4 >= 0) {
index -= 4;
loadImages();
}
});
// ---- MODAL ----
const modal = document.getElementById("imgModal");
const modalImg = document.getElementById("modalImg");
const closeBtn = document.querySelector(".close-modal");
function enableImageClick() {
const imgs = document.querySelectorAll("#galleryContainer img");
imgs.forEach(img => {
img.style.cursor = "pointer";
img.addEventListener("click", () => {
modal.style.display = "block";
modalImg.src = img.src;
});
});
}
closeBtn.onclick = () => modal.style.display = "none";
modal.onclick = (e) => {
if (e.target === modal) modal.style.display = "none";
};
loadImages();
</script>
</body>
</html>